digraph {
rankdir=LR;
node [shape=plaintext];
subgraph cluster__s3m {
label="S3m";
graph[style=dotted];
s3m__seq [label=<
pos | size | type | id |
0 | 28 | | song_name |
28 | 1 | | magic1 |
29 | 1 | u1 | file_type |
30 | 2 | | reserved1 |
32 | 2 | u2le | num_orders |
34 | 2 | u2le | num_instruments |
36 | 2 | u2le | num_patterns |
38 | 2 | u2le | flags |
40 | 2 | u2le | version |
42 | 2 | u2le | samples_format |
44 | 4 | | magic2 |
48 | 1 | u1 | global_volume |
49 | 1 | u1 | initial_speed |
50 | 1 | u1 | initial_tempo |
51 | 1b | BitsType1(BigBitEndian) | is_stereo |
51:1 | 7b | b7 | master_volume |
52 | 1 | u1 | ultra_click_removal |
53 | 1 | u1 | has_custom_pan |
54 | 8 | | reserved2 |
62 | 2 | u2le | ofs_special |
64 | 1 | Channel | channels |
repeat 32 times |
96 | num_orders | | orders |
... | 2 | InstrumentPtr | instruments |
repeat num_instruments times |
... | 2 | PatternPtr | patterns |
repeat num_patterns times |
... | 1 | ChannelPan | channel_pans |
repeat 32 times |
>];
subgraph cluster__channel_pan {
label="S3m::ChannelPan";
graph[style=dotted];
channel_pan__seq [label=<
pos | size | type | id |
0 | 2b | b2 | reserved1 |
0:2 | 1b | BitsType1(BigBitEndian) | has_custom_pan |
0:3 | 1b | BitsType1(BigBitEndian) | reserved2 |
0:4 | 4b | b4 | pan |
>];
}
subgraph cluster__pattern_cell {
label="S3m::PatternCell";
graph[style=dotted];
pattern_cell__seq [label=<
pos | size | type | id |
0 | 1b | BitsType1(BigBitEndian) | has_fx |
0:1 | 1b | BitsType1(BigBitEndian) | has_volume |
0:2 | 1b | BitsType1(BigBitEndian) | has_note_and_instrument |
0:3 | 5b | b5 | channel_num |
1 | 1 | u1 | note |
2 | 1 | u1 | instrument |
3 | 1 | u1 | volume |
4 | 1 | u1 | fx_type |
5 | 1 | u1 | fx_value |
>];
}
subgraph cluster__pattern_cells {
label="S3m::PatternCells";
graph[style=dotted];
pattern_cells__seq [label=<
pos | size | type | id |
0 | 6 | PatternCell | cells |
repeat to end of stream |
>];
}
subgraph cluster__channel {
label="S3m::Channel";
graph[style=dotted];
channel__seq [label=<
pos | size | type | id |
0 | 1b | BitsType1(BigBitEndian) | is_disabled |
0:1 | 7b | b7 | ch_type |
>];
}
subgraph cluster__swapped_u3 {
label="S3m::SwappedU3";
graph[style=dotted];
swapped_u3__seq [label=<
pos | size | type | id |
0 | 1 | u1 | hi |
1 | 2 | u2le | lo |
>];
swapped_u3__inst__value [label=<
id | value |
value | (lo | (hi << 16)) |
>];
}
subgraph cluster__pattern {
label="S3m::Pattern";
graph[style=dotted];
pattern__seq [label=<
pos | size | type | id |
0 | 2 | u2le | size |
2 | (size - 2) | PatternCells | body |
>];
}
subgraph cluster__pattern_ptr {
label="S3m::PatternPtr";
graph[style=dotted];
pattern_ptr__seq [label=<
pos | size | type | id |
0 | 2 | u2le | paraptr |
>];
pattern_ptr__inst__body [label=<
pos | size | type | id |
(paraptr * 16) | ... | Pattern | body |
>];
}
subgraph cluster__instrument_ptr {
label="S3m::InstrumentPtr";
graph[style=dotted];
instrument_ptr__seq [label=<
pos | size | type | id |
0 | 2 | u2le | paraptr |
>];
instrument_ptr__inst__body [label=<
pos | size | type | id |
(paraptr * 16) | ... | Instrument | body |
>];
}
subgraph cluster__instrument {
label="S3m::Instrument";
graph[style=dotted];
instrument__seq [label=<
pos | size | type | id |
0 | 1 | u1→InstTypes | type |
1 | 12 | | filename |
13 | ... | switch (type) | body |
... | 4 | u4le | tuning_hz |
... | 12 | | reserved2 |
... | 28 | | sample_name |
... | 4 | | magic |
>];
instrument__seq_body_switch [label=<
case | type |
:inst_types_sample | Sampled |
_ | Adlib |
>];
subgraph cluster__sampled {
label="S3m::Instrument::Sampled";
graph[style=dotted];
sampled__seq [label=<
pos | size | type | id |
0 | 3 | SwappedU3 | paraptr_sample |
3 | 4 | u4le | len_sample |
7 | 4 | u4le | loop_begin |
11 | 4 | u4le | loop_end |
15 | 1 | u1 | default_volume |
16 | 1 | u1 | reserved1 |
17 | 1 | u1 | is_packed |
18 | 1 | u1 | flags |
>];
sampled__inst__sample [label=<
pos | size | type | id |
(paraptr_sample.value * 16) | len_sample | | sample |
>];
}
subgraph cluster__adlib {
label="S3m::Instrument::Adlib";
graph[style=dotted];
adlib__seq [label=<
pos | size | type | id |
0 | 3 | | reserved1 |
3 | 16 | | _unnamed1 |
>];
}
}
}
s3m__seq:channels_type -> channel__seq [style=bold];
s3m__seq:num_orders_type -> s3m__seq:orders_size [color="#404040"];
s3m__seq:instruments_type -> instrument_ptr__seq [style=bold];
s3m__seq:num_instruments_type -> s3m__seq:instruments__repeat [color="#404040"];
s3m__seq:patterns_type -> pattern_ptr__seq [style=bold];
s3m__seq:num_patterns_type -> s3m__seq:patterns__repeat [color="#404040"];
s3m__seq:channel_pans_type -> channel_pan__seq [style=bold];
pattern_cells__seq:cells_type -> pattern_cell__seq [style=bold];
swapped_u3__seq:lo_type -> swapped_u3__inst__value [color="#404040"];
swapped_u3__seq:hi_type -> swapped_u3__inst__value [color="#404040"];
pattern__seq:size_type -> pattern__seq:body_size [color="#404040"];
pattern__seq:body_type -> pattern_cells__seq [style=bold];
pattern_ptr__seq:paraptr_type -> pattern_ptr__inst__body:body_pos [color="#404040"];
pattern_ptr__inst__body:body_type -> pattern__seq [style=bold];
instrument_ptr__seq:paraptr_type -> instrument_ptr__inst__body:body_pos [color="#404040"];
instrument_ptr__inst__body:body_type -> instrument__seq [style=bold];
instrument__seq:body_type -> instrument__seq_body_switch [style=bold];
instrument__seq_body_switch:case0 -> sampled__seq [style=bold];
instrument__seq_body_switch:case1 -> adlib__seq [style=bold];
instrument__seq:type_type -> instrument__seq:body_type [color="#404040"];
sampled__seq:paraptr_sample_type -> swapped_u3__seq [style=bold];
swapped_u3__inst__value:value_type -> sampled__inst__sample:sample_pos [color="#404040"];
sampled__seq:len_sample_type -> sampled__inst__sample:sample_size [color="#404040"];
}