Das kommt IMHO sehr darauf an, wieviel ein (vermutlich) deutlich komplexerer Code an Zeitgewinn bringt. Du kannst es natürlich ausprobieren und Messungen machen. Meine persönliche Erfahrung ist, dass Python in Sachen Listenerstellung schneller arbeitet als man vielleicht vermuten würde.jens hat geschrieben:Macht es eigentlich Sinn zu versuchen das ganze komplett als Generator zu bauen?
z.Z. mache ich ja noch oft ein list() um dann doch wieder eine normale Liste zu haben...
Dragon 32 Homecomputer Kassetten in ASCII umwandeln...
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
So... um es nochmal klar zu machen, was da überhaupt passiert:
1. WAV Sinus-Kurvenlänge -> Bitstream aus Nullen und Einsen
2. suche nach Muster "10101010" (0x55) Zeichenweise
3. in 8-Bit-Schritten weiter Springen, bis das Muster "10101010" nicht mehr vorkommt.
4. Suchen des Sync-Bits "00111100" (0x3C) Zeichenweise
Ab hier könnte ich IMHO jeweils 8-Bit in einem Byte umwandeln und nur noch damit weitermachen.
5. Ersten Bytes sind: Block-Typ und Block-Länge
6. Lese Blocklänge und werte die Daten aus (in Python Objekte packen)
7. Schleife wenn Block-Typ nicht EOF-Block ist, weiter bei Punkt 2.
In der aktuellen Implementierung arbeite ich viel zu lange mit dem Bit-Stream, statt ihn nach Punkt 4 umzuwandeln.
EDIT: Werte doch die Block-Länge aus
1. WAV Sinus-Kurvenlänge -> Bitstream aus Nullen und Einsen
2. suche nach Muster "10101010" (0x55) Zeichenweise
3. in 8-Bit-Schritten weiter Springen, bis das Muster "10101010" nicht mehr vorkommt.
4. Suchen des Sync-Bits "00111100" (0x3C) Zeichenweise
Ab hier könnte ich IMHO jeweils 8-Bit in einem Byte umwandeln und nur noch damit weitermachen.
5. Ersten Bytes sind: Block-Typ und Block-Länge
6. Lese Blocklänge und werte die Daten aus (in Python Objekte packen)
7. Schleife wenn Block-Typ nicht EOF-Block ist, weiter bei Punkt 2.
In der aktuellen Implementierung arbeite ich viel zu lange mit dem Bit-Stream, statt ihn nach Punkt 4 umzuwandeln.
EDIT: Werte doch die Block-Länge aus
@jens: Das mit den drei Nullbytes ist aber nicht wirklich robust. Die können schliesslich auch innerhalb der Daten vorkommen. Selbst bei reinem BASIC ist es nicht ausgeschlossen, bei (zusätzlichen) Binärdaten aber überhaupt nicht.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Hab ich schon editiert. In wirklich nutzte ich die Längeninformation des Blocks.BlackJack hat geschrieben:@jens: Das mit den drei Nullbytes ist aber nicht wirklich robust. Die können schliesslich auch innerhalb der Daten vorkommen. Selbst bei reinem BASIC ist es nicht ausgeschlossen, bei (zusätzlichen) Binärdaten aber überhaupt nicht.
Die drei 0x0 kommen im BASIC-Code selbst vor: Ein 0x0 ist das Zeilenende Zeichen und dann nochmal zwei 0x0 markieren das Ende des BASIC Blocks.
Eigentlich ist das IMHO doppelt gemoppelt. Also das nochmal mit zwei 0x0 das Ende markiert wird, wenn vorher schon die Länge des Blocks angegeben ist.
Keine Ahnung warum das so ist...
@jens: Ich schrob doch gerade das drei Nullbytes auch *innerhalb* der Daten vorkommen können, nicht nur am Ende, also ist das nicht doppelt gemoppelt. Selbst wenn es bei (tokenisierten) BASIC-Programmen ausgeschlossen *wäre*: Das Bandformat soll ja nicht nur BASIC-Programme speichern können und man möchte nicht `x` verschiedene Formate für `x` Dateiarten haben, die alle eine eigene Laderoutine brauchen.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
So ist es allerdings laut http://dragon32.info/info/basicfmt.html spezifiziert.
Dennoch ist IMHO das unnötig. Man hat die Block länge und zusätzlich das Ende markiert. Naja... Sind ja nur zwei Byte unnötige Zeichen...
EDIT: Generell muß ich mir nochmal alle Dokumente von http://dragon32.info/info/ genauer ansehen...
Dennoch ist IMHO das unnötig. Man hat die Block länge und zusätzlich das Ende markiert. Naja... Sind ja nur zwei Byte unnötige Zeichen...
EDIT: Generell muß ich mir nochmal alle Dokumente von http://dragon32.info/info/ genauer ansehen...
@jens: Es können, auch wenn man sich an diese Spezifikation hält, *innerhalb* eines BASIC-Programms drei Nullbytes vorkommen. Davon abgesehen halten die Leute sich nicht immer an Spezifikationen. Man kann zum Beispiel Binärdaten hinter einem BASIC-Programm speichern. Beim C64 war das kein Problem auf diese Weise ein BASIC-Programm zusammen mit Maschinenprogrammteilen und/oder (Grafik)Daten in einer Datei zu speichern. Solange Zeilen kein Sprungziel sind, kann man die Zeilennummer auch beliebig manipulieren. Zum Beispiel all diese Zeilen auf die Zeilennummer 0 setzen. War beliebt um Programme vor Veränderungen zu schützen.
Du vermischt hier IMHO auch zwei Ebenen. Das eine ist das Speicherformat auf dem Band und das andere ist das Speicherformat für BASIC-Programme. Die Bandroutinen sollten wie schon gesagt so entworfen sein, dass für alle Dateitypen das Laden/Lesen grundsätzlich gleich funktioniert. Damit man eben nicht für jedem Typ eigene Laderoutinen braucht. Der Laderoutine ist der Blocktyp oder der Dateityp egal, die funktioniert immer gleich.
Du vermischt hier IMHO auch zwei Ebenen. Das eine ist das Speicherformat auf dem Band und das andere ist das Speicherformat für BASIC-Programme. Die Bandroutinen sollten wie schon gesagt so entworfen sein, dass für alle Dateitypen das Laden/Lesen grundsätzlich gleich funktioniert. Damit man eben nicht für jedem Typ eigene Laderoutinen braucht. Der Laderoutine ist der Blocktyp oder der Dateityp egal, die funktioniert immer gleich.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Aber wie soll das gehen? Eigentlich darf kein einziges 0x00 vorkommen, denn das markiert ja das Ende der BASIC Zeile.BlackJack hat geschrieben:*innerhalb* eines BASIC-Programms drei Nullbytes vorkommen
Ansonsten könnte man die Zeilen nicht richtig trennen.
Hab auch angefangen, neben dem tokenized BASIC auch ASCII BASIC zu behandeln, hier: https://github.com/jedie/PyDragon32/blo ... DC.py#L717
Der wird aber bisher nur angezeigt, mehr nicht.
Interessant dabei: Beim tokenized BASIC wird das Ende des Codes mit zwei 0x00 extra Markiert. Beim ASCII BASIC sind die Zeilen mit einem \r getrennt. Sieht so aus:
Hätte jetzt zwei \r nochmal am Ende erwartet...\r1 PRINT "LINE NUMBER TEST"\r
\r10 PRINT 10\r
\r100 PRINT 100\r
\r1000 PRINT 1000\r
\r10000 PRINT 10000\r
\r32768 PRINT 32768\r
\r63999 PRINT "END";63999\r
Auch hier darf dann im BASIC-Code kein \r vorkommen. Keine Ahnung ob man das überhaupt einfügen kann. Aber evtl. wird es dann escaped?
Ich weiß noch nicht wie man sowas machen kann und ob der Dragon das kann.BlackJack hat geschrieben:Man kann zum Beispiel Binärdaten hinter einem BASIC-Programm speichern. Beim C64 war das kein Problem auf diese Weise ein BASIC-Programm zusammen mit Maschinenprogrammteilen und/oder (Grafik)Daten in einer Datei zu speichern. Solange Zeilen kein Sprungziel sind, kann man die Zeilennummer auch beliebig manipulieren. Zum Beispiel all diese Zeilen auf die Zeilennummer 0 setzen. War beliebt um Programme vor Veränderungen zu schützen.
Hab zwar schon damit gerechnet, das man BASIC+Daten+BIN speichern kann, aber ich bin davon ausgegenagen, das das dann immer in einem neuen Block passiert. Es also immer mehrere Dateien sind.
Hast du info's dazu? Evtl. vom C64 und man kann das "Übertragen" ?
Nein, ich weiß um die beiden Ebenen. Nur weiß ich nicht ob wir vom selben redenBlackJack hat geschrieben:Du vermischt hier IMHO auch zwei Ebenen. Das eine ist das Speicherformat auf dem Band und das andere ist das Speicherformat für BASIC-Programme. Die Bandroutinen sollten wie schon gesagt so entworfen sein, dass für alle Dateitypen das Laden/Lesen grundsätzlich gleich funktioniert. Damit man eben nicht für jedem Typ eigene Laderoutinen braucht. Der Laderoutine ist der Blocktyp oder der Dateityp egal, die funktioniert immer gleich.
Eigentlich sind das mehrere Ebenen:
* WAVE <-> bits (Also wie die Binäredaten im Ton moduliert werden, das macht IMHO der C64 anders)
* Blockebene: Die ich mir z.Z. mit get_block_info() durchgehe: https://github.com/jedie/PyDragon32/blo ... DC.py#L543
* Block Daten: Fileinfo-Block (Dateiname, Typ, Länge usw.) / Datei-Inhalt
EDIT: Gerade das nochmal ins Auge gesprugen:
Ist in den Meta-Daten des Fileinfo-Blocks...5.4 A gap flag to indicate whether the
data stream is continuous (00) as
in binary or BASIC files, or in blocks
where the tape keeps stopping (FF) as
in data files.
Keine Ahnung was das wirklich bedeutet. Habe festgestellt, das es pausen zwischen den Blöcken gibt. Ob das damit gemeint ist?
@jens: Natürlich dürfen noch andere Nullbytes vorkommen. Sonst könnte man keine Zeilennummer verwenden die als 16-Bit-Wert ein Nullbyte enthält, insbesondere nicht die Zeilennummer 0, die sogar zu *zwei* Nullbytes wird. Und es dürfte keine BASIC-Zeile an einer Speicheradresse beginnen deren High- oder Lowbyte Null ist. Womit dann auch klar ist wie man völlig legal drei Nullbytes hinbekommt: Eine Zeile mit der Zeilennummer 0 die so im Speicher platziert ist, dass das Lowbyte der Adresse der nächsten Zeile 0 ist.
Aber wie schon gesagt, die Leute stellen manchmal die abenteuerlichsten Sachen an. Die Beschreibung der Spezifikation sagt ja zum Beispiel nichts darüber aus, dass die Zeilennummern in jeder Zeile verschieden sein müssen. Man kann auch einfach allen Zeilen die kein Sprungziel sind, die Zeilennnummer 0 verpassen. Damit steigt die Wahrscheinlichkeit drei Nullbytes in den Daten zu bekommen. Das könnte zu Problemen mit Sprunganweisung die im Programm *zurück* springen geben, darum wird das so gelöst, dass die Zeilennummern immer bei einer Zeile die Sprungziel sind, um 1 hochgezählt wird. Sinn davon ist übrigens nicht nur das Bearbeiten zu erschweren, sondern auch Programme kürzer zu machen, denn die Sprungziele werden im Quelltext als Ziffernfolge gespeichert. Kurze Zeilennummern bedeuten also weniger Bytes.
Das '\r' ist ja die Return-Taste. Wie würdest Du das denn eingeben wollen? Wenn Du die betätigst wird ja die Zeile übernommen und in den Speicher geschrieben.
Beim C64 hat man einfach die verschiedenen Dateien in den Speicher geladen. Die Zeiger für das Ende des BASIC-Programms hinter die letzten Daten gesetzt und dann den BASIC-Speicherbefehl aufgerufen.
Wave->Bits macht der C64 sehr ähnlich und diverse TurboTape-Routinen auf dem C64 noch ähnlicher. Die beiden Bitwerte haben jeweils eine Pulslänge zugeordnet, wie beim Dragon.
Kleine Pausen werden auch bei „continuous”-Dateien sein. Technisch bedingt. Bei Datendateien werden die grösser sein, weil das ja wahrscheinlich so läuft, dass es einen Blockpuffer im Speicher gibt, der immer wenn er voll ist geschrieben wird, oder beim lesen immer wenn er leer ist, der nächste Block vom Band geladen wird. Dafür muss vor jedem Block der Bandmotor gestartet und nach dem Block der Motor wieder gestoppt werden. So entstehen an sich schon Lücken, die dann wahrscheinlich noch etwas verlängert werden um Laufwerksunterschiede auszugleichen.
Aber wie schon gesagt, die Leute stellen manchmal die abenteuerlichsten Sachen an. Die Beschreibung der Spezifikation sagt ja zum Beispiel nichts darüber aus, dass die Zeilennummern in jeder Zeile verschieden sein müssen. Man kann auch einfach allen Zeilen die kein Sprungziel sind, die Zeilennnummer 0 verpassen. Damit steigt die Wahrscheinlichkeit drei Nullbytes in den Daten zu bekommen. Das könnte zu Problemen mit Sprunganweisung die im Programm *zurück* springen geben, darum wird das so gelöst, dass die Zeilennummern immer bei einer Zeile die Sprungziel sind, um 1 hochgezählt wird. Sinn davon ist übrigens nicht nur das Bearbeiten zu erschweren, sondern auch Programme kürzer zu machen, denn die Sprungziele werden im Quelltext als Ziffernfolge gespeichert. Kurze Zeilennummern bedeuten also weniger Bytes.
Das '\r' ist ja die Return-Taste. Wie würdest Du das denn eingeben wollen? Wenn Du die betätigst wird ja die Zeile übernommen und in den Speicher geschrieben.
Beim C64 hat man einfach die verschiedenen Dateien in den Speicher geladen. Die Zeiger für das Ende des BASIC-Programms hinter die letzten Daten gesetzt und dann den BASIC-Speicherbefehl aufgerufen.
Wave->Bits macht der C64 sehr ähnlich und diverse TurboTape-Routinen auf dem C64 noch ähnlicher. Die beiden Bitwerte haben jeweils eine Pulslänge zugeordnet, wie beim Dragon.
Kleine Pausen werden auch bei „continuous”-Dateien sein. Technisch bedingt. Bei Datendateien werden die grösser sein, weil das ja wahrscheinlich so läuft, dass es einen Blockpuffer im Speicher gibt, der immer wenn er voll ist geschrieben wird, oder beim lesen immer wenn er leer ist, der nächste Block vom Band geladen wird. Dafür muss vor jedem Block der Bandmotor gestartet und nach dem Block der Motor wieder gestoppt werden. So entstehen an sich schon Lücken, die dann wahrscheinlich noch etwas verlängert werden um Laufwerksunterschiede auszugleichen.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Also du meinst 0x00 kann vorkommen z.B. bei GOTO ?
Wenn das wirklich so ist, wie soll ich dann die Zeilen parsen können?
Ich hab nur flüchtig auf das Bild dort geblickt und dachte, das würde was mit der Amplitude gemacht werden. Aber offensichtlich geht es da auch nur um die Länge...
Wäre ja interessant, das ganze dann modular auch für den C64 zu bauen.
Ich glaube ich habe auch einen Denkfehler beim umwandeln der WAVE in den Bit-Strom: Denn bei https://github.com/jedie/PyDragon32/blo ... DC.py#L266 suche ich immer nach einer kompletten Sinus-Kurve. Dann schaue ich wie lange die war und unterscheide zwischen 0 und 1
Ich denke das Problem liegt darin, das ich bei falscher even_odd Vorgabe, eine Hälfte der Sinuskurve von z.B. 1 zur anderen Hälfte von 0 zu zähle. In dem Fall kommt natürlich Müll raus.
Somit sollte ich lieber die Zeiten der Halben Sinus-Kurve messen. Also doch einfach die Nulldurchgänge... Doch echte Nulldurchgänge vom Rauschen Unterscheiden, wäre dabei das Problem.
Allerdings kann ich dabei vielleicht bei dem Aktuellen Algorithmus bleiben (Kommt ja nicht auf die Absolut genaue Zeit des Nulldurchgangs an): https://github.com/jedie/PyDragon32/blo ... DC.py#L203
Im Groben: Ein Nulldurchgang ist immer dann geschehen, wenn mehrere MIN_TOGGLE_COUNT Sample-Werte im Positiven oder Negativen Bereich sind.
Vielleicht das ganze in drei hintereinander geschalteten Generatoren:
1. Generator liefert die WAVE-Samples zurück iter_wave_values(): https://github.com/jedie/PyDragon32/blo ... DC.py#L134
2. Generator wartet auf die mehrere MIN_TOGGLE_COUNT Sample-Werte im Positiven oder Negativen Bereich und spuckt dann nur die rohen Zeiten aus.
3. Generator nimmt die Zeiten entgehen und bildet damit den Bit-Stream
Wenn das wirklich so ist, wie soll ich dann die Zeilen parsen können?
Stimmt: http://en.wikipedia.org/wiki/Datasette#Physical_codingBlackJack hat geschrieben:Wave->Bits macht der C64 sehr ähnlich und diverse TurboTape-Routinen auf dem C64 noch ähnlicher. Die beiden Bitwerte haben jeweils eine Pulslänge zugeordnet, wie beim Dragon.
Ich hab nur flüchtig auf das Bild dort geblickt und dachte, das würde was mit der Amplitude gemacht werden. Aber offensichtlich geht es da auch nur um die Länge...
Wäre ja interessant, das ganze dann modular auch für den C64 zu bauen.
Ich glaube ich habe auch einen Denkfehler beim umwandeln der WAVE in den Bit-Strom: Denn bei https://github.com/jedie/PyDragon32/blo ... DC.py#L266 suche ich immer nach einer kompletten Sinus-Kurve. Dann schaue ich wie lange die war und unterscheide zwischen 0 und 1
Ich denke das Problem liegt darin, das ich bei falscher even_odd Vorgabe, eine Hälfte der Sinuskurve von z.B. 1 zur anderen Hälfte von 0 zu zähle. In dem Fall kommt natürlich Müll raus.
Somit sollte ich lieber die Zeiten der Halben Sinus-Kurve messen. Also doch einfach die Nulldurchgänge... Doch echte Nulldurchgänge vom Rauschen Unterscheiden, wäre dabei das Problem.
Allerdings kann ich dabei vielleicht bei dem Aktuellen Algorithmus bleiben (Kommt ja nicht auf die Absolut genaue Zeit des Nulldurchgangs an): https://github.com/jedie/PyDragon32/blo ... DC.py#L203
Im Groben: Ein Nulldurchgang ist immer dann geschehen, wenn mehrere MIN_TOGGLE_COUNT Sample-Werte im Positiven oder Negativen Bereich sind.
Vielleicht das ganze in drei hintereinander geschalteten Generatoren:
1. Generator liefert die WAVE-Samples zurück iter_wave_values(): https://github.com/jedie/PyDragon32/blo ... DC.py#L134
2. Generator wartet auf die mehrere MIN_TOGGLE_COUNT Sample-Werte im Positiven oder Negativen Bereich und spuckt dann nur die rohen Zeiten aus.
3. Generator nimmt die Zeiten entgehen und bildet damit den Bit-Stream
@jens: Nein, nicht bei GOTO sondern bei den Zeilennummern und den Pointern auf die nächste Zeile. Da kann im Grunde jeder beliebige Bytewert, also auch die 0 vorkommen. Danach bis zum Ende der Zeile sollte kein Nullbyte mehr vorkommen.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Achso... Deswegen hab ich dich nicht verstanden... Ja klar, da kommen Null-Bytes vor. Aber das ist nicht das Problem.BlackJack hat geschrieben:@jens: Nein, nicht bei GOTO sondern bei den Zeilennummern und den Pointern auf die nächste Zeile. Da kann im Grunde jeder beliebige Bytewert, also auch die 0 vorkommen. Danach bis zum Ende der Zeile sollte kein Nullbyte mehr vorkommen.
Es kommen immer 2-Byte "Line-Pointer" dann 2-Byte "Zeilen-Nummer" dann X-Bytes Code bis 0x00
@jens: Ja, aber wenn Du das *so* verarbeitest, an welcher Stelle suchst Du denn dann nach drei Nullbytes? Darum ging es doch. Das Ende erkennt man in dem Fall doch an einem Nullpointer, also *zwei* Nullbytes, und auch nicht ohne Kontext, sondern in dem Wissen, dass man sich gerade am Anfang von den Daten einer neuen Zeile befindet. Und das hat ja schon alles nichts mehr mit dem Lesen vom Band zu tun.
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
Wüßte nicht wie man es anders machen kann.
An dieser Stelle ist das mit den zwei 0x00 Bytes: https://github.com/jedie/PyDragon32/blo ... DC.py#L699
Siehe auch das Beispiel von hier: http://www.python-forum.de/viewtopic.ph ... 35#p244435
EDIT: An dieser Stelle geht es um das Parsen der Roh "tokenized BASIC source code"
An dieser Stelle ist das mit den zwei 0x00 Bytes: https://github.com/jedie/PyDragon32/blo ... DC.py#L699
Siehe auch das Beispiel von hier: http://www.python-forum.de/viewtopic.ph ... 35#p244435
EDIT: An dieser Stelle geht es um das Parsen der Roh "tokenized BASIC source code"
@jens: Ähm, der Start dieser (Teil)Diskussion war, dass Du gesagt hast man könnte das Ende eines BASIC-Programms an den drei Nullbytes erkennen und darum wäre die Längenangabe überflüssig. Das Stand mal in diesem Beitrag: http://www.python-forum.de/viewtopic.ph ... 70#p244470
Hier mal eine Hilfsklasse zum Umwandeln von Bits in Integern, falls du es gebrauchen kannst:jens hat geschrieben:So... um es nochmal klar zu machen, was da überhaupt passiert:
1. WAV Sinus-Kurvenlänge -> Bitstream aus Nullen und Einsen
2. suche nach Muster "10101010" (0x55) Zeichenweise
3. in 8-Bit-Schritten weiter Springen, bis das Muster "10101010" nicht mehr vorkommt.
4. Suchen des Sync-Bits "00111100" (0x3C) Zeichenweise
Code: Alles auswählen
import collections
class BitContainer(object):
def __init__(self, bits=[], max_size=8):
self._bits = collections.deque(maxlen=max_size)
self.feed_iterable(bits)
def __repr__(self):
return '{}({})'.format(type(self).__name__, self.to_string())
def __str__(self):
return self.to_string()
def __len__(self):
return len(self._bits)
def __int__(self):
return self.to_integer()
def __iter__(self):
return iter(self._bits)
@property
def bits(self):
return list(self._bits)
def feed(self, bit):
bit = int(bit)
if not bit in (0, 1):
raise ValueError('bit must be 0 or 1')
self._bits.append(bit)
def feed_iterable(self, bits):
for bit in bits:
self.feed(bit)
def to_integer(self):
return sum(
bit << i for i, bit in enumerate(reversed(self._bits))
)
def to_string(self):
return ''.join(map(str, self._bits))
Code: Alles auswählen
bc = BitContainer()
for bit in bitstream:
bc.feed(bit)
if int(bc) == 0x55:
break
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
ja, anders herum: Die beiden 0x00 Bytes am Ende sind eigentlich Überflüssig. Denn wenn Block zu Ende, dann BASIC code zuende...BlackJack hat geschrieben:@jens: Ähm, der Start dieser (Teil)Diskussion war, dass Du gesagt hast man könnte das Ende eines BASIC-Programms an den drei Nullbytes erkennen und darum wäre die Längenangabe überflüssig. Das Stand mal in diesem Beitrag: http://www.python-forum.de/viewtopic.ph ... 70#p244470
- jens
- Python-Forum Veteran
- Beiträge: 8502
- Registriert: Dienstag 10. August 2004, 09:40
- Wohnort: duisburg
- Kontaktdaten:
So, hab den ASCII BASIC Parser fertig mit: https://github.com/jedie/PyDragon32/com ... 8130d21cfb
Dann noch die Block-Längenangabe geprüft: https://github.com/jedie/PyDragon32/com ... a821917447
Wobei das ein wenig Witzlos ist, denn ich schneide ja anhand der Block Länge auch wirklich den Code raus. Von daher kann die Länge ja beim parsen nicht anders sein...
@snafu: Deinen Code muß ich mir später ansehen.
Generell weiß ich nicht, wie früh man die Bits in Bytes umformen kann/sollte.
Dann noch die Block-Längenangabe geprüft: https://github.com/jedie/PyDragon32/com ... a821917447
Wobei das ein wenig Witzlos ist, denn ich schneide ja anhand der Block Länge auch wirklich den Code raus. Von daher kann die Länge ja beim parsen nicht anders sein...
@snafu: Deinen Code muß ich mir später ansehen.
Generell weiß ich nicht, wie früh man die Bits in Bytes umformen kann/sollte.
In welchem Zusammenhang meinst du das? Wegen möglichen Fehlinterpretationen, wenn man zu früh umwandelt, oder warum? Falls die Spec nichts anderes vorgibt, dann würde ich doch mal davon ausgehen, dass 1 Byte = 8 Bit.jens hat geschrieben:Generell weiß ich nicht, wie früh man die Bits in Bytes umformen kann/sollte.
Falls man sich eh immer solche Päckchen holt, dann braucht man natürlich keinen BitContainer mehr, sondern wirft die Päckchen einfach in eine Funktion ähnlich zu der `.to_integer()`-Methode in meinem Code.
@snafu: Warum der Umweg über deque?
Code: Alles auswählen
class BitContainer(object):
def __init__(self, bits=[], max_size=8):
self.bits = 0
self._mask = (1 << max_size) - 1
self.feed_iterable(bits)
def feed(self, bit):
bit = int(bit)
if not bit in (0, 1):
raise ValueError('bit must be 0 or 1')
self.bits = ((self.bits << 1) | bit) & self._mask
def feed_iterable(self, bits):
for bit in bits:
self.feed(bit)
Das Leben ist wie ein Tennisball.