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" :-D

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. :-D

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:

Code: Alles auswählen

inner_loop:
    asl tmp1
    rol tmp1+1
    bcc skip
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.... :D

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

Code: Alles auswählen

return chr(crc_tmp // 256) + chr(crc_tmp % 256)
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:

Code: Alles auswählen

return chr(crc_tmp // 256) + chr(crc_tmp % 256)
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:

Code: Alles auswählen

print int(dein_string.encode('hex'), 16)
pro Byte:

Code: Alles auswählen

print [ord(i) for i in dein_string]
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