From 33d17a730b1e04041e1e756e31ae90957f04aba9 Mon Sep 17 00:00:00 2001 From: feyris-tan Date: Fri, 7 Nov 2025 14:03:27 +0100 Subject: [PATCH] Sucessfulyl parsed our very first BFBS GSE Frame. --- skyscraper8/GS/GSE-BFBS/BfbsGseReader.cs | 79 +++++++++++++++++++++ skyscraper8/GS/GSE/GseLabel.cs | 25 +++++-- skyscraper8/Skyscraper/IO/StreamlikeSpan.cs | 51 +++++++++++++ 3 files changed, 149 insertions(+), 6 deletions(-) diff --git a/skyscraper8/GS/GSE-BFBS/BfbsGseReader.cs b/skyscraper8/GS/GSE-BFBS/BfbsGseReader.cs index a97c094..d201240 100644 --- a/skyscraper8/GS/GSE-BFBS/BfbsGseReader.cs +++ b/skyscraper8/GS/GSE-BFBS/BfbsGseReader.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading.Tasks; using skyscraper5.Mpeg2; using skyscraper8.GSE; +using skyscraper8.GSE.GSE; using skyscraper8.Skyscraper.IO; using skyscraper8.Skyscraper.Scraper; @@ -15,6 +16,8 @@ namespace skyscraper8.GS.GSE_BFBS private readonly byte _misId; private readonly ISubTsHandler _subTsHandler; + private GseLabel lastLabel; + public BfbsGseReader(byte misId, ISubTsHandler subTsHandler) { _misId = misId; @@ -32,6 +35,82 @@ namespace skyscraper8.GS.GSE_BFBS StreamlikeSpan span = new StreamlikeSpan(readOnlySpan); + + while (span.GetAvailableBytes() >= 1) + { + byte byteA = span.ReadUInt8(); + bool startIndicator = (byteA & 0x80) != 0; + bool endIndicator = (byteA & 0x40) != 0; + int labelTypeIndicator = (byteA & 0x30) >> 4; + if (!startIndicator && !endIndicator && labelTypeIndicator == 0) + { + //padding bits, packet has ended. + return; + } + else + { + int gseLength = (byteA & 0x0f) << 8; + gseLength += span.ReadUInt8(); + + byte? fragId = null; + if (!startIndicator || !endIndicator) + { + fragId = span.ReadUInt8(); + gseLength -= 1; + } + + ushort? totalLength = null; + if ((startIndicator) && !endIndicator) + { + totalLength = span.ReadUInt16BE(); + gseLength -= 2; + } + + GseLabel label = null; + ushort? protocolType = null; + if (startIndicator) + { + protocolType = span.ReadUInt16BE(); + gseLength -= 2; + if (labelTypeIndicator == 0) + { + label = new _6byteLabel(span.ReadBytes(6)); + gseLength -= 6; + } + else if (labelTypeIndicator == 1) + { + label = new _3byteLabel(span.ReadBytes(3)); + gseLength -= 3; + } + else if (labelTypeIndicator == 2) + { + label = BroadcastLabel.GetInstance(); + } + else if (labelTypeIndicator == 3) + { + label = lastLabel; + } + } + + if (!startIndicator && endIndicator) + gseLength -= 4; + + ReadOnlySpan gseDataBytes = span.ReadBytes(gseLength); + + if (!startIndicator && endIndicator) + { + uint crc32 = span.ReadUInt32BE(); + throw new NotImplementedException("crc32"); + } + + HandleGseFrame(startIndicator, endIndicator, fragId, totalLength, label, protocolType, + gseDataBytes); + } + } + } + + private void HandleGseFrame(bool startIndicator, bool endIndicator, byte? fragId, ushort? totalLength, GseLabel label, ushort? protocolType, ReadOnlySpan gseDataBytes) + { throw new NotImplementedException(); } } diff --git a/skyscraper8/GS/GSE/GseLabel.cs b/skyscraper8/GS/GSE/GseLabel.cs index 563c871..799f5d6 100644 --- a/skyscraper8/GS/GSE/GseLabel.cs +++ b/skyscraper8/GS/GSE/GseLabel.cs @@ -29,16 +29,29 @@ public class _3byteLabel : GseLabel { public _3byteLabel(byte[] buffer) { - Label = buffer; + this.buffer = buffer; } - - public byte[] Label { get; private set; } - override public string ToString() + private byte[] buffer; + + public byte GroupId => buffer[0]; + + public ushort LogonId { - return BitConverter.ToString(Label); + get + { + ushort result = buffer[1]; + result <<= 8; + result += buffer[2]; + return result; + } } - + + public override string ToString() + { + return $"{nameof(GroupId)}: {GroupId}, {nameof(LogonId)}: {LogonId}"; + } + override public int Length => 3; } diff --git a/skyscraper8/Skyscraper/IO/StreamlikeSpan.cs b/skyscraper8/Skyscraper/IO/StreamlikeSpan.cs index 1a0a7c8..53c8ed7 100644 --- a/skyscraper8/Skyscraper/IO/StreamlikeSpan.cs +++ b/skyscraper8/Skyscraper/IO/StreamlikeSpan.cs @@ -69,6 +69,57 @@ namespace skyscraper8.Skyscraper.IO public bool CanWrite => true; public long Length => internalLength; public long Position => internalPosition; + + public byte ReadUInt8() + { + byte result = _readOnlySpan[internalPosition]; + internalPosition++; + return result; + } + + public ushort ReadUInt16BE() + { + ushort a = _readOnlySpan[internalPosition]; + a <<= 8; + a += _readOnlySpan[internalPosition + 1]; + internalPosition += 2; + return a; + } + + public byte[] ReadBytes(int i) + { + byte[] buffer = new byte[i]; + if (Read(buffer, 0, i) != i) + { + throw new IOException(String.Format("Failed to read {0} bytes", i)); + } + return buffer; + } + + public ReadOnlySpan ReadSpan(int length) + { + ReadOnlySpan buffer = _readOnlySpan.Slice(internalPosition, length); + internalPosition += length; + return buffer; + } + + public uint ReadUInt32BE() + { + uint result = _readOnlySpan[internalPosition]; + result <<= 8; + result += _readOnlySpan[internalPosition + 1]; + result <<= 8; + result += _readOnlySpan[internalPosition + 2]; + result <<= 8; + result += _readOnlySpan[internalPosition + 3]; + internalPosition += 4; + return result; + } + + public int GetAvailableBytes() + { + return internalLength - internalPosition; + } } class TelepathyStream : Stream