Πώς ανάκτησα δεδομένα σε άγνωστη μορφή από μαγνητική ταινία

Ιστορικό

Όντας λάτρης του ρετρό υλικού, κάποτε αγόρασα ένα ZX Spectrum+ από έναν πωλητή στο Ηνωμένο Βασίλειο. Μαζί με τον ίδιο τον υπολογιστή, έλαβα αρκετές κασέτες ήχου με παιχνίδια (στην αρχική συσκευασία με οδηγίες), καθώς και προγράμματα ηχογραφημένα σε κασέτες χωρίς ειδική σήμανση. Παραδόξως, τα δεδομένα από κασέτες 40 ετών ήταν ευανάγνωστα και μπορούσα να κατεβάσω σχεδόν όλα τα παιχνίδια και τα προγράμματα από αυτές.

Πώς ανάκτησα δεδομένα σε άγνωστη μορφή από μαγνητική ταινία

Ωστόσο, σε κάποιες κασέτες βρήκα ηχογραφήσεις που σαφώς δεν έγιναν από τον υπολογιστή ZX Spectrum. Ακούγονταν εντελώς διαφορετικά και, σε αντίθεση με τις ηχογραφήσεις από τον αναφερόμενο υπολογιστή, δεν ξεκίνησαν με ένα σύντομο bootloader BASIC, που συνήθως υπάρχει στις εγγραφές όλων των προγραμμάτων και παιχνιδιών.

Για κάποιο διάστημα αυτό με στοίχειωνε - ήθελα πολύ να μάθω τι κρύβεται σε αυτά. Εάν μπορούσατε να διαβάσετε το ηχητικό σήμα ως μια ακολουθία byte, θα μπορούσατε να αναζητήσετε χαρακτήρες ή οτιδήποτε σε αυτά που υποδεικνύει την προέλευση του σήματος. Ένα είδος ρετρο-αρχαιολογίας.

Τώρα που έχω πάει μέχρι τέλους και κοιτάζω τις ίδιες τις ετικέτες των κασετών, χαμογελώ γιατί

η απάντηση ήταν μπροστά στα μάτια μου όλη την ώρα
Στην ετικέτα της αριστερής κασέτας αναγράφεται το όνομα του υπολογιστή TRS-80 και ακριβώς κάτω από το όνομα του κατασκευαστή: "Κατασκευάζεται από την Radio Shack στις ΗΠΑ"

(Αν θέλετε να κρατήσετε την ίντριγκα μέχρι το τέλος, μην πάτε κάτω από το spoiler)

Σύγκριση ηχητικών σημάτων

Πρώτα απ 'όλα, ας ψηφιοποιήσουμε τις ηχογραφήσεις. Μπορείτε να ακούσετε πώς ακούγεται:


Και ως συνήθως η ηχογράφηση από τον υπολογιστή ZX Spectrum ακούγεται:


Και στις δύο περιπτώσεις, στην αρχή της ηχογράφησης υπάρχει το λεγόμενο πιλοτικό τόνο - ήχος ίδιας συχνότητας (στην πρώτη ηχογράφηση είναι πολύ σύντομος <1 δευτερόλεπτο, αλλά διακρίνεται). Ο πιλοτικός τόνος σηματοδοτεί τον υπολογιστή να προετοιμαστεί για λήψη δεδομένων. Κατά κανόνα, κάθε υπολογιστής αναγνωρίζει μόνο τον "δικό του" πιλοτικό τόνο από το σχήμα του σήματος και τη συχνότητά του.

Είναι απαραίτητο να πούμε κάτι για το ίδιο το σχήμα του σήματος. Για παράδειγμα, στο ZX Spectrum το σχήμα του είναι ορθογώνιο:

Πώς ανάκτησα δεδομένα σε άγνωστη μορφή από μαγνητική ταινία

Όταν ανιχνεύεται ένας πιλοτικός τόνος, το ZX Spectrum εμφανίζει εναλλασσόμενες κόκκινες και μπλε γραμμές στο περίγραμμα της οθόνης για να υποδείξει ότι το σήμα αναγνωρίστηκε. Ο πιλοτικός τόνος τελειώνει συγχρονικός παλμός, το οποίο δίνει σήμα στον υπολογιστή να αρχίσει να λαμβάνει δεδομένα. Χαρακτηρίζεται από μικρότερη διάρκεια (σε σύγκριση με τον πιλοτικό τόνο και τα μετέπειτα δεδομένα) (βλ. σχήμα)

Μετά τη λήψη του παλμού συγχρονισμού, ο υπολογιστής καταγράφει κάθε άνοδο/πτώση του σήματος, μετρώντας τη διάρκειά του. Εάν η διάρκεια είναι μικρότερη από ένα ορισμένο όριο, το bit 1 γράφεται στη μνήμη, διαφορετικά 0. Τα bit συλλέγονται σε byte και η διαδικασία επαναλαμβάνεται μέχρι να ληφθούν N byte. Ο αριθμός N λαμβάνεται συνήθως από την κεφαλίδα του ληφθέντος αρχείου. Η σειρά φόρτωσης έχει ως εξής:

  1. πιλοτικό τόνο
  2. κεφαλίδα (σταθερό μήκος), περιέχει το μέγεθος των ληφθέντων δεδομένων (N), το όνομα και τον τύπο του αρχείου
  3. πιλοτικό τόνο
  4. τα ίδια τα δεδομένα

Για να βεβαιωθείτε ότι τα δεδομένα έχουν φορτωθεί σωστά, το ZX Spectrum διαβάζει το λεγόμενο byte ισοτιμίας (byte ισοτιμίας), το οποίο υπολογίζεται κατά την αποθήκευση ενός αρχείου με XOR σε όλα τα byte των γραπτών δεδομένων. Κατά την ανάγνωση ενός αρχείου, ο υπολογιστής υπολογίζει το byte ισοτιμίας από τα ληφθέντα δεδομένα και, εάν το αποτέλεσμα διαφέρει από το αποθηκευμένο, εμφανίζει το μήνυμα σφάλματος "R Tape loading error". Αυστηρά μιλώντας, ο υπολογιστής μπορεί να εκδώσει αυτό το μήνυμα νωρίτερα εάν, κατά την ανάγνωση, δεν μπορεί να αναγνωρίσει έναν παλμό (χάθηκε ή η διάρκειά του δεν αντιστοιχεί σε ορισμένα όρια)

Λοιπόν, ας δούμε τώρα πώς μοιάζει ένα άγνωστο σήμα:

Πώς ανάκτησα δεδομένα σε άγνωστη μορφή από μαγνητική ταινία

Αυτός είναι ο πιλοτικός τόνος. Το σχήμα του σήματος είναι σημαντικά διαφορετικό, αλλά είναι σαφές ότι το σήμα αποτελείται από επανάληψη σύντομων παλμών συγκεκριμένης συχνότητας. Σε συχνότητα δειγματοληψίας 44100 Hz, η απόσταση μεταξύ των «κορυφών» είναι περίπου 48 δείγματα (που αντιστοιχεί σε συχνότητα ~918 Hz). Ας θυμηθούμε αυτό το σχήμα.

Ας δούμε τώρα το τμήμα δεδομένων:

Πώς ανάκτησα δεδομένα σε άγνωστη μορφή από μαγνητική ταινία

Εάν μετρήσουμε την απόσταση μεταξύ των μεμονωμένων παλμών, αποδεικνύεται ότι η απόσταση μεταξύ των "μακριών" παλμών εξακολουθεί να είναι ~48 δείγματα και μεταξύ των σύντομων παλμών - ~24. Κοιτώντας λίγο μπροστά, θα πω ότι στο τέλος αποδείχτηκε ότι παλμοί «αναφοράς» με συχνότητα 918 Hz ακολουθούν συνεχώς, από την αρχή μέχρι το τέλος του αρχείου. Μπορούμε να υποθέσουμε ότι κατά τη μετάδοση δεδομένων, εάν συναντηθεί ένας επιπλέον παλμός μεταξύ των παλμών αναφοράς, τον θεωρούμε ως bit 1, διαφορετικά 0.

Τι γίνεται με τον παλμό συγχρονισμού; Ας δούμε την αρχή των δεδομένων:

Πώς ανάκτησα δεδομένα σε άγνωστη μορφή από μαγνητική ταινία

Ο πιλοτικός τόνος τελειώνει και τα δεδομένα αρχίζουν αμέσως. Λίγο αργότερα, αφού αναλύσαμε πολλές διαφορετικές ηχογραφήσεις, μπορέσαμε να ανακαλύψουμε ότι το πρώτο byte δεδομένων είναι πάντα το ίδιο (10100101b, A5h). Ο υπολογιστής μπορεί να αρχίσει να διαβάζει δεδομένα αφού τα λάβει.

Μπορείτε επίσης να δώσετε προσοχή στη μετατόπιση του πρώτου παλμού αναφοράς αμέσως μετά τον τελευταίο 1ο στο byte συγχρονισμού. Ανακαλύφθηκε πολύ αργότερα στη διαδικασία ανάπτυξης ενός προγράμματος αναγνώρισης δεδομένων, όταν τα δεδομένα στην αρχή του αρχείου δεν μπορούσαν να διαβαστούν σταθερά.

Τώρα ας προσπαθήσουμε να περιγράψουμε έναν αλγόριθμο που θα επεξεργαστεί ένα αρχείο ήχου και θα φορτώσει δεδομένα.

Τα δεδομένα φορτώνονται

Αρχικά, ας δούμε μερικές υποθέσεις για να διατηρήσουμε τον αλγόριθμο απλό:

  1. Θα εξετάσουμε μόνο αρχεία σε μορφή WAV.
  2. Το αρχείο ήχου πρέπει να ξεκινά με πιλοτικό τόνο και δεν πρέπει να περιέχει σιωπή στην αρχή
  3. Το αρχείο προέλευσης πρέπει να έχει ρυθμό δειγματοληψίας 44100 Hz. Σε αυτή την περίπτωση, η απόσταση μεταξύ των παλμών αναφοράς 48 δειγμάτων έχει ήδη καθοριστεί και δεν χρειάζεται να την υπολογίσουμε προγραμματικά.
  4. Η μορφή του δείγματος μπορεί να είναι οποιαδήποτε (8/16 bit/floating point) - αφού κατά την ανάγνωση μπορούμε να τη μετατρέψουμε στην επιθυμητή.
  5. Υποθέτουμε ότι το αρχείο προέλευσης είναι κανονικοποιημένο κατά πλάτος, το οποίο θα πρέπει να σταθεροποιεί το αποτέλεσμα.

Ο αλγόριθμος ανάγνωσης θα είναι ο εξής:

  1. Διαβάζουμε το αρχείο στη μνήμη, μετατρέποντας ταυτόχρονα τη μορφή δείγματος σε 8 bit.
  2. Προσδιορίστε τη θέση του πρώτου παλμού στα δεδομένα ήχου. Για να γίνει αυτό, πρέπει να υπολογίσετε τον αριθμό του δείγματος με το μέγιστο πλάτος. Για απλότητα, θα το υπολογίσουμε μία φορά χειροκίνητα. Ας το αποθηκεύσουμε στη μεταβλητή prev_pos.
  3. Προσθέστε 48 στη θέση του τελευταίου παλμού (pos := prev_pos + 48)
  4. Επειδή η αύξηση της θέσης κατά 48 δεν εγγυάται ότι θα φτάσουμε στη θέση του επόμενου παλμού αναφοράς (ελαττώματα ταινίας, ασταθής λειτουργία του μηχανισμού κίνησης ταινίας κ.λπ.), πρέπει να ρυθμίσουμε τη θέση του παλμού pos. Για να το κάνετε αυτό, πάρτε ένα μικρό κομμάτι δεδομένων (pos-8;pos+8) και βρείτε τη μέγιστη τιμή πλάτους σε αυτό. Η θέση που αντιστοιχεί στο μέγιστο θα αποθηκευτεί σε pos. Εδώ το 8 = 48/6 είναι μια πειραματικά ληφθείσα σταθερά, η οποία εγγυάται ότι θα προσδιορίσουμε το σωστό μέγιστο και δεν θα επηρεάσουμε άλλες ωθήσεις που μπορεί να είναι κοντά. Σε πολύ κακές περιπτώσεις, όταν η απόσταση μεταξύ των παλμών είναι πολύ μικρότερη ή μεγαλύτερη από 48, μπορείτε να πραγματοποιήσετε μια αναγκαστική αναζήτηση για έναν παλμό, αλλά στο πλαίσιο του άρθρου δεν θα το περιγράψω στον αλγόριθμο.
  5. Στο προηγούμενο βήμα, θα ήταν επίσης απαραίτητο να ελέγξετε ότι ο παλμός αναφοράς βρέθηκε καθόλου. Δηλαδή, αν απλά αναζητήσετε το μέγιστο, αυτό δεν εγγυάται ότι η ώθηση είναι παρούσα σε αυτό το τμήμα. Στην τελευταία μου εφαρμογή του προγράμματος ανάγνωσης, ελέγχω τη διαφορά μεταξύ της μέγιστης και ελάχιστης τιμής πλάτους σε ένα τμήμα και αν υπερβαίνει ένα ορισμένο όριο, υπολογίζω την παρουσία ώθησης. Το ερώτημα είναι επίσης τι να κάνετε εάν δεν βρεθεί ο παλμός αναφοράς. Υπάρχουν 2 επιλογές: είτε τα δεδομένα έχουν λήξει και ακολουθεί σιωπή, είτε αυτό θα πρέπει να θεωρείται σφάλμα ανάγνωσης. Ωστόσο, θα το παραλείψουμε αυτό για να απλοποιήσουμε τον αλγόριθμο.
  6. Στο επόμενο βήμα, πρέπει να προσδιορίσουμε την παρουσία ενός παλμού δεδομένων (bit 0 ή 1), για αυτό παίρνουμε το μέσο του τμήματος (prev_pos;pos) middle_pos ίσο με middle_pos := (prev_pos+pos)/2 και σε κάποια γειτονιά του middle_pos στο τμήμα (middle_pos-8;middle_pos +8) ας υπολογίσουμε το μέγιστο και το ελάχιστο πλάτος. Εάν η διαφορά μεταξύ τους είναι μεγαλύτερη από 10, γράφουμε το bit 1 στο αποτέλεσμα, διαφορετικά το 0. 10 είναι μια σταθερά που λαμβάνεται πειραματικά.
  7. Αποθηκεύστε την τρέχουσα θέση στο prev_pos (prev_pos := pos)
  8. Επαναλάβετε ξεκινώντας από το βήμα 3 μέχρι να διαβάσουμε ολόκληρο το αρχείο.
  9. Ο προκύπτων πίνακας bit πρέπει να αποθηκευτεί ως σύνολο byte. Εφόσον δεν λάβαμε υπόψη το byte συγχρονισμού κατά την ανάγνωση, ο αριθμός των bit μπορεί να μην είναι πολλαπλάσιο του 8 και η απαιτούμενη μετατόπιση bit είναι επίσης άγνωστη. Στην πρώτη υλοποίηση του αλγορίθμου, δεν ήξερα για την ύπαρξη του byte συγχρονισμού και ως εκ τούτου απλά αποθήκευσα 8 αρχεία με διαφορετικούς αριθμούς μπιτ offset. Ένα από αυτά περιείχε σωστά δεδομένα. Στον τελικό αλγόριθμο, απλώς αφαιρώ όλα τα bit έως και A5h, κάτι που μου επιτρέπει να λαμβάνω αμέσως το σωστό αρχείο εξόδου

Αλγόριθμος σε Ruby, για όσους ενδιαφέρονται
Επέλεξα τη Ruby ως γλώσσα για τη συγγραφή του προγράμματος, επειδή... Το προγραμματίζω τις περισσότερες φορές. Η επιλογή δεν είναι υψηλής απόδοσης, αλλά δεν αξίζει τον κόπο να κάνετε την ταχύτητα ανάγνωσης όσο το δυνατόν πιο γρήγορα.

# Используем gem 'wavefile'
require 'wavefile'

reader = WaveFile::Reader.new('input.wav')
samples = []
format = WaveFile::Format.new(:mono, :pcm_8, 44100)

# Читаем WAV файл, конвертируем в формат Mono, 8 bit 
# Массив samples будет состоять из байт со значениями 0-255
reader.each_buffer(10000) do |buffer|
  samples += buffer.convert(format).samples
end

# Позиция первого импульса (вместо 0)
prev_pos = 0
# Расстояние между импульсами
distance = 48
# Значение расстояния для окрестности поиска локального максимума
delta = (distance / 6).floor
# Биты будем сохранять в виде строки из "0" и "1"
bits = ""

loop do
  # Рассчитываем позицию следующего импульса
  pos = prev_pos + distance
  
  # Выходим из цикла если данные закончились 
  break if pos + delta >= samples.size

  # Корректируем позицию pos обнаружением максимума на отрезке [pos - delta;pos + delta]
  (pos - delta..pos + delta).each { |p| pos = p if samples[p] > samples[pos] }

  # Находим середину отрезка [prev_pos;pos]
  middle_pos = ((prev_pos + pos) / 2).floor

  # Берем окрестность в середине 
  sample = samples[middle_pos - delta..middle_pos + delta]

  # Определяем бит как "1" если разница между максимальным и минимальным значением на отрезке превышает 10
  bit = sample.max - sample.min > 10
  bits += bit ? "1" : "0"
end

# Определяем синхро-байт и заменяем все предшествующие биты на 256 бит нулей (согласно спецификации формата) 
bits.gsub! /^[01]*?10100101/, ("0" * 256) + "10100101"

# Сохраняем выходной файл, упаковывая биты в байты
File.write "output.cas", [bits].pack("B*")

Αποτέλεσμα

Έχοντας δοκιμάσει πολλές παραλλαγές του αλγορίθμου και των σταθερών, ήμουν τυχερός που πήρα κάτι εξαιρετικά ενδιαφέρον:

Πώς ανάκτησα δεδομένα σε άγνωστη μορφή από μαγνητική ταινία

Έτσι, αν κρίνουμε από τις συμβολοσειρές χαρακτήρων, έχουμε ένα πρόγραμμα για τη δημιουργία γραφημάτων. Ωστόσο, δεν υπάρχουν λέξεις-κλειδιά στο κείμενο του προγράμματος. Όλες οι λέξεις-κλειδιά κωδικοποιούνται ως byte (κάθε τιμή > 80h). Τώρα πρέπει να μάθουμε ποιος υπολογιστής από τη δεκαετία του '80 θα μπορούσε να αποθηκεύσει προγράμματα σε αυτήν τη μορφή.

Στην πραγματικότητα, μοιάζει πολύ με ένα πρόγραμμα BASIC. Ο υπολογιστής ZX Spectrum αποθηκεύει προγράμματα στην ίδια περίπου μορφή στη μνήμη και αποθηκεύει προγράμματα σε κασέτα. Για κάθε ενδεχόμενο, έλεγξα τις λέξεις-κλειδιά τραπέζι. Ωστόσο, το αποτέλεσμα ήταν προφανώς αρνητικό.

Έλεγξα επίσης τις ΒΑΣΙΚΕΣ λέξεις-κλειδιά του δημοφιλούς Atari, Commodore 64 και αρκετών άλλων υπολογιστών εκείνης της εποχής, για τους οποίους μπόρεσα να βρω τεκμηρίωση, αλλά χωρίς επιτυχία - οι γνώσεις μου για τους τύπους ρετρό υπολογιστών αποδείχτηκαν όχι τόσο ευρεία.

Τότε αποφάσισα να πάω η λίστα, και μετά το βλέμμα μου έπεσε στο όνομα του κατασκευαστή Radio Shack και του υπολογιστή TRS-80. Αυτά ήταν τα ονόματα που έγραφαν στις ετικέτες των κασετών που ήταν ξαπλωμένα στο τραπέζι μου! Δεν ήξερα αυτά τα ονόματα πριν και δεν ήμουν εξοικειωμένος με τον υπολογιστή TRS-80, οπότε μου φάνηκε ότι το Radio Shack ήταν κατασκευαστής κασετών ήχου όπως η BASF, η Sony ή η TDK, και το TRS-80 ήταν ο χρόνος αναπαραγωγής. Γιατί όχι?

Υπολογιστής Tandy/Radio Shack TRS-80

Είναι πολύ πιθανό η εν λόγω ηχογράφηση, την οποία έδωσα ως παράδειγμα στην αρχή του άρθρου, να έγινε σε έναν υπολογιστή όπως αυτός:

Πώς ανάκτησα δεδομένα σε άγνωστη μορφή από μαγνητική ταινία

Αποδείχθηκε ότι αυτός ο υπολογιστής και οι ποικιλίες του (Μοντέλο I/Μοντέλο ΙΙΙ/Μοντέλο IV κ.λπ.) ήταν πολύ δημοφιλείς κάποτε (φυσικά, όχι στη Ρωσία). Αξιοσημείωτο είναι ότι ο επεξεργαστής που χρησιμοποίησαν ήταν επίσης Z80. Για αυτόν τον υπολογιστή μπορείτε να βρείτε στο Διαδίκτυο πολλες ΠΛΗΡΟΦΟΡΙΕΣ. Στη δεκαετία του '80, οι πληροφορίες ηλεκτρονικών υπολογιστών διανεμήθηκαν στο περιοδικά. Αυτή τη στιγμή υπάρχουν αρκετές εξομοιωτές υπολογιστές για διαφορετικές πλατφόρμες.

Κατέβασα τον εξομοιωτή trs80gp και για πρώτη φορά μπόρεσα να δω πώς λειτουργούσε αυτός ο υπολογιστής. Φυσικά, ο υπολογιστής δεν υποστήριζε έγχρωμη έξοδο· η ανάλυση της οθόνης ήταν μόνο 128x48 pixel, αλλά υπήρχαν πολλές επεκτάσεις και τροποποιήσεις που θα μπορούσαν να αυξήσουν την ανάλυση της οθόνης. Υπήρχαν επίσης πολλές επιλογές για λειτουργικά συστήματα για αυτόν τον υπολογιστή και επιλογές για την εφαρμογή της γλώσσας BASIC (η οποία, σε αντίθεση με το ZX Spectrum, σε ορισμένα μοντέλα δεν «φλάσιζε» καν στη ROM και οποιαδήποτε επιλογή μπορούσε να φορτωθεί από μια δισκέτα, όπως ακριβώς το ίδιο το λειτουργικό σύστημα)

βρήκα κι εγώ χρησιμότητα να μετατρέψω ηχογραφήσεις σε μορφή CAS, η οποία υποστηρίζεται από εξομοιωτές, αλλά για κάποιο λόγο δεν ήταν δυνατή η ανάγνωση εγγραφών από τις κασέτες μου χρησιμοποιώντας αυτές.

Έχοντας καταλάβει τη μορφή αρχείου CAS (η οποία αποδείχθηκε ότι ήταν απλώς ένα αντίγραφο σπιθαμή προς μπιτ των δεδομένων από την κασέτα που είχα ήδη στη διάθεσή μου, εκτός από την κεφαλίδα με την παρουσία ενός byte συγχρονισμού), έφτιαξα ένα λίγες αλλαγές στο πρόγραμμά μου και μπόρεσα να βγάλω ένα λειτουργικό αρχείο CAS που λειτουργούσε στον εξομοιωτή (TRS-80 Model III):

Πώς ανάκτησα δεδομένα σε άγνωστη μορφή από μαγνητική ταινία

Σχεδίασα την πιο πρόσφατη έκδοση του βοηθητικού προγράμματος μετατροπής με αυτόματο προσδιορισμό του πρώτου παλμού και της απόστασης μεταξύ των παλμών αναφοράς ως πακέτο GEM, ο πηγαίος κώδικας είναι διαθέσιμος στη διεύθυνση Github.

Συμπέρασμα

Το μονοπάτι που διανύσαμε αποδείχθηκε ένα συναρπαστικό ταξίδι στο παρελθόν και χαίρομαι που στο τέλος βρήκα την απάντηση. Μεταξύ άλλων, εγώ:

  • Ανακάλυψα τη μορφή αποθήκευσης δεδομένων στο ZX Spectrum και μελέτησα τις ενσωματωμένες ρουτίνες ROM για την αποθήκευση/ανάγνωση δεδομένων από κασέτες ήχου
  • Γνώρισα τον υπολογιστή TRS-80 και τις ποικιλίες του, μελέτησα το λειτουργικό σύστημα, κοίταξα δείγματα προγραμμάτων και μάλιστα είχα την ευκαιρία να κάνω εντοπισμό σφαλμάτων σε κωδικούς μηχανών (εξάλλου, όλα τα μνημονικά Z80 μου είναι γνωστά)
  • Έγραψε ένα πλήρες βοηθητικό πρόγραμμα για τη μετατροπή ηχογραφήσεων σε μορφή CAS, το οποίο μπορεί να διαβάσει δεδομένα που δεν αναγνωρίζονται από το "επίσημο" βοηθητικό πρόγραμμα

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο