diff --git a/source/ChanSort.Loader.PhilipsBin/ChanSort.Loader.PhilipsBin.csproj b/source/ChanSort.Loader.PhilipsBin/ChanSort.Loader.PhilipsBin.csproj index 2c67c2d..0269083 100644 --- a/source/ChanSort.Loader.PhilipsBin/ChanSort.Loader.PhilipsBin.csproj +++ b/source/ChanSort.Loader.PhilipsBin/ChanSort.Loader.PhilipsBin.csproj @@ -64,6 +64,7 @@ + diff --git a/source/ChanSort.Loader.PhilipsBin/ChanSort.Loader.PhilipsBin.ini b/source/ChanSort.Loader.PhilipsBin/ChanSort.Loader.PhilipsBin.ini index 4a7a94d..e3d907b 100644 --- a/source/ChanSort.Loader.PhilipsBin/ChanSort.Loader.PhilipsBin.ini +++ b/source/ChanSort.Loader.PhilipsBin/ChanSort.Loader.PhilipsBin.ini @@ -17,3 +17,28 @@ lenName=32 offProvider=60 lenProvider=32 +[CableDigSrvTable_entry] +offChecksum=0 +offSymbolRate=24 +offFreqTimes16=48 +offOnid=50 +offSid=52 +offTsid=54 +offProgNr=122 +offLocked=146 +offIsFav=147 +offName=216 +lenName=64 + +[CablePresetTable_entry] +offChecksum=0 +offFreqTimes16=4 +offProgNr=8 +offOnid=14 +offTsid=16 +offSid=18 + +[CableFrqMapTable_entry] +offChecksum=0 +offSymbolRate=8 +offFreq=18 \ No newline at end of file diff --git a/source/ChanSort.Loader.PhilipsBin/Channel.cs b/source/ChanSort.Loader.PhilipsBin/Channel.cs new file mode 100644 index 0000000..d424642 --- /dev/null +++ b/source/ChanSort.Loader.PhilipsBin/Channel.cs @@ -0,0 +1,16 @@ +using ChanSort.Api; + +namespace ChanSort.Loader.PhilipsBin +{ + class Channel : ChannelInfo + { + public Channel(SignalSource source, long index, int oldProgNr, string name) : base(source, index, oldProgNr, name) + { + } + + /// + /// index of the record in the AntennaPresetTable / CablePresetTable file for the channel, matched by (onid + tsid + sid) + /// + public int PresetTableIndex { get; set; } = -1; + } +} diff --git a/source/ChanSort.Loader.PhilipsBin/Serializer.cs b/source/ChanSort.Loader.PhilipsBin/Serializer.cs index 8a21833..4d169ba 100644 --- a/source/ChanSort.Loader.PhilipsBin/Serializer.cs +++ b/source/ChanSort.Loader.PhilipsBin/Serializer.cs @@ -3,16 +3,19 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; -using System.Runtime.InteropServices; using System.Text; -using System.Threading; -using System.Xml; -using System.Xml.Schema; using ChanSort.Api; namespace ChanSort.Loader.PhilipsBin { /* + channellib\CableDigSrvTable: + =========================== + Channels in this file are not phyiscally ordered by the program number and there is no linked list with prev/next indexes. + When editing a channel with the Philips Channel Editor, it only updates the progNr field (and overwrites all trailing bytes of the channel name with 0x00). + There is also the CablePresetTable file which is probably used for LCN. The Philips tool also updates the progNr in that file and uses it as is primary source + for the progNr. I don't know if there is a direct reference from the channel to the preset, hence this code uses the combination of ONID+TSID+SID to link the two. + s2channellib\service.dat: ======================== All observed files have a perfectly linear next/prev table. The Philips Channel Editor also keeps that list linear and physically reorders the channel records. @@ -27,17 +30,20 @@ namespace ChanSort.Loader.PhilipsBin When swapping satellite channels 1 and 2 with the Philips Channel Editor 6.62, it only updates a few fields and leaves the rest stale. updated: SID, transponderIndex, channelName, providerName - This code here copyies the whole record before updating the fields + This code here copies the whole record before updating the fields. + + The favorite.dat file stores favorites as linked list which may support independent ordering from the main channel list. + The Philips editor even saves non-linear lists, but not in any particular order. + */ class Serializer : SerializerBase { private readonly IniFile ini; private readonly List dataFilePaths = new List(); - private readonly ChannelList dvbtChannels = new ChannelList(SignalSource.DvbCT, "DVB-T"); - private readonly ChannelList dvbcChannels = new ChannelList(SignalSource.DvbCT, "DVB-C"); + private readonly ChannelList dvbtChannels = new ChannelList(SignalSource.DvbT, "DVB-T"); + private readonly ChannelList dvbcChannels = new ChannelList(SignalSource.DvbC, "DVB-C"); private readonly ChannelList satChannels = new ChannelList(SignalSource.DvbS, "DVB-S"); - #region ctor() public Serializer(string inputFile) : base(inputFile) { @@ -49,7 +55,7 @@ namespace ChanSort.Loader.PhilipsBin this.Features.CanSaveAs = false; this.Features.CanHaveGaps = false; this.Features.SupportedFavorites = Favorites.A; - this.Features.SortedFavorites = true; + this.Features.SortedFavorites = false; // satellite favorites are stored in a separate file that may support independent sorting, but DVB C/T only have a flag this.Features.AllowGapsInFavNumbers = false; this.Features.CanEditFavListNames = false; @@ -61,17 +67,20 @@ namespace ChanSort.Loader.PhilipsBin { list.VisibleColumnFieldNames.Remove("Skip"); list.VisibleColumnFieldNames.Remove("ShortName"); + list.VisibleColumnFieldNames.Remove("ServiceTypeName"); + list.VisibleColumnFieldNames.Remove("Hidden"); + list.VisibleColumnFieldNames.Remove("AudioPid"); + list.VisibleColumnFieldNames.Remove("Encrypted"); } - var supportedColumns = new[] {"OldPosition", "Position", "Name", "Lock"}; - //this.satChannels.VisibleColumnFieldNames.Clear(); - //foreach(var supportedColumn in supportedColumns) - // this.satChannels.VisibleColumnFieldNames.Add(supportedColumn); - - this.satChannels.VisibleColumnFieldNames.Remove("AudioPid"); - this.satChannels.VisibleColumnFieldNames.Remove("ServiceTypeName"); - this.satChannels.VisibleColumnFieldNames.Remove("Encrypted"); - this.satChannels.VisibleColumnFieldNames.Remove("Hidden"); + foreach (var list in new[] {dvbcChannels, dvbtChannels}) + { + list.VisibleColumnFieldNames.Remove("PcrPid"); + list.VisibleColumnFieldNames.Remove("VideoPid"); + list.VisibleColumnFieldNames.Remove("AudioPid"); + list.VisibleColumnFieldNames.Remove("ChannelOrTransponder"); + list.VisibleColumnFieldNames.Remove("Provider"); + } string iniFile = Assembly.GetExecutingAssembly().Location.Replace(".dll", ".ini"); this.ini = new IniFile(iniFile); @@ -87,32 +96,43 @@ namespace ChanSort.Loader.PhilipsBin + "ChannelList\\channellib\\CableDigSrvTable\n" + "ChannelList\\s2channellib\\service.dat"); - var dir = Path.GetDirectoryName(this.FileName); - LoadDvbCT(dvbtChannels, Path.Combine(dir, "channellib", "AntennaDigSrvTable")); - LoadDvbCT(dvbcChannels, Path.Combine(dir, "channellib", "CableDigSrvTable")); + var dir = Path.GetDirectoryName(this.FileName) ?? ""; + var channellib = Path.Combine(dir, "channellib"); + var s2channellib = Path.Combine(dir, "s2channellib"); - LoadDvbsSatellites(Path.Combine(dir, "s2channellib", "satellite.dat")); - LoadDvbsTransponders(Path.Combine(dir, "s2channellib", "tuneinfo.dat")); - LoadDvbS(satChannels, Path.Combine(dir, "s2channellib", "service.dat")); - LoadDvbsFavorites(Path.Combine(dir, "s2channellib", "favorite.dat")); - var db_file_info = Path.Combine(dir, "s2channellib", "db_file_info.dat"); + // channellib files for DVB-C/T + LoadDvbCT(dvbtChannels, Path.Combine(channellib, "AntennaDigSrvTable")); + LoadDvbCTPresets(dvbtChannels, Path.Combine(channellib, "AntennaPresetTable")); + LoadDvbCT(dvbcChannels, Path.Combine(channellib, "CableDigSrvTable")); + LoadDvbCTPresets(dvbcChannels, Path.Combine(channellib, "CablePresetTable")); + + // s2channellib files for DVB-S + LoadDvbsSatellites(Path.Combine(s2channellib, "satellite.dat")); + LoadDvbsTransponders(Path.Combine(s2channellib, "tuneinfo.dat")); + LoadDvbS(satChannels, Path.Combine(s2channellib, "service.dat")); + LoadDvbsFavorites(Path.Combine(s2channellib, "favorite.dat")); + var db_file_info = Path.Combine(s2channellib, "db_file_info.dat"); if (File.Exists(db_file_info)) this.dataFilePaths.Add(db_file_info); // for a proper ChanSort backup/restore with .bak files, the Philips _backup.dat files must also be included - foreach(var file in this.dataFilePaths.ToList()) - this.dataFilePaths.Add(file.Replace(".dat", "_backup.dat")); + foreach (var file in this.dataFilePaths.ToList()) + { + if (file.Contains(".dat")) + this.dataFilePaths.Add(file.Replace(".dat", "_backup.dat")); + } } + #endregion #region SetFileNameToChanLstBin() private bool SetFileNameToChanLstBin() { - var dir = Path.GetDirectoryName(this.FileName); + var dir = Path.GetDirectoryName(this.FileName) ?? ""; var dirName = Path.GetFileName(dir); if (StringComparer.InvariantCultureIgnoreCase.Compare(dirName, "channellib") == 0 || StringComparer.InvariantCultureIgnoreCase.Compare(dirName, "s2channellib") == 0) { - dir = Path.GetDirectoryName(dir); + dir = Path.GetDirectoryName(dir) ?? ""; dirName = Path.GetFileName(dir); } @@ -134,52 +154,110 @@ namespace ChanSort.Loader.PhilipsBin #endregion #region LoadDvbCT - private byte[] LoadDvbCT(ChannelList list, string path) + private void LoadDvbCT(ChannelList list, string path) { + if (!ReadAndValidateChannellibFile(path, out var data, out var recordSize, out var recordCount)) + return; + + var mapping = new DataMapping(this.ini.GetSection("CableDigSrvTable_entry")); + mapping.SetDataPtr(data, 20); + + for (int i = 0; i < recordCount; i++, mapping.BaseOffset += recordSize) + { + var progNr = mapping.GetWord("offProgNr"); + + var offChannelName = mapping.BaseOffset + mapping.GetConst("offName", 0); + var lenName = mapping.GetConst("lenName", 0); + for (int j = 0; j < lenName; j += 2) + { + if (data[offChannelName + j] == 0) + { + lenName = j; + break; + } + } + string channelName = Encoding.Unicode.GetString(data, offChannelName, lenName); + + var checksum = mapping.GetDword("offChecksum"); + mapping.SetDword("offChecksum", 0); + var crc = FaultyCrc32(data, mapping.BaseOffset + mapping.GetConst("offChecksum", 0), recordSize); + if (crc != checksum) + throw new FileLoadException($"Invalid CRC in record {i} in {path}"); + + var ch = new Channel(list.SignalSource, i, progNr, channelName); + ch.FreqInMhz = (decimal) mapping.GetWord("offFreqTimes16") / 16; + ch.OriginalNetworkId = mapping.GetWord("offOnid"); + ch.TransportStreamId = mapping.GetWord("offTsid"); + ch.ServiceId = mapping.GetWord("offSid"); + ch.SymbolRate = (int)mapping.GetDword("offSymbolRate") / 1000; + ch.Lock = mapping.GetByte("offLocked") != 0; + ch.Favorites = mapping.GetByte("offIsFav") != 0 ? Favorites.A : 0; + if (ch.Favorites != 0) + ch.OldFavIndex[0] = ch.OldProgramNr; + this.DataRoot.AddChannel(list, ch); + } + } + #endregion + + #region LoadDvbCTPresets + private void LoadDvbCTPresets(ChannelList list, string path) + { + if (!ReadAndValidateChannellibFile(path, out var data, out var recordSize, out var recordCount)) + return; + + // build a mapping of (onid,tsid,sid) => channel + var channelById = new Dictionary(); + foreach(var chan in list.Channels) + { + var ch = (Channel)chan; + var id = ((ulong)ch.OriginalNetworkId << 32) | ((ulong)ch.TransportStreamId << 16) | (uint)ch.ServiceId; + channelById[id] = ch; + } + + // apply preset progNr (LCN?) to the channel and remember the preset index for it + var mapping = new DataMapping(this.ini.GetSection("CablePresetTable_entry")); + mapping.SetDataPtr(data, 20); + for (int i = 0; i < recordCount; i++, mapping.BaseOffset += recordSize) + { + var onid = mapping.GetWord("offOnid"); + var tsid = mapping.GetWord("offTsid"); + var sid = mapping.GetWord("offSid"); + var id = ((ulong)onid << 32) | ((ulong)tsid << 16) | sid; + if (!channelById.TryGetValue(id, out var ch)) + continue; + + ch.PresetTableIndex = i; + var progNr = mapping.GetWord("offProgNr"); + if (progNr != 0 && progNr != 0xFFFF) + ch.OldProgramNr = progNr; + } + } + #endregion + + #region ReadAndValidateChannellibFile + private bool ReadAndValidateChannellibFile(string path, out byte[] data, out int recordSize, out int recordCount) + { + data = null; + recordSize = 0; + recordCount = 0; + if (!File.Exists(path)) - return null; + return false; - var data = File.ReadAllBytes(path); + data = File.ReadAllBytes(path); if (data.Length < 20) - return null; + return false; - var recordSize = BitConverter.ToInt32(data, 8); - var recordCount = BitConverter.ToInt32(data, 12); + recordSize = BitConverter.ToInt32(data, 8); + recordCount = BitConverter.ToInt32(data, 12); if (data.Length != 20 + recordCount * recordSize) throw new FileLoadException("Unsupported file content: " + path); this.dataFilePaths.Add(path); - - int baseOffset = 20; - for (int i = 0; i < recordCount; i++, baseOffset += recordSize) - { - uint checksum = BitConverter.ToUInt32(data, baseOffset + 0); - ushort progNr = BitConverter.ToUInt16(data, baseOffset + 122); - byte locked = data[baseOffset + 140]; - int nameLen; - for (nameLen=0; nameLen<64; nameLen+=2) - if (data[baseOffset + 216 + nameLen] == 0) - break; - string channelName = Encoding.Unicode.GetString(data, baseOffset + 216, nameLen); - - data[baseOffset + 0] = 0; - data[baseOffset + 1] = 0; - data[baseOffset + 2] = 0; - data[baseOffset + 3] = 0; - var crc = FaultyCrc32(data, baseOffset, recordSize); - - if (crc != checksum) - throw new FileLoadException($"Invalid CRC in record {i} in {path}"); - - var ch = new ChannelInfo(list.SignalSource, i, progNr, channelName); - ch.Lock = locked != 0; - this.DataRoot.AddChannel(list, ch); - } - - return data; + return true; } - #endregion + #endregion #region LoadDvbsSatellites() private void LoadDvbsSatellites(string path) @@ -397,13 +475,70 @@ namespace ChanSort.Loader.PhilipsBin #region Save() public override void Save(string tvOutputFile) { - var dir = Path.GetDirectoryName(this.FileName); + var dir = Path.GetDirectoryName(this.FileName) ?? ""; + var channellib = Path.Combine(dir, "channellib"); + var s2channellib = Path.Combine(dir, "s2channellib"); - // TODO: save cable and antenna channels + SaveDvbCTChannels(this.dvbtChannels, Path.Combine(channellib, "AntennaDigSrvTable")); + SaveDvbCTPresets(this.dvbtChannels, Path.Combine(channellib, "AntennaPresetTable")); + SaveDvbCTChannels(this.dvbcChannels, Path.Combine(channellib, "CableDigSrvTable")); + SaveDvbCTPresets(this.dvbcChannels, Path.Combine(channellib, "CablePresetTable")); - SaveDvbsChannels(Path.Combine(dir, "s2channellib", "service.dat")); - SaveDvbsFavorites(Path.Combine(dir, "s2channellib", "favorite.dat")); - SaveDvbsDbFileInfo(Path.Combine(dir, "s2channellib", "db_file_info.dat")); + SaveDvbsChannels(Path.Combine(s2channellib, "service.dat")); + SaveDvbsFavorites(Path.Combine(s2channellib, "favorite.dat")); + SaveDvbsDbFileInfo(Path.Combine(s2channellib, "db_file_info.dat")); + } + + #endregion + + #region SaveDvbCTChannels + private void SaveDvbCTChannels(ChannelList list, string path) + { + if (!ReadAndValidateChannellibFile(path, out var data, out var recordSize, out _)) + return; + + var mapping = new DataMapping(this.ini.GetSection("CableDigSrvTable_entry")); + mapping.SetDataPtr(data, 20); + foreach (var ch in list.Channels) + { + mapping.BaseOffset = 20 + (int)ch.RecordIndex * recordSize; + mapping.SetWord("offProgNr", ch.NewProgramNr); + mapping.SetByte("offLocked", ch.Lock ? 1 : 0); + mapping.SetByte("offIsFav", ch.Favorites == 0 ? 0 : 1); + + mapping.SetDword("offChecksum", 0); + var crc = FaultyCrc32(data, mapping.BaseOffset, recordSize); + mapping.SetDword("offChecksum", crc); + } + + File.WriteAllBytes(path, data); + } + #endregion + + #region SaveDvbCTPresets + private void SaveDvbCTPresets(ChannelList list, string path) + { + if (!ReadAndValidateChannellibFile(path, out var data, out var recordSize, out _)) + return; + + var mapping = new DataMapping(this.ini.GetSection("CablePresetTable_entry")); + mapping.SetDataPtr(data, 20); + + + // update the preset records with new channel numbers + foreach (var chan in list.Channels) + { + if (!(chan is Channel ch) || ch.PresetTableIndex < 0) + continue; + mapping.BaseOffset = 20 + ch.PresetTableIndex * recordSize; + mapping.SetWord("offProgNr", ch.NewProgramNr); + + mapping.SetDword("offChecksum", 0); + var crc = FaultyCrc32(data, mapping.BaseOffset, recordSize); + mapping.SetDword("offChecksum", crc); + } + + File.WriteAllBytes(path, data); } #endregion diff --git a/source/Information/FileStructures_for_HHD_Hex_Editor_Neo/philips_dat.h b/source/Information/FileStructures_for_HHD_Hex_Editor_Neo/philips_dat.h index 443fdc1..1a8d638 100644 --- a/source/Information/FileStructures_for_HHD_Hex_Editor_Neo/philips_dat.h +++ b/source/Information/FileStructures_for_HHD_Hex_Editor_Neo/philips_dat.h @@ -1,5 +1,9 @@ #include "chansort.h" +/*********************************************************** + * s2channellib / DVB-S files + ***********************************************************/ + struct Ph_NextPrevTableEntry { word next; @@ -134,43 +138,131 @@ public struct Ph_FavoriteDat dword crc32; }; +/*********************************************************** + * channellib / antenna and cable files + ***********************************************************/ public struct Ph_CableDigSrvTable { - byte unk1[8]; + dword unk1; + dword unk2; dword chRecordSize; dword channelCount; - byte unk2[4]; + dword versionCode; struct Ph_CableChannel { var off0 = current_offset; dword checksum; - byte unk1[110]; + byte unk1[20]; + dword symbolRate; + byte unk2[20]; + struct + { + word subFreq : 4; + word mhz : 12; + } freqTimes16; + word onid; + word sid; + word tsid; + byte unk3b[58]; + word progNrMostly; + byte unk4[6]; word progNr; - byte unk2[6]; - word progNr2; - byte unk2b[16]; + byte unk5[22]; byte locked; - byte unk3[75]; + byte isFav; + byte unk6[68]; wchar_t channelName[32]; byte unk4[chRecordSize - (current_offset - off0)]; } Channels[channelCount]; }; -public struct Ph_CablePresetTable +public struct Ph_CableDigTSTable { - byte unk1[8]; + dword unk1; + dword unk2; dword recordSize; dword recordCount; - byte unk2[4]; + dword versionCode; + struct Ph_CableChannel + { + var off0 = current_offset; + dword checksum; + dword unk1; + dword unk2; + struct + { + dword subFreq :4; + dword mhz : 28; + } freqInMhzTimes16a; + dword unk3; + dword unk4; + dword unk5; + dword symbolRate; + dword unk6; + dword unk7; + struct + { + dword subFreq :4; + dword mhz : 28; + } freqInMhzTimes16b; + word onid; + word nid; + word tsid; + word unk10; + byte unk4[recordSize - (current_offset - off0)]; + } Transponders[recordCount]; +}; + +public struct Ph_CableFrqMapTable +{ + dword unk1; + dword unk2; + dword recordSize; + dword recordCount; + dword versionCode; + struct + { + var off0 = current_offset; + dword checksum; + struct + { + dword subFreq :4; + dword mhz : 28; + } freqInMhzTimes16; + dword symbolRate; + dword unk2; + word onid; + word tsid; + word unk5; + word unk6; + dword unk7; + byte unk[recordSize - (current_offset - off0)]; + } Transponders[recordCount]; +}; + +public struct Ph_CablePresetTable +{ + dword unk1; + dword unk2; + dword recordSize; + dword recordCount; + dword versionCode; struct { var off0 = current_offset; - byte unk1[12]; - word unk2; + dword checksum; + struct + { + dword subFreq :4; + dword mhz : 28; + } freqInMhzTimes16; + word progNr; word unk3; word unk4; - word unk5; + word onid; + word tsid; + word sid; byte unk[recordSize - (current_offset - off0)]; } ChanPreset[recordCount]; }; diff --git a/source/Test.Loader.PhilipsBin/PhilipsChannellibTest.cs b/source/Test.Loader.PhilipsBin/PhilipsChannellibTest.cs new file mode 100644 index 0000000..c612517 --- /dev/null +++ b/source/Test.Loader.PhilipsBin/PhilipsChannellibTest.cs @@ -0,0 +1,37 @@ +using System; +using System.IO; +using System.Linq; +using ChanSort.Api; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace Test.Loader.PhilipsBin +{ + [TestClass] + public class PhilipsChannellibTest + { + [TestMethod] + public void TestFiles1() + { + var baseDir = Path.GetDirectoryName(this.GetType().Assembly.Location); + var baseFile = Path.Combine(baseDir, "TestFiles1\\Repair\\ChannelList\\chanLst.bin"); + var plugin = new ChanSort.Loader.PhilipsBin.SerializerPlugin(); + var loader = plugin.CreateSerializer(baseFile); + loader.Load(); + + var list = loader.DataRoot.GetChannelList(SignalSource.DvbC); + Assert.AreEqual(179, list.Channels.Count); + Assert.AreEqual(179, list.Channels.Count(ch => !ch.IsDeleted)); + + var ch0 = list.Channels.FirstOrDefault(ch => ch.RecordIndex == 0); + Assert.AreEqual(41, ch0.OldProgramNr); + Assert.AreEqual("Passion HD", ch0.Name); + Assert.IsFalse(ch0.Lock); + Assert.AreEqual((Favorites)0, ch0.Favorites); + Assert.AreEqual(810, ch0.FreqInMhz); + Assert.AreEqual(9999, ch0.OriginalNetworkId); + Assert.AreEqual(461, ch0.TransportStreamId); + Assert.AreEqual(46102, ch0.ServiceId); + Assert.AreEqual(6900, ch0.SymbolRate); + } + } +} diff --git a/source/Test.Loader.PhilipsBin/Test.Loader.PhilipsBin.csproj b/source/Test.Loader.PhilipsBin/Test.Loader.PhilipsBin.csproj index e0b81b1..ee48b8e 100644 --- a/source/Test.Loader.PhilipsBin/Test.Loader.PhilipsBin.csproj +++ b/source/Test.Loader.PhilipsBin/Test.Loader.PhilipsBin.csproj @@ -69,172 +69,173 @@ + - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always - PreserveNewest + Always diff --git a/source/Test.Loader.PhilipsBin/TestFiles1/Repair/ChannelList/chanLst.bin b/source/Test.Loader.PhilipsBin/TestFiles1/Repair/ChannelList/chanLst.bin index 71f4578..5568295 100644 Binary files a/source/Test.Loader.PhilipsBin/TestFiles1/Repair/ChannelList/chanLst.bin and b/source/Test.Loader.PhilipsBin/TestFiles1/Repair/ChannelList/chanLst.bin differ diff --git a/source/Test.Loader.PhilipsBin/TestFiles1/Repair/ChannelList/channellib/CableDigSrvTable b/source/Test.Loader.PhilipsBin/TestFiles1/Repair/ChannelList/channellib/CableDigSrvTable index 48c48a1..9f1f508 100644 Binary files a/source/Test.Loader.PhilipsBin/TestFiles1/Repair/ChannelList/channellib/CableDigSrvTable and b/source/Test.Loader.PhilipsBin/TestFiles1/Repair/ChannelList/channellib/CableDigSrvTable differ