Please create an account or Login! Have fun!

DAT: Difference between revisions

Jump to navigation Jump to search
14,692 bytes added ,  23 January 2022
→‎5: Cloner linkage: never mind i'm dumb
m (Tylersontag moved page dAT to DAT over redirect: revert)
(→‎5: Cloner linkage: never mind i'm dumb)
(11 intermediate revisions by 4 users not shown)
Line 1: Line 1:
A '''DAT''' file (having the extension .dat) is the file format which Chip's Challenge [[level set]]s are commonly stored in.
In the context of [[Chip's Challenge]], '''DAT''' or <code>.dat</code> is the file format which Chip's Challenge 1 [[level set]]s are commonly stored in, named for the <code>CHIPS.DAT</code> file containing the levels for [[MSCC]].  The <code>.dat</code> extension is short for "data" and commonly used on data files with ad-hoc formats; it is not specific to Chip's Challenge.


Since the release of [[CCTools]], level sets are sometimes stored in '''CCL''' files (having the extension .ccl, which stands for [[Chip's Challenge]] level set). For people who have [[ChipEdit]], which does not provide a way to open CCL files "normally", simply change the extension back to .dat, or type the file name manually when in the Open dialog.
Since the release of [[CCTools]], the format is sometimes referred to as '''CCL''' or <code>.ccl</code>, short for "[[Chip's Challenge]] levels". For people who have [[ChipEdit]], which does not provide a way to open CCL files "normally", simply change the extension back to .dat, or type the file name manually when in the Open dialog.


==External Links==
== Structure ==


[http://www.seasip.info/ccfile.html Explanation of the CHIPS.DAT format]
The format is a relatively simple binary structure. All fields are little-endian.


{{stub}}
=== File header ===
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$00
|4
|Magic number, identifying the file format.  MSCC will reject the file if this is not <code>$0002AAAC</code>.  Tile World will also accept <code>$0102AAAC</code> as meaning a level set using [[Ruleset#Lynx|Lynx rules]].  The [[pgchip]] modification expects <code>$0003aaac</code>.
|-
|$04
|2
|Number of levels in the file.
|}
 
Levels begin at offset $06, immediately following the header.
 
=== Level structure ===
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$00
|2
|Length of this level in bytes, '''not''' including this field.
|-
|$02
|2
|Level number.  <!-- XXX what if this doesn't match the level order?  is this only used in the UI? -->
|-
|$04
|2
|Time limit, in seconds.  Zero indicates the level is untimed.  Every official version of the game has a three-digit timer, so values over 999 are uncommon.
|-
|$06
|2
|Required number of [[chip]]s.  This may be less than the number of chips in the level, in which case the extras will be optional, or it may be more, in which case the [[chip socket]] will be impossible to open.
|-
|$08
|2
|Unclear.  Must always be 0 or 1.  The original levels all have this set to 1.  Possibly once indicated whether the level data was compressed or not.
|-
|$0a
|2
|Length of top layer, in bytes.
|-
|$0c
|varies
|Contents of top layer; see [[#Level contents|below]].
|-
|varies
|2
|Length of bottom layer, in bytes.
|-
|varies
|varies
|Contents of bottom layer; see [[#Level contents|below]].
|-
|varies
|2
|Total length of all metadata chunks, in bytes; see [[#Level metadata chunks|below]].  MSCC crashes if there are more than 1152 bytes of metadata.
|-
|varies
|varies
|Zero or more metadata chunks; see [[#Level metadata chunks|below]].
|}
 
=== Level contents ===
 
The level is encoded as two layers, top and bottom.  Every CC1 level is 32×32, so each layer contains exactly 1024 tiles.  If a cell only contains one tile, it should be placed on the ''top'' layer, and the corresponding tile in the ''bottom'' layer should simply be floor.  (Another way to think of this is that the floor byte, <code>$00</code>, represents ''nothing'', but that every cell implicitly has floor underneath.)
 
''Any'' tile may appear on either layer, which allows for a vast number of strange combinations.  However, within the original rules of the game, the only valid combinations are a lone static tile, or a static tile with a movable object on top.  Anything else (including some otherwise intuitive possibilities that would work in [[Chip's Challenge 2]], like a key on gravel) is an [[invalid tile]], will be rejected by Tile World's Lynx mode, and may behave unexpectedly.
 
A layer is a simple stream of bytes representing the tiles in [[reading order]].  A lone byte indicates a particular tile according to the encoding below.  A <code>$FF</code> byte indicates simple run-length encoding, where the next two bytes are the number of copies and the byte to repeat.  The sequence `00 FF 0A 01 00` thus describes twelve tiles: a floor tile, a span of ten walls, and another floor tile.
 
==== Tile encoding ====
 
The tile encoding exactly matches the arrangement of sprites in the [[:File:Color_Tileset.gif|MSCC tileset]].
 
Values of <code>$70</code> and above are used internally for graphical transparency.  <!-- XXX what happens if you use them? -->
 
{| class="wikitable" border="1"
!
!<code>$0_</code>
!<code>$1_</code>
!<code>$2_</code>
!<code>$3_</code>
!<code>$4_</code>
!<code>$5_</code>
!<code>$6_</code>
|-
!<code>$_0</code>
|[[Image:Floor.png]] [[Floor]]
|[[Image:Clone block S.png]] [[Clone block]] (S) <ref name="clone-block">Must be used when creating a block cloner, to indicate the direction of cloning.  A clone block placed on its own won't be pushable.</ref>
|''unused'' <ref>Used internally as the [[overlay buffer|Combination]] tile.</ref>
|[[Image:Thin wall SE.png]] [[Thin wall]] (SE)
|[[Image:Bug N.png]] [[Bug]] (N)
|[[Image:Glider N.png]] [[Glider]] (N)
|[[Image:Paramecium NS.png]] [[Paramecium]] (N)
|-
!<code>$_1</code>
|[[Image:Wall.png]] [[Wall]]
|[[Image:Clone block E.png]] [[Clone block]] (E) <ref name="clone-block"/>
|[[Image:Thief.png]] [[Thief]]
|[[Image:Clone machine.png]] [[Cloner]]
|[[Image:Bug W.png]] [[Bug]] (W)
|[[Image:Glider W.png]] [[Glider]] (W)
|[[Image:Paramecium WE.png]] [[Paramecium]] (W)
|-
!<code>$_2</code>
|[[Image:Computer chip.png]] [[Computer chip]]
|[[Image:Force floor N.png]] [[Force floor]] (N)
|[[Image:Socket.png]] [[Chip socket]]
|[[Image:Force floor Random.png]] [[Random force floor]]
|[[Image:Bug S.png]] [[Bug]] (S)
|[[Image:Glider S.png]] [[Glider]] (S)
|[[Image:Paramecium NS.png]] [[Paramecium]] (S)
|-
!<code>$_3</code>
|[[Image:Water.png]] [[Water]]
|[[Image:Force floor E.png]] [[Force floor]] (E)
|[[Image:Green button.png]] [[Green button]]
|[[Image:Drowned Chip.png]] [[Drowned Chip]] <ref name="invalid">This tile is an [[invalid tile|implementation detail]], not an intended game element.</ref>
|[[Image:Bug E.png]] [[Bug]] (E)
|[[Image:Glider E.png]] [[Glider]] (E)
|[[Image:Paramecium WE.png]] [[Paramecium]] (E)
|-
!<code>$_4</code>
|[[Image:Fire.png]] [[Fire]]
|[[Image:Force floor W.png]] [[Force floor]] (W)
|[[Image:Red button.png]] [[Red button]]
|[[Image:Chip in Fire.png]] [[Burned Chip]] <ref name="invalid"/>
|[[Image:Fireball.png]] [[Fireball]] (N)
|[[Image:Teeth N.png]] [[Teeth]] (N)
|[[Image:Blue key.png]] [[Blue key]]
|-
!<code>$_5</code>
|[[Image:Invisible wall.png]] [[Invisible wall]]
|[[Image:Exit.png]] [[Exit]]
|[[Image:Toggle wall Closed.png]] [[Toggle wall]]
|[[Image:Burned Chip.png]] [[Burned Chip]] <ref name="invalid"/>
|[[Image:Fireball.png]] [[Fireball]] (W)
|[[Image:Teeth W.png]] [[Teeth]] (W)
|[[Image:Red key.png]] [[Red key]]
|-
!<code>$_6</code>
|[[Image:Thin wall N.png]] [[Thin wall]] (N)
|[[Image:Blue lock.png]] [[Blue lock]]
|[[Image:Toggle wall Open.png]] [[Toggle wall|Toggle floor]]
|''unused'' <ref name="unused">This byte does not correspond to any defined tile, but acts like an invisible wall.</ref>
|[[Image:Fireball.png]] [[Fireball]] (S)
|[[Image:Teeth S.png]] [[Teeth]] (S)
|[[Image:Green key.png]] [[Green key]]
|-
!<code>$_7</code>
|[[Image:Thin wall W.png]] [[Thin wall]] (W)
|[[Image:Red lock.png]] [[Red lock]]
|[[Image:Brown button.png]] [[Brown button]]
|''unused'' <ref name="unused"/>
|[[Image:Fireball.png]] [[Fireball]] (E)
|[[Image:Teeth E.png]] [[Teeth]] (E)
|[[Image:Yellow key.png]] [[Yellow key]]
|-
!<code>$_8</code>
|[[Image:Thin wall S.png]] [[Thin wall]] (S)
|[[Image:Green lock.png]] [[Green lock]]
|[[Image:Blue button.png]] [[Blue button]]
|''unused'' <ref name="unused"/> <ref>In the pgchip hack, this byte is used to indicate an [[ice block]].</ref>
|[[Image:Pink ball.png]] [[Ball]] (N)
|[[Image:Walker NS.png]] [[Walker]] (N)
|[[Image:Flippers.png]] [[Flippers]]
|-
!<code>$_9</code>
|[[Image:Thin wall E.png]] [[Thin wall]] (E)
|[[Image:Yellow lock.png]] [[Yellow lock]]
|[[Image:Teleport.png]] [[Teleporter]]
|[[Image:Chip in Exit.png]] [[Fake exit]] <ref name="invalid"/>
|[[Image:Pink ball.png]] [[Ball]] (W)
|[[Image:Walker WE.png]] [[Walker]] (W)
|[[Image:Fire boots.png]] [[Fire boots]]
|-
!<code>$_a</code>
|[[Image:Block.png]] [[Dirt block]]
|[[Image:Ice NW.png]] [[Ice corner]] (NW)
|[[Image:Bomb.png]] [[Bomb]]
|[[Image:Exit2.png]] [[Fake exit]] <ref name="invalid"/>
|[[Image:Pink ball.png]] [[Ball]] (S)
|[[Image:Walker NS.png]] [[Walker]] (S)
|[[Image:Ice skates.png]] [[Ice skates]]
|-
!<code>$_b</code>
|[[Image:Dirt.png]] [[Dirt]]
|[[Image:Ice NE.png]] [[Ice corner]] (NE)
|[[Image:Trap.png]] [[Trap]]
|[[Image:Exit3.png]] [[Fake exit]] <ref name="invalid"/>
|[[Image:Pink ball.png]] [[Ball]] (E)
|[[Image:Walker WE.png]] [[Walker]] (E)
|[[Image:Suction boots.png]] [[Suction boots]]
|-
!<code>$_c</code>
|[[Image:Ice.png]] [[Ice]]
|[[Image:Ice SE.png]] [[Ice corner]] (SE)
|[[Image:Hidden wall.png]] [[Hidden wall]]
|[[Image:Swimming Chip N.png]] [[Swimming Chip]] (N)  <ref name="invalid"/>
|[[Image:Tank N.png]] [[Tank]] (N)
|[[Image:Blob.png]] [[Blob]] (N)
|[[Image:Chip N.png]] [[Chip]] (N)
|-
!<code>$_d</code>
|[[Image:Force floor S.png]] [[Force floor]] (S)
|[[Image:Ice SW.png]] [[Ice corner]] (SW)
|[[Image:Gravel.png]] [[Gravel]]
|[[Image:Swimming Chip W.png]] [[Swimming Chip]] (W) <ref name="invalid"/>
|[[Image:Tank W.png]] [[Tank]] (W)
|[[Image:Blob.png]] [[Blob]] (W)
|[[Image:Chip W.png]] [[Chip]] (W)
|-
!<code>$_e</code>
|[[Image:Clone block N.png]] [[Clone block]] (N) <ref name="clone-block"/>
|[[Image:Blue wall.png]] Fake [[blue wall]]
|[[Image:Recessed wall.png]] [[Recessed wall]]
|[[Image:Swimming Chip S.png]] [[Swimming Chip]] (S) <ref name="invalid"/>
|[[Image:Tank S.png]] [[Tank]] (S)
|[[Image:Blob.png]] [[Blob]] (S)
|[[Image:Chip S.png]] [[Chip]] (S)
|-
!<code>$_f</code>
|[[Image:Clone block W.png]] [[Clone block]] (W) <ref name="clone-block"/>
|[[Image:Blue wall.png]] Real [[blue wall]]
|[[Image:Hint.png]] [[Hint]]
|[[Image:Swimming Chip E.png]] [[Swimming Chip]] (E) <ref name="invalid"/>
|[[Image:Tank E.png]] [[Tank]] (E)
|[[Image:Blob.png]] [[Blob]] (E)
|[[Image:Chip E.png]] [[Chip]] (E)
|}
 
<references />
 
=== Level metadata chunks ===
 
Each chunk begins with a small header.
 
Because the length of a chunk is stored in a single byte, no chunk may be longer than 255 bytes.
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$00
|1
|Chunk type
|-
|$01
|1
|Chunk length in bytes, '''not''' including this two-byte header
|}
 
A level '''must''' have a title (3) and password (6).  A level intended to work under MS rules should also have [[trap]] linkage (4), [[cloner]] linkage (5), and a [[monster]] list (10), or those elements will not work.
 
Unrecognized chunk types are ignored.
 
==== 1: Time limit ====
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$02
|2
|Time limit in seconds
|}
 
This chunk is never used in the original game, since it's redundant with the time limit field in the level header.
 
==== 2: Required chips ====
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$02
|2
|Required number of chips
|}
 
This chunk is never used in the original game, since it's redundant with the required chips field in the level header.
 
==== 3: Title ====
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$02
|?
|Map title.  Must include a trailing NUL byte, and must not exceed 64 characters (including the NUL).  Should generally be ASCII, though Tile World appears to interpret this as Latin-1.  <!-- XXX what does MSCC do with a long title or byte over 128? -->
|}
 
==== 4: Trap linkage ====
 
Contains zero or more of the following structure.  As this structure is 10 bytes in size, the chunk size should be a multiple of 10, and there cannot be more than 25 trap linkages in a level.  Any given brown button may only be linked to a single trap.
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$00
|2
|x-coordinate of brown button
|-
|$02
|2
|y-coordinate of brown button
|-
|$04
|2
|x-coordinate of trap
|-
|$06
|2
|y-coordinate of trap
|-
|$08
|2
|Always zero.  Presumably a placeholder for runtime state regarding whether the trap is open or closed.
|}
 
This structure links brown buttons to traps in MSCC, where such linkage must be explicit.  If a brown button is not listed in this chunk, it will not function in MSCC.
 
Tile World in Lynx mode will ignore this structure and always connect brown buttons in [[reading order]].
 
If this chunk appears more than once, MSCC will only read the first, but Tile World will merge them all.
 
==== 5: Cloner linkage ====
 
Contains zero or more of the following structure.  As this structure is 8 bytes in size, the chunk size should be a multiple of 8, and there cannot be more than 31 cloner linkages in a level.
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$00
|2
|x-coordinate of red button
|-
|$02
|2
|y-coordinate of red button
|-
|$04
|2
|x-coordinate of cloner
|-
|$06
|2
|y-coordinate of cloner
|}
 
This structure links red buttons to cloners in MSCC, where such linkage must be explicit.  If a red button is not listed in this chunk, it will not function in MSCC.  Any given red button may only be linked to a single cloner.
 
Tile World in Lynx mode will ignore this structure and always connect red buttons in [[reading order]].
 
If this chunk appears more than once, MSCC will only read the first, but Tile World will merge them all.
 
==== 6: Password ====
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$02
|?
|Encrypted password.  Must include a trailing NUL.  Should be ASCII.  May be up to 10 characters, but generally should be 5 (4 + NUL).
|}
 
The password is encrypted trivially, by XORing every character ('''not''' including the trailing NUL) with <code>0x99</code>.
 
==== 7: Hint ====
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$02
|?
|[[Hint]] text.  Must include a trailing NUL byte, and must not exceed 128 characters (including the NUL).  Should generally be ASCII, though Tile World appears to interpret this as Latin-1.  <!-- XXX what does MSCC do with a long title or byte over 128? -->
|}
 
==== 8: Unencrypted password ====
 
This chunk is identical to chunk 6, but without the encryption.  It is never used in the original <code>CHIPS.DAT</code>, and Tile World ignores it.
 
==== 10: Monster list ====
 
Contains zero or more of the following structure.  As this structure is 2 bytes in size, the chunk size should be a multiple of 2, and there cannot be more than 127 moving monsters in a level.
 
{| class="wikitable" border="1"
!Offset
!Bytes
!Content
|-
|$00
|1
|x-coordinate of monster
|-
|$02
|1
|y-coordinate of monster
|}
 
This structure allows monsters to move in MSCC; if a monster is not listed in this chunk, it will not move.
 
Tile World in Lynx mode will ignore this structure and always allow any number of monsters to move as normal.
 
== See also ==
 
* [[C2M]], the more flexible format used in [[Chip's Challenge 2]]
 
== External Links ==
* [http://www.seasip.info/ccfile.html Explanation of the CHIPS.DAT format]
* Implementation in [[Tile World]]: [https://github.com/zrax/tworld/blob/master/series.c <code>series.c</code>] (whole file) and [https://github.com/zrax/tworld/blob/master/encoding.c <code>encoding.c</code>] (individual level)
* Implementation in [[Lexy's Labyrinth]]: [https://github.com/eevee/lexys-labyrinth/blob/master/js/format-dat.js <code>js/format-dat.js</code>]


[[Category:Terminology]]
[[Category:Terminology]]
[[Category:File formats]]
[[Category:File formats]]
Anonymous user

Navigation menu