Sub Read_Samsung_map_AirD() ' ' Lee el fichero map_AirD extraído de un fichero de lista de canales de Samsung. ' Read map_AirD extracted from a Samsung channel list. ' ' (Para extraerlo, cambie la extensión del archivo SCM a ZIP y extráigalo). ' (To extract from the SCM file, change extension from SCM to ZIP and unzip it). Dim a$ Const outputDetails = 1 ' Detalles / Output channel details. Const outputCSV = 2 ' CSV / Output a CSV channel list Const outputHex = 4 ' Hex / Output hexdump ' ' Specify here what to output, like outputDetails + outputHex ' Indique aquí la salida que desea, como outputDetails+outputHex ' Dim outputType As Integer: outputType = outputCSV ' ' Skip empty records? / ¿Saltar canales vacíos? ' Dim skipEmpty As Boolean: skipEmpty = True ' ' Input file. This points to [user folder]\desktop\map-AirD ' Archivo de entrada. Esto apunta a escritorio\map-AirD ' Dim inFile$: inFile$ = Environ$("userprofile") + "\Desktop\map-AirD" ' inFile$= "E:\prueba\map-AirD" Dim f As Integer, g As Integer Dim Position As Integer, Channel As Integer Open inFile$ For Binary As #1 firstname = 66 endname = 320 Seek 1, 1 While Loc(1) < LOF(1) ' ' El fichero contiene 1000 registros de 320 bytes, uno por cada posible canal. ' File contains 1000 320-byte records, one for each possible channel. ' a$ = InputB$(320, 1) If Not ((AscB(LeftB(a$, 1)) = 0) And (skipEmpty)) Then deleted = (AscB(MidB(a$, 20, 1)) = 0) Position = AscB(MidB(a$, 1, 1)) + AscB(MidB(a$, 2, 1)) * 256 Channel = AscB(MidB(a$, 43, 1)) + AscB(MidB(a$, 44, 1)) * 256 Unknown1 = AscB(MidB(a$, 283, 1)) + AscB(MidB(a$, 284, 1)) * 256 pname$ = Trim$(MidB(a$, 66, 66 + 256)) If AscB(MidB(a$, 22, 1)) = 255 Then ResolutionX = -1 Else ResolutionX = AscB(MidB(a$, 21, 1)) + AscB(MidB(a$, 22, 1)) * 256 End If If AscB(MidB(a$, 24, 1)) = 255 Then resolutionY = -1 Else resolutionY = AscB(MidB(a$, 23, 1)) + AscB(MidB(a$, 24, 1)) * 256 End If If AscB(MidB(a$, 4, 1)) = 255 Then VideoID = -1 'RadioID: a PID that is valid for both TVs and radios, but is not the Audio ID RadioID = AscB(MidB(a$, 5, 1)) + AscB(MidB(a$, 6, 1)) * 256 Else VideoID = AscB(MidB(a$, 3, 1)) + AscB(MidB(a$, 4, 1)) * 256 'RadioID: a PID that is valid for both TVs and radios, but is not the Audio ID RadioID = AscB(MidB(a$, 5, 1)) + AscB(MidB(a$, 6, 1)) * 256 End If 'If deleted Then pname$ = "(D)" + pname$ 'Display hex records for given channels only. ' This allows more detailed reverse engineering. ' encontrar$ = "" If encontrar$ > "" Then If InStr(pname$, encontrar$) > 0 Then outputType = outputType Or outputHex Else outputType = outputType And (Not outputHex) End If End If ' 'pname$ is unicode, use Instr, Chr instead of InstrB, ChrB ' Inst = InStr(pname$, Chr(0)) If Inst > 0 Then pname$ = Left(pname$, Inst - 1) 'Buscar longitud del campo de texto... ' For q = firstname + LenB(pname$) + 1 To 320 ' If endname >= LenB(a$) Then endname = LenB(a$) ' If q > endname Then Exit For ' If AscB(MidB(a$, q, 1)) <> 0 Then ' endname = q ' End If ' Next q ' Debug.Print endname ' No muestres canales vacíos ' Do not show empty channels If Position > 0 And Channel > 0 Then ' Salida para humanos ' Human readable output If (outputType And outputDetails) Then Debug.Print "Deleted? "; deleted; ";"; Debug.Print "Position #"; Position; ";"; Debug.Print "Channel #"; Channel; ";"; Debug.Print "Program name:"; pname$; ";"; Debug.Print "AnchoBanda:"; AscB(MidB(a$, 13, 1)); Debug.Print "VideoPID:"; VideoID; Debug.Print "_____PID:"; RadioID; Debug.Print "Resolution:"; ResolutionX; "x"; resolutionY; Debug.Print "Unknown1:"; Unknown1; 'Debug.Print End If ''Salida para CSV / CSV output ' CSV formato es_ES: datos delimitados con ";" ' CSV es_ES format: data delimited with ";" instead of "," If (outputType And outputCSV) Then Debug.Print Trim$(Str$(Position)) + ";" + Trim(Str$(Channel)) + ";""" + pname$ + """"; Debug.Print Str$(AscB(MidB(a$, 13, 1))) + ";"; Debug.Print Str$(VideoID) + ";"; Debug.Print Str$(RadioID) + ";"; Debug.Print Str$(ResolutionX) + ";"; Debug.Print Str$(resolutionY) + ";"; Debug.Print Str$(Unknown1) + ";"; If deleted Then Debug.Print "Deleted"; Else Debug.Print "Active"; Debug.Print End If End If ' xorval = 0 xorval1 = 0 xorval0 = 0 For g = 0 To 319 Step 16 ' 'Step 16: muestro 16 bytes en cada línea. / 16 bytes per line ' 'saltar registros vacíos en hexdump 'skip empty records in hexdump For f = 1 To 16 n = AscB(MidB$(a$, g + f, 1)) 'xorval = (xorval + n) Mod 256 'If (f And 1) Then xorval1 = (xorval1 + n) Mod 256 Else xorval0 = (xorval0 + n) Mod 256 If (outputType And outputHex) Then Debug.Print Right$("00" + Hex$(n), 2) + " "; If n >= 32 Then Debug.Print Chr$(n); Else Debug.Print ("."); Debug.Print " "; End If Next If (outputType And outputHex) Then Debug.Print Next 'Last value is some form of verification code, maybe xor, maybe crc. 'I can't guess what is it. 'Debug.Print GetCRC32(a$) 'Debug.Print Hex(xorval), Hex(xorval1), Hex(xorval0) End If Wend Close #1 Stop ' allows to use debug window before exiting End Sub Public Function GetCRC32(ByVal buffer As String) As String ' ' Modified from code by Tim Hartwig, ' http://dotnet-snippets.com/snippet/calculate-crc32-hash-from-file/587 ' Dim CRC32Result As Long: CRC32Result = &HFFFFFFFF Dim CRC32Table(256) As Long Dim DWPolynomial As Long: DWPolynomial = &HEDB88320 Dim DWCRC As Long Dim i As Integer, j As Integer, n As Integer 'Create CRC32 Table For i = 0 To 255 DWCRC = i For j = 8 To 1 Step -1 If (DWCRC And 1) Then DWCRC = ((DWCRC And &HFFFFFFFE) \ 2&) And &H7FFFFFFF DWCRC = DWCRC Xor DWPolynomial Else DWCRC = ((DWCRC And &HFFFFFFFE) \ 2&) And &H7FFFFFFF End If Next j CRC32Table(i) = DWCRC Next i 'Calcualting CRC32 Hash For i = 1 To LenB(buffer) n = (CRC32Result And &HFF) Xor AscB(MidB(buffer, i, 1)) CRC32Result = ((CRC32Result And &HFFFFFF00) \ &H100) And &HFFFFFF CRC32Result = CRC32Result Xor CRC32Table(n) Next i GetCRC32 = Hex(Not (CRC32Result)) End Function