> ## Documentation Index
> Fetch the complete documentation index at: https://chart-spec.enchor.us/llms.txt
> Use this file to discover all available pages before exploring further.

# Syntax

> The structure of a .chart file: its encoding, sections, lines, and events.

A `.chart` file is text, divided into named sections. Each section holds one entry per line:

```text theme={null}
[Song]
{
  Name = "Song Name"
  Resolution = 192
}
[SyncTrack]
{
  0 = TS 4
  0 = B 120000
}
[Events]
{
  0 = E "section Intro"
}
[ExpertSingle]
{
  0 = N 0 0
  192 = N 1 96
}
```

## Encoding

**Recommended:** UTF-8, with or without a byte order mark. A file may also be UTF-16 or UTF-32, with a byte order mark.

A scanner decodes a file by its byte order mark. It checks the marks in this order, so a file that starts with `FF FE 00 00` is UTF-32, not UTF-16:

| The file starts with | Encoding |
| - | - |
| `00 00 FE FF` | UTF-32, big-endian |
| `FF FE 00 00` | UTF-32, little-endian |
| `FF FE` | UTF-16, little-endian |
| `FE FF` | UTF-16, big-endian |
| `EF BB BF` | UTF-8 |
| Anything else | UTF-8 if the whole file is valid UTF-8, and ISO-8859-1 otherwise |

**Required:** after a byte order mark, text that is valid in that encoding.

**Required:** no other byte order mark, such as UTF-7's, `2B 2F 76`.

**Edge case:** ISO-8859-1 reads each byte as the character with the same number. Bytes `80` to `9F` are control characters, not the characters Windows-1252 gives them, such as `€`.

## Sections

A section is a name in square brackets on its own line, then a body between curly brackets, each on its own line:

```text theme={null}
[ExpertSingle]
{
  ...
}
```

* **The name** is every character between `[` and `]`, as written. Names are case-sensitive.
* **The `{`** is alone on the line after the name.
* **The `}`** is alone on the section's last line, and is the section's only `}`.
* **Between sections**, a file holds only blank lines.

### Section names

| Name | Holds | |
| - | - | - |
| `Song` | The resolution and the song's metadata. See [\[Song\]](/chart/song) | **Required**, first |
| `SyncTrack` | Tempo markers and time signatures. See [\[SyncTrack\]](/chart/sync-track) | **Required**, second |
| `Events` | Practice sections, lyrics, and other events for the whole song. See [\[Events\]](/chart/events) | |
| An instrument and difficulty, such as `ExpertSingle` | One track's notes and phrases. See [Instrument sections](/chart/instrument-sections) | |

* `Events` and the instrument sections follow `SyncTrack`, in any order.
* **Required:** each section name once.

## Lines

* A line ends at a line feed, or at a carriage return followed by a line feed. A carriage return alone doesn't end a line. **Recommended:** a carriage return and a line feed.
* **Recommended:** each entry indented with two spaces, and no blank lines inside a section.
* A `.chart` file has no comments.

**Edge case: spaces and tabs.** A scanner ignores spaces and tabs at the start and the end of every line, in every section, so `0 = TS 4 ` with a space at the end is `0 = TS 4`. An exporter ends each line with its last value.

## Events

Every entry of the `SyncTrack`, `Events`, and instrument sections is an event:

```text theme={null}
<tick> = <type> <value> <value>...
```

* **Tick:** the position, written in the digits `0` to `9`, without a sign.
* **Type:** a code of one or two capital letters, such as `N` or `TS`.
* **Values:** whole numbers in the digits `0` to `9`, or one text value in an `E` event. Each type takes a set number of values, and an event has exactly that number. `TS` alone takes one or two: see [Time signatures](/chart/sync-track#time-signatures).
* **Spaces:** exactly one space comes before and after the `=`, after the type, and between values.
* **Required:** every event in exactly this form.

Each section holds only some types of event:

| Section | Types |
| - | - |
| `SyncTrack` | `B` tempo, `TS` time signature, and `A` tempo anchor, which is [ignored](#ignored) |
| `Events` | `E` text event, and `H` from older charts, which is [ignored](#ignored) |
| Instrument | `N` note, `S` phrase, and `E` text event |

**Required:** in `SyncTrack` and `Events`, only the types the table gives them.

A scanner ignores a note or phrase value that has no meaning on its instrument, and an event of another type in an instrument section.

### Tick order

**Required:** within a section, each event's tick the same as the previous event's or later:

```text theme={null}
[ExpertSingle]
{
  0 = N 0 0
  0 = N 1 0
  192 = N 2 0
}
```

Events at the same tick may be written in any order. **Recommended:** at one tick, notes, then phrases, then text events in an instrument section, and the time signature before the tempo marker in `SyncTrack`.

## Named entries

Each entry of the `Song` section names a value:

```text theme={null}
<key> = <value>
```

* The key is followed by exactly one space, `=`, and one space.
* **Required:** each key once in the section.
* Text values are written in quotation marks: `Name = "Song Name"`. Numbers are written without them: `Resolution = 192`.
* **Required:** every entry in exactly this form.

[\[Song\]](/chart/song) lists the keys.

**Edge case: white space in an entry.** A scanner removes white space from both ends of the key and of the value, and from both ends of the text inside the quotation marks, so `Name = " Song Name "` is `Song Name`. White space is every character that .NET counts as white space, such as a tab or a no-break space, U+00A0, but not a byte order mark, U+FEFF.

## Text

Text events are written differently in the two kinds of section:

* **In `Events`**, the text is in quotation marks: `0 = E "section Intro"`.
* **In an instrument section**, the text has no quotation marks: `768 = E solo`.

A `.chart` file has no escape characters. Text can't hold a line break, and a quotation mark inside the text is part of it.

**Required:** no quotation marks around the text in an instrument section.

**Edge case: brackets in `Events`.** A scanner removes spaces around the text, then one `[` at its start and one `]` at its end, so `0 = E "[section Intro]"` means the same as `0 = E "section Intro"`. Older charts write the brackets. An exporter writes the text without them. A bracket anywhere else is part of the text, as in `E "section Verse [2]"`.

## Ignored

* **`A` tempo anchors** in `SyncTrack`, such as `0 = A 0`. Chart editors such as Moonscraper write them to hold a tempo marker at a time in the audio. Games ignore them. An exporter may keep them.
* **`H` events** in `Events`, from older charts.
* **A section with any other name.**

## Invalid forms

<Accordion title="Bytes that aren't valid in the encoding of the byte order mark">
  Clone Hero refuses the file. A scanner that reads it reads each byte sequence that isn't valid as the replacement character, U+FFFD, and takes no metadata from `[Song]`, as scan-chart does. scan-chart keeps the bytes as they are when saving.
</Accordion>

<Accordion title="2B 2F 76, the mark of UTF-7, at the start of the file">
  Clone Hero refuses the file. A scanner that reads it reads it as a file without a byte order mark, and takes no metadata from `[Song]`, as scan-chart does.
</Accordion>

<Accordion title="Events out of tick order">
  Clone Hero refuses a file whose events go back in time in any section, and YARG's song list refuses the file too. A scanner that reads it reads each section's events in tick order, keeping the file's order at one tick, as scan-chart does. YARG's chart loader sorts the instrument sections, and drops each `SyncTrack` or `Events` line that goes back in time. scan-chart reports `unsortedChartLines`, and saving puts the lines in tick order.
</Accordion>

<Accordion title="Two tempo markers, or two time signatures, at one tick in SyncTrack">
  Both games use the later one, and so does scan-chart. Saving removes the earlier one, which changes no hash.
</Accordion>

<Accordion title="A section name that appears twice">
  A scanner reads the first section with each name, and ignores the rest, as scan-chart does. Clone Hero reads the first instrument section with that name, but joins every `[Song]`, `[SyncTrack]` and `[Events]` section into one, and the last `Resolution` counts. YARG's chart loader reads the first `[Song]` and `[SyncTrack]`, and joins the `[Events]` sections and the instrument sections of one name. Saving with scan-chart removes the others.
</Accordion>

<Accordion title="No Song section">
  A scanner reads the file with a resolution of 192, as it reads a `[Song]` section without `Resolution`. scan-chart's saving adds a `[Song]` section with `Resolution = 192`.
</Accordion>

<Accordion title="No SyncTrack section">
  A scanner refuses the file, as YARG's chart loader and scan-chart do. From its code, Clone Hero plays the chart at 120 BPM in 4/4.
</Accordion>

<Accordion title="Song not first, or SyncTrack not second">
  A scanner reads `[Song]` and `[SyncTrack]` wherever they are, and takes the song's metadata from the file's first section, whatever its name, as Clone Hero and scan-chart do. YARG's chart loader refuses the file, and its song list reads `[Song]` only when the file starts with it. Saving with scan-chart puts them first.
</Accordion>

<Accordion title="An event of another type in SyncTrack or Events">
  Clone Hero refuses a file with one in `SyncTrack` or `Events`. A scanner that reads it ignores the event, as YARG and scan-chart do. scan-chart keeps it, and writes it back as it is.
</Accordion>

<Accordion title="A quoted text event in an instrument section">
  Clone Hero, YARG and scan-chart read `768 = E "solo"` as a solo. The same holds for `soloend`, `mix` and `ld_range_shift` events. scan-chart reports `quotedChartTrackEvent`, and saving removes the quotation marks.
</Accordion>

<Accordion title="Other spellings, such as a missing = or extra spaces">
  Games read these differently, or not at all. A scanner reads such a line as Clone Hero does where Clone Hero loads the file, and otherwise by its probable meaning, as scan-chart does. [Nonstandard files](/scan-chart/nonstandard-files) lists them. Saving with scan-chart writes the standard spelling.
</Accordion>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.