Format of CHANLIST.BIN
From comaglisteditor
by Michael Schierl, 2009-11-24 - 2009-12-22
This file describes the file format of CHANLIST.BIN used by the DVB-S receiver SilverCrest SL250/2 100CI and other models of identical construction.
Contents |
Conventions
Data types
Integral types are written as u (for unsigned) followed by the (decimal) number of bytes the number consumes. All numbers are stored in little endian (Intel) format. I did not encounter any signed numbers, nor did I encounter any floating point numbers (and only very rarely fixed-point decimal numbers).
Strings are written as sz (for String Zero) followed by the (decimal) number of bytes the string consumes. If the string is shorter, it is terminated by a NUL byte (and sometimes filled with garbage after that one). If the string fills all the bytes, it is not terminated at all.
Magic values (or values I don't know the value of) are written as m followed by the number of bytes. Its value is given in the description field, either in hexadecimal (like 34 32) or as a string (like "42") or as a data type with value (like u16:12852) or as a combination of these (depending on what I think the value's type might be...).
Any other bytes (like structured described later) are prefixed by a b
Allocation maps
When looking at the file, a certain data structure repeats again and again. As it reminds me of the good old FAT file system's File Allocation Table, but on the other hand also maps a value for each record, I called this beast an "allocation map".
The purpose of an allocation map seems to be to be able to remove records without having to copy another record in place. While useful in an in-ROM file format, its use in the export file format is at least questionable.
An allocation map provides details for a list of records after the start of the map. Both the size of the records and the number of record "slots" stored in the file are stored in the allocation map. Additionally, the size of the allocation map itself is also stored in the allocation map. There are cases where there is a map of (for example) 64 entries followed by, for example, only 5 entries, of which 2 are deleted. I think this is due to the fact that only the part which is really needed (i. e. up to the last non-deleted record) is really exported, but I don't think it is a good idea for implementations to depend on this fact.
An allocation map looks like this:
Offset | Datatype | Fieldname | Description |
---|---|---|---|
0x00 | u4 | recordLength | Length of the individual records |
0x04 | u4 | totalCount | Total number of not deleted records |
0x08 | u4 | mapCount | Number of entries in the map |
0x0C | u4 | savedCount | Number of records saved in the file (including deleted ones) |
0x10 | u4 | firstDeleted | Index of the first record in the file which is deleted |
0x14 | b(mapCount) | map | The map itself (one byte for each record) |
... | b(recordLength*savedCount) | data | The records themselves; deleted records are filled with garbage or NULs |
Allocation maps below are written as am followed by the (decimal) record length. The records are usually documented elsewhere.
The map itself stores one byte for each record. Deleted records (or records after the end of the map) store 0x00, all other records store either 0x21 or 0x11. I don't really know what this flag is used for :(
Overall structure of the file
Header
Like every file, CHANLIST.BIN contains a header which is 32 bytes long:
Offset | Datatype | Fieldname | Description |
---|---|---|---|
0x00 | m4 | Magic value: 78 00 7A 71 | |
0x04 | u1 | majorFirmwareVersion | Major firmware version number, for example 03 |
0x05 | u1 | minorFirmwareVersion | Minor firmware version number, for example 08 |
0x06 | u1 | majorVersion | Major version number, usually 01 |
0x07 | u1 | minorVersion | Minor version number, usually 01 |
0x08 | sz4 | language | Language, for example "deu" |
0x0C | u2 | satelliteCount | Number of satellites |
0x0E | u2 | transponderCount | Number of transponders |
0x10 | u2 | channelCount | Number of channels (radio + TV) |
0x12 | b3 | time | Save time, one byte for hour / minute / second each |
0x15 | m1 | Padding?: 00 | |
0x16 | u2 | dateYear | Year of save date, for example 2009 |
0x18 | u1 | dateMonth | Month of save date, for example 2 for February |
0x19 | m1 | dateUnknown | Unknown, I have seen 17 (hex) and 02 (hex). Day of something? |
0x1A | u1 | dateDay | Day of save date, for example 28 |
0x1B | u1 | dateDOW | Day of week of save date, 01=Monday, 07=Sunday |
0x1C | m4 | Padding?: 00 00 00 00 |
The rest of the file consists of blocks, that start with a 8 character name each.
"Satelite" block
Contains information about satellites (like name, position, tuner configuration):
Offset | Datatype | Fieldname | Description |
---|---|---|---|
0x00 | m8 | "Satelite" | |
0x08 | m8 | Unknown: 02 00 "rj" u4:14 | |
0x10 | u4 | Unknown: Either 0 or 2 | |
0x14 | m12 | Unknown: Either u4:2 u4:2 u4:0 or u4:3 u4:3 u4:0 | |
0x20 | m4 | Unknown: 02 00 "rj" | |
0x24 | am140 | satellites | Allocation map containing data about satellites. |
There should be as many satellites allocated in that map as the number of satellites listed above. The length of the allocation map is usually 0x40.
Format of the satellite records:
Offset | Datatype | Fieldname | Description |
---|---|---|---|
0x00 | u4 | id | ID of the satellite (referenced elsewhere?) |
0x04 | sz32 | name | Satellite name |
0x24 | m4 | Unknown: 01 00 00 00 | |
0x28 | u4 | orbitalDegree | Orbital degree in 10ths of a degree (e. g. 192 for 19.2°) |
0x2C | u4 | orbitalDirection | 01 = West, 02 = East |
The block starting from here appears twice - however, only the first one is edited by the channel editor application | |||
0x30/0x4C | u4 | tuner | 00=LOOP, 01=1, 02=2, 03=1&2 |
0x34/0x50 | m4 | Unknown: 00 00 00 00 or 01 00 00 00 | |
0x38/0x54 | u4 | lnbType | 00=Universal1, 01=Universal2, 02=Standard |
0x3C/0x58 | u4 | lnbFreqLow | in kHz, i. e. 97500000 for 9750 MHz |
0x40/0x5C | u4 | lnbFreqHigh | in kHz, i. e. 10600000 for 10600 MHz |
0x44/0x60 | m4 | Unknown: 00 00 00 00 | |
0x48/0x64 | u1 | toneBurst | 00 = TONE A, 01 = TONE B, 02 = None |
0x49/0x65 | u1 | diseqC | 00 = A, 01 = B, 02 = C, 03 = D |
0x4A/0x66 | u2 | diseqCPos | For example 2 |
End of the block appearing twice. | |||
0x68 | m36 | Padding?: All zeroes |
"Transpnd" block
Contains information about transponders for each satellite:
Offset | Datatype | Fieldname | Description |
---|---|---|---|
0x00 | m8 | "Transpnd" | |
0x08 | m12 | Unknown: 03 00 "rj" u4:8 u4:0x40 | |
Repeated for each satellite which exists in the allocation map above: | |||
0x14/... | am88 | transponders | Allocation map containing all transponders for this satellite |
End of repetition. |
Note that there is one allocation map for every allocation map entry in the satellite allocation map. That means, if the allocation map has 64 entries, but only 10 satellites are configured, there are 54 allocation maps here that do not contain any allocated transponders. As the allocation map usually contains 200 (NUL) bytes, this wastes a lot of space in the file. But who cares...
The transponder count above should be the sum of the transponders of all satellites. The length of the allocation map is usually 200.
Format of transponder records:
Offset | Datatype | Fieldname | Description |
---|---|---|---|
0x00 | u2 | id | Transponder ID |
0x02 | u2 | Unknown | |
0x04 | u4 | Unknown | |
0x08 | u4 | Unknown | |
0x0C | u4 | frequency | Frequency in kHz |
0x10 | u4 | symbolRate | Symbol rate in KS/s |
0x14 | u4 | Unknown (00 to 05) | |
0x18 | u4 | polarization; | Polarization (00 = Horizontal, 01 = Vertical) |
0x1C | m4 | 00 00 00 00 | |
0x20 | u4 | Unknown (00 or 01) | |
0x24 | m52 | Padding?: All zeroes |
"ServiceL" block
Contains information about channels and channel lists:
Offset | Datatype | Fieldname | Description |
---|---|---|---|
0x00 | m8 | "ServiceL" | |
0x08 | m8 | Unknown: 07 00 "rj" u4:5 | |
0x10 | am200 | channels | Allocation map of channels. |
Repeated for 76 (magic number?) times (channel lists): | |||
... | m8 | Unknown: 04 00 "rj" u4:12 | |
... | u2 | entryCount | Number of entries of this channel list |
... | sz16 | name | Name of the channel list |
... | b50 | data | Unknown. "EF 00 58 E7 CB 01 4C BF 0D 0C 00 00 00 00 08 00 00 00 E0 E3 CF 01 00 00 00 00 E0 E3 CF 01 CC 3B 78 00 FF FF FF FF 84 A4 58 00 AC E7 CB 01 01 00 00 00" for Radio/TV list, or "CB 01 00 06 00 00 00 00 00 00 00 00 00 00 1B 2F 12 00 20 2F 12 00 DE B4 0B 0C D5 B4 0B 6C DE B4 0B 0C FD 80 0D 0C 84 A4 58 00 59 0C 10 8C 00 00 00 00" for favourites. |
Repeated for entryCount times: | |||
... | u2 | entry | Channels in this list |
End of repetition. | |||
End of repetition. | |||
... | m8 | Unknown: 07 00 "rj" u4:5 |
The channels allocation map contains a lot of deleted channels... Perhaps this is because the channel does not have an ID and therefore you can only refer to it by index? The total number of non-deleted channels should match the number of channels in the header.
Format of the channel records:
Offset | Datatype | Fieldname | Description |
---|---|---|---|
0x00 | sz64 | name | Name of the channel |
0x40 | u2 | serviceID | Service ID |
0x42 | m2 | Unknown: 00 00 | |
0x44 | u2 | pcrPid | PCR PID |
0x46 | u2 | videoPid | VIDEO PID (0 = Radio) |
0x48 | u4 | audioCount | Number of audio channels, maximum 8 |
Repeated for 8 times (audio channels): | |||
0x4C/... | u2 | audioPid | Lower 13 bits: AUDIO PID, upper 3 bits: TODO |
0x4E/... | u2 | format | Audio format (00 = MPEG, 01 = AC3) |
0x50/... | sz4 | language | Name of channel/language |
End of repetition. | |||
0x8C | u2 | teletextPid | TELETEXT PID |
0x8E | m2 | Unknown: 00 00 | |
0x90 | m4 | Unknown: 01 00 00 00 | |
0x94 | u2 | satIdx | Satellite index |
0x96 | m2 | Unknown: 00 00 | |
0x98 | u2 | transpIdx | Transponder index |
0x9A | u2 | Unknown, value from 00 to 07 (Scrambled?) | |
0x9C | u2 | Unknown, either 00 or 04 or 05 or 0F | |
0x9E | u2 | Unknown | |
0xA0 | u2 | transponderID | Transponder ID, at least sometimes |
0xA2 | u2 | serviceID2 | Copy of service ID (unchanged by the channel editor application) |
0xA4 | u4 | Unknown, 00 or 02 or 08 or 0E | |
0xA8 | m32 | Padding?: All zeroes |
"CAInfoCI" block
Contains additional information for each channel mentioned in the ServiceL block. The data itself has not been decoded yet. Note that even though this is an allocation map, there seem to be data stored in "deleted" records as well. Records for deleted channels will be both deleted. Records for not deleted channels may be "deleted" but still not empty. The length of both allocation maps (both mapCount and savedCount) on disk usually have the same length. (I have seen files that contain more saved CAInfoCI entries than saved channel entries. In that case, the official editor just keeps the surplus entries unchanged all the time).
The contents of these 18 bytes per channel has not yet been deciphered yet. But as long as the information is stored within the channel and properly written out when the file is saved again, it will hopefully not matter.
Offset | Datatype | Fieldname | Description |
---|---|---|---|
0x00 | m8 | "CAInfoCI" | |
0x08 | m8 | Unknown: 07 00 "rj" u4:5 | |
0x10 | am16 | channels | Allocation map for channels. |
... | m8 | Unknown: 07 00 "rj" u4:5 |
CRC
The last 4 bytes are a CRC, which is computed using the polynomial 0x04C11DB7 and a starting value of 0xFFFFFFFF. Remember to recompute this value if you change anything :)
The end
To be continued?