Seite 2 von 3
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Dienstag 2. November 2010, 00:38
von /me
BlackJack hat geschrieben:[...] hier ist das ganze in Commodore BASIC V2:
Code: Alles auswählen
10 REM@ £PROTOCOL
20 REM@ £BOOLEAN T
30 REM@ £WORD R,X
40 REM@ £BYTE BS(,I,J
50 REM@ £CONSTANT MC
60 REM@ £FASTFOR:£FASTARRAY:£SHORTIF
[...]
Es ist zwar fürchterlich off-topic, aber da kommen gerade so Erinnerungen hoch. Waren das die Optimierungsanweisungen für den genialen Basic-Boss-Compiler?
Edit: Hmpfff, ich hätte dein Posting bis zum Ende lesen sollen ...
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Dienstag 2. November 2010, 05:44
von snafu
BlackJack hat geschrieben:@snafu: Deswegen haben viele dann ja auch auf Assembler zurückgegriffen.

Sieht gleich viel schöner aus:
Total. Besonders weil an einer Stelle "php" vorkommt.

Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Dienstag 2. November 2010, 10:12
von Hyperion
snafu hat geschrieben:
Total. Besonders weil an einer Stelle "php" vorkommt.

Steht hier aber für "push processor status"

Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Dienstag 2. November 2010, 10:13
von Hyperion
C4S3 hat geschrieben:
Weil, PB ist und bleibt halt eine Nischensprache. Dass jemand hier im Forum das kann, ist schon Zufall.
Naja, ich habe es mir aufgrund seiner "Kritik" ja mal angeguckt und ihm einen kommentierten Quellcode gepostet, in dem viele Basic-Anwesiungen schon finden. Das sollte ein PureBasic-Programmierer nun schon umsetzen können denke ich mal.
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Dienstag 2. November 2010, 11:10
von BlackJack
@snafu: Jau, man kann also sagen, dass es tatsächlich sinnvolle Anwendungen für ``php`` gibt. Wer hätte das gedacht.
Die Python-Implementierung skaliert übrigens nicht so toll. Weil `int` "beliebig" gross werden kann und bei den im Kommentar erwähnten 256 Byte Blöcken der Wert durch die innere Schleife 256×8 mal nach links geschiftet wird, kommen da im schlechtesten Fall Zahlen wie diese als Zwischenergebnisse heraus:
Code: Alles auswählen
In [169]: 0xffff << 256*8
Out[169]: 2101413319786998249728984856680763626227877776098249349189275711424790
70040488460533014802178427744797635888540894641871760512433376067214420810710892
87996099190228008087472708660566087190871282444136479359239936271984140172363496
44423522084359412984849571521528660735413764622347457804204706094753033573318562
47952866318396590504048549636113140302284669709409182650931299799997818086763192
76205650009931170151044828317929822746778327836784145249338504373004945022105438
47648321084137378340539793709308615847231307201783226365972374653736449964523944
473162743722728856545755042061834071287013436285969381059150244898406400L
Und das beim Berechnen für einen 16-Bit-Wert.
Das die Zwischensumme mehr Bits als das Ergebnis hat, sollte man ausnutzen um das Linksverschieben aus dem ``if``/``else`` zu ziehen, womit dann nur noch ein ``if`` bleibt. Wobei mir gerade auffällt, das man bei der 6510-Assembler-Implementierung ohne ``php`` und mit deutlich weniger Bytes -- 6 statt 11 -- im ersten Teil der inneren Schleife auskommt:
Und an der API würde ich ändern, dass man optional eine Zwischensumme übergeben kann, und das als Ergebnis eine Zahl heraus kommt. Dann kann man eine Prüfsumme auch über mehrere Datenpäckchen berechnen. Bin dann letztendlich hier gelandet:
Code: Alles auswählen
def calculate_checksum(block, checksum=SEED_CRC):
"""Calculate the checksum for a data block."""
for byte in block:
checksum ^= ord(byte) << 8
for dummy in xrange(8):
checksum <<= 1
if checksum & 0x10000:
checksum ^= MASK_CRC
checksum &= 0xffff
return ~checksum & 0xffff
(Der Syntax-Highlighter ist doof! Ich habe mal versucht ihn mit Unicode "auszutricksen".)
Eine Besonderheit beim Original ist wohl auch noch, dass das Ergebnis im Big-Endian-Format in eine Zwei-Byte-"Zeichenkette" formatiert wird.
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Dienstag 2. November 2010, 19:35
von funkheld
Jup, das ist der Boss-Compiler vom C64.
Habe die Basiczeilen halbwegs übernehmen können von der Checksumme, musste nur wieder die Bytes in Word reinbringen.
danke.
Gruss
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Dienstag 2. November 2010, 19:42
von funkheld
Das ist es:
Eine Bin-Datei einlesen und dann in eine Wav umwandeln von 44100hz und die Flanke hat 1000Baud , die dem Tape vom CPC464 entspricht.
Funktioniert schon halbswegs, kommt aber noch ein "Read_Error b" bei der Checksumme.
Obwohl die Checksumme jetzt stimmt.
Gruss
Code: Alles auswählen
SetCurrentDirectory(GetPathPart(ProgramFilename()))
Global *tonspeicher.l,*datspeicher.c,tonlaenge.l,datlaenge.l,zaehler.l
Global byte_bits.c,secs.f,i.l,h.l,pegel_0.l,pegel_1.l,bytespersec.l
Global block.l,block_header.l,block_data.l,block_sync.l,block_vor_nach.l
Global samplerate.l,bitrate.l,channels.l,volume.l,n_samples.l,n_dat.l,text1.l,text2.l
Global n_anf.l,dat_seg.l
Global seed_crc.u,mask_crc.u,crc_tmp.u,i.l,j.l
Global Dim head_byte.c(65)
Declare erstelle_wav()
Declare lade_datei()
Declare bit_0()
Declare bit_1()
Declare w_byte()
Declare pegel_0()
Declare checken()
Macro HiByte(word)
(word >> 8) & $FF
EndMacro
Macro Lobyte(word)
word & $FF
EndMacro
Procedure pegel_0()
For h=0 To pegel_0
PokeW(*tonspeicher+n_samples,-volume)
n_samples + 2
Next
EndProcedure
Procedure bit_0()
For h=0 To pegel_0
PokeW(*tonspeicher+n_samples,-volume)
n_samples + 2
Next
For h=0 To pegel_0
PokeW(*tonspeicher+n_samples,volume)
n_samples + 2
Next
EndProcedure
Procedure bit_1()
For h=0 To pegel_1
PokeW(*tonspeicher+n_samples,-volume)
n_samples + 2
Next
For h=0 To pegel_1
PokeW(*tonspeicher+n_samples,volume)
n_samples + 2
Next
EndProcedure
Procedure w_byte()
For i=7 To 0 Step -1
If (byte_bits & (1<<i))
bit_1()
Else
bit_0()
EndIf
Next i
EndProcedure
Procedure checken()
seed_crc=$ffff
mask_crc=$1021
crc_tmp=seed_crc
For i=0 To 255
crc_tmp=crc_tmp ! (PeekB(*datspeicher+i)*256)
For j=0 To 7
If crc_tmp & $8000
crc_tmp=(crc_tmp *2) ! mask_crc
Else
crc_tmp=crc_tmp*2
EndIf
Next
Next
crc_tmp=(crc_tmp & $ffff) ! $ffff
Debug (crc_tmp & $0000ffff)
Debug $77A1
EndProcedure
Procedure lade_datei()
If ReadFile(0, "cpc.bin")
datlaenge = Lof(0)
dat_seg=Round(datlaenge/256,#PB_Round_Up)
If dat_seg
*datspeicher = AllocateMemory(256*dat_seg)
ReadData(0, *datspeicher, datlaenge)
Else
CloseFile(0)
ProcedureReturn #False
EndIf
CloseFile(0)
channels = 1
bitrate = 16
samplerate = 44100
volume = 32760
bytespersec = channels*bitrate /8*samplerate
secs = 10
block=Round((datlaenge/2048), #PB_Round_Up)
block_vor_nach=512*block
block_sync=257*block
block_header=65*block
block_data=(2048+16)*block
tonlaenge = (block_sync+block_header+block_data+block_vor_nach)*34*8+44
*tonspeicher = AllocateMemory(tonlaenge )
pegel_1=30
pegel_0=15
EndIf
EndProcedure
Procedure erstelle_wav()
PokeS(*tonspeicher,"RIFF")
PokeL(*tonspeicher+4,36+bytespersec*secs)
PokeS(*tonspeicher+8,"WAVE")
PokeS(*tonspeicher+12,"fmt ")
PokeL(*tonspeicher+16,16)
PokeW(*tonspeicher+20,1)
PokeW(*tonspeicher+22,channels)
PokeL(*tonspeicher+24,samplerate )
PokeL(*tonspeicher+28,bytespersec)
PokeW(*tonspeicher+32,bitrate/8*channels)
PokeW(*tonspeicher+34,bitrate)
PokeS(*tonspeicher+36,"data")
PokeL(*tonspeicher+40,bytespersec*secs)
n_samples=44
;datenübertragung
For n_anf=0 To 4000; vorspann "0"-Pegel
pegel_0()
Next
For n_anf=0 To 2048-1 ; systemvorspann mit 2048x "1"
bit_1()
Next
bit_0()
byte_bits=44 ; sync-headeranfang
w_byte()
head_byte(0)=Asc("a")
head_byte(1)=Asc("1")
head_byte(2)=0
head_byte(3)=0
head_byte(4)=0
head_byte(5)=0
head_byte(6)=0
head_byte(7)=0
head_byte(8)=0
head_byte(9)=0
head_byte(10)=0
head_byte(11)=0
head_byte(12)=0
head_byte(13)=0
head_byte(14)=0
head_byte(15)=0
head_byte(16)=1
head_byte(17)=255
head_byte(18)=2
head_byte(19)=lobyte(datleange)
head_byte(20)=hibyte(datleange)
head_byte(21)=0
head_byte(22)=$40
head_byte(23)=255
head_byte(24)=lobyte(datleange)
head_byte(25)=hibyte(datleange)
head_byte(26)=0
head_byte(27)=0
For n_anf=28 To 63
head_byte(n_anf)=0
Next
For n_anf=0 To 63
byte_bits=head_byte(n_anf)
w_byte()
Next
byte_bits=22 ; sync-datenanfang
w_byte()
; block mit 2048 byte (8 sectoren zu 256 byte + 2 checkbyte)
For n_dat=0 To 256-1
byte_bits=PeekB(*datspeicher+n_dat)
w_byte()
Next
checken()
byte_bits=lobyte(crc_tmp) ; 2x checkbyte
w_byte()
byte_bits=hibyte(crc_tmp)
w_byte()
For n_anf=0 To 32-1 ; nachspann mit 32x "1"
bit_1()
Next
For n_anf=0 To 4000; nachspann "0"-Pegel
pegel_0()
Next
; ende datenübertragung
CreateFile(0, "wavtest.wav")
WriteData(0,*tonspeicher,tonlaenge)
CloseFile(0)
EndProcedure
InitSprite()
InitSound()
OpenWindow(0,0,0,600,400,"sound-test",#PB_Window_SystemMenu|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
OpenWindowedScreen(WindowID(0),220,10,300,300,0,0,0)
text1=TextGadget(#PB_Any, 10,20,120,20, "E-Erstellen, S-Spielen")
text2=TextGadget(#PB_Any, 10,40,180,20, "")
ClearScreen(RGB(128,128,128))
Repeat
Event.l = WaitWindowEvent(2)
If GetAsyncKeyState_(#VK_E)
lade_datei()
erstelle_wav()
SetGadgetText(text2,"Datenlänge= "+Str(datlaenge)+ " Tonlänge= "+ Str(tonlaenge))
EndIf
If GetAsyncKeyState_(#VK_S)
SetGadgetText(text2,"spielen")
EndIf
Until Event = #PB_Event_CloseWindow
End
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Dienstag 2. November 2010, 19:52
von BlackJack
@funkheld: Zumindest laut dem Python-Quelltext von Dir wird die Checksumme im Big-Endian-Format erzeugt, also das High-Byte zuerst.
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Dienstag 2. November 2010, 19:55
von funkheld
Bei mir war es zuerst Assembler, dann Basic auf dem C=64, dann Forth, dann C, dann Pascal, dann COBOL, PL/1, RPG, C++, ...
Na dann hast du ja auch nur ein Halbwissen, weil bei dir keine Beständigkeit drin ist.
Dann gehöre ich ja zu den Spezis, die wenigstens "Forth" komplett beherrschen ,BASIC vom C64 und das Basic vom CPC....
Mehr braucht man nicht zum Pensionärsleben.
Gruss
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Dienstag 2. November 2010, 19:57
von funkheld
Python-Quelltext
Der ist nicht von mir, den hat mir ein Franz zugeschustert im Forum.
Gruss
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Mittwoch 3. November 2010, 10:28
von funkheld
Wie kann ich diese jetzt als Zahl ausgeben mit Print.
danke.
gruss
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Mittwoch 3. November 2010, 10:30
von Hyperion
funkheld hat geschrieben:
Wie kann ich diese jetzt als Zahl ausgeben mit Print.
Denk doch mal drüber nach, was die äußeren Funktionen chr() machen.
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Mittwoch 3. November 2010, 10:35
von funkheld
Wenn ich "print aufruf(s))" ausgebe kommen nur 2 Buchstaben.
Wenn ich als "print ord(aufruf(s))" aufrufe, kommt eine Fehlermeldung.
gruss
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Mittwoch 3. November 2010, 10:37
von Hyperion
"Ausprobieren" ist ja auch nicht "nachdenken"! Lies doch mal in der Doku nach, was chr() macht. Und denke dann darüber nach, ob Du es brauchst
(Nebenbei: chr() hatte Dir auch in einem Thread schon mal jemand erklärt iirc)
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Mittwoch 3. November 2010, 10:44
von funkheld
Kommt eine Fehlermeldung bei print ord(a).
Gruss
Code: Alles auswählen
import os
def calculate_checksum(block):
"""
Calculate the checksum for a 256 bytes block
"""
# Constants
SEED_CRC = 0xFFFF # Seed for CRC
MASK_CRC = 0x1021 # Mask of CRC-16-CCITT (ISO 3309 / x^16 + x^12 + x^5 + 1)
crc_tmp = SEED_CRC # Initialize CRC
for i in block:
crc_tmp = crc_tmp ^ (ord(i) << 8)
for j in range(8):
if (crc_tmp & 0x8000):
crc_tmp = (crc_tmp << 1) ^ MASK_CRC
else:
crc_tmp = crc_tmp << 1
crc_tmp = (crc_tmp & 0xFFFF) ^ 0xFFFF # Make the CRC ones' complement
return chr(crc_tmp // 256) + chr(crc_tmp % 256)
laenge=os.path.getsize("cpc.bin")
print
print laenge," byte lesen"
print
f=open("cpc.bin", "rb")
s = f.read(laenge)
a=calculate_checksum(s)
print ord(a)
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Mittwoch 3. November 2010, 10:50
von funkheld
Code: Alles auswählen
a=str(calculate_checksum(s))
print repr(a)
print ord(a)
print a
Nur die erste "print" bringt Buchstaben. Bei den beiden anderen kommt eine Fehlermeldung.
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Mittwoch 3. November 2010, 10:50
von Hyperion
Aus der Doku:
Doku hat geschrieben:
chr(i)
Return a string of one character whose ASCII code is the integer i. For example, chr(97) returns the string 'a'. This is the inverse of ord(). The argument must be in the range [0..255], inclusive; ValueError will be raised if i is outside that range. See also unichr().
Also chr() verwandelt einen Integer-Wert in ein druckbares Zeichen - Du willst aber die Zahl.
Du versuchst das, mit ord() wieder rückgängig zu machen. Prinzipiell keine ganz schlechte Idee, aber da Du
zwei Zeichen als Argument übergibst, schlägt das eben fehl.
Sieh es doch mal so: Du hast einen roten Schrank und streichst den sofort blau. Dann willst Du ihn später wieder rot haben und versuchst ihn wieder rot zu streichen. Lass ihn doch von Anfang an rot!
(Das Gleichnis hinkt ein wenig, aber vom Prinzip passt es)
Denk also noch mal über die von Dir gepostete Zeile nach, wie man die "rot" lassen könnte.
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Mittwoch 3. November 2010, 11:29
von jerch
@Hyperion:
Ich liebe blumige Vergleiche (auch wenn Sie noch so hinken)
gesamten String als Zahl:
pro Byte:
Schau Dir doch bitte mal die Python-Doku an, insbesondere Datentypen und deren Methoden. Dann wird Dir schnell klar, was da vor sich geht.
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Mittwoch 3. November 2010, 11:48
von funkheld
Jup, danke.
Die 2 Ausgaben sind sehr hilfreich.
Bei der 1. sollte eine "hex" geprintet werden oder? es kommt eine Decimalzahl, macht aber nichts.
Gruss
Re: wer kann diese python-routine mal umsetzen in basic.
Verfasst: Mittwoch 3. November 2010, 11:50
von funkheld
Also chr() verwandelt einen Integer-Wert in ein druckbares Zeichen
Hmmm..., jetzt steh ich wieder auf dem Schlauch.
Kann man bei Python mit einem Integerwert(4byte) 4 druckbare zeichen mit einem Schwung ausgeben.
Gruss