{{ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Autor: Ingo Kripahle │ │ Copyright (c) 2010 Ingo Kripahle │ │ See end of file for terms of use. │ │ Die Nutzungsbedingungen befinden sich am Ende der Datei │ └──────────────────────────────────────────────────────────────────────────────────────────────────────┘ Informationen : hive-project.de Kontakt : drohne235@googlemail.com System : TriOS Name : Administra-Flash Chip : Administra Typ : Flash Version : 01 Subversion : 1 Komponenten : HSS 1.2 Andrew Arsenault Lizenz unklar FSRW 1.6 Radical Eye Software MIT Lizenz SDSPIQASM Radical Eye Software MIT Lizenz ASM WAV Player 1b Raymond Allen MIT Lizenz COG's : MAIN 1 COG HSS 2 COG's FSRW/SDSPI 1 COG WAV 1 COG - WAV und HSS werden alternativ verwendet! Logbuch : 14.11.2008 - erste version erstellt 13.03.2009 - sd_eof eingefügt 25.01.2009 - komfortableres interface für hss-player eingefügt 19.03.2009 - seek, ftime, fattrib und fsize eingefügt 22.08.2009 - getcogs eingefügt 09.01.2010 - fehler in sfx_fire korrigiert 10.01.2010 - fehler in sdw_stop - hss wurde nicht wieder gestartet 15.03.2010 - start trios Kommandoliste : #1 err.b> sd.mount - medium mounten #2 sd.dir - verzeichnis öffnen #3 0> len.b> name.b> sd.next - nächster eintrag im verzeichnis 1> - kein weiterer dateiname #4 >modus.b >len.b >name.s err.b> sd.open - datei öffnen #5 err.b> sd.close - datei schließen #6 daten.b> sd.getc - zeichen lesen #7 >daten.b sd.putc - zeichen schreiben #8 >len.b sd.getblk - block lesen #9 >len.b sd.putblk - block schreiben #100 >len.b >name.b err.b> hss.load - hss-datei in player laden #101 hss.play - musikdatei abspielen #102 hss.stop - musikwiedergabe beenden #103 hss.pause - musikwiedergabe pausieren #104 >1-byte-regnr 4-byte-regwert> hss.peek - register des players lesen #105 >1-byte-regnr 2-byte-regwert> hss.intreg - interfaceregister auslesen #106 >1-byte-vol hss.vol - volume einstellen 0..15 #107 >1-byte-slotnr >1-byte-channel - sfx in slotpuffer abspielen #108 >1-byte-slotnr >32-byte-sfxdaten - schreibt 32 byte slotpufferdaten #109 - sfx keyoff Notizen : }} CON _CLKMODE = XTAL1 + PLL16X _XINFREQ = 5_000_000 'signaldefinitionen administra #0, D0,D1,D2,D3,D4,D5,D6,D7 'datenbus #8, ADM_SOUNDL,ADM_SOUNDR 'sound (stereo 2 pin) #10, ADM_SDD0,ADM_SDCLK,ADM_SDCMD,ADM_SDD3 'sd-cardreader (4 pin) #23, ADM_SELECT 'administra-auswahlsignal #24, HBEAT 'front-led BUSCLK 'bustakt BUS_WR '/wr - schreibsignal BUS_HS ' '/hs - quittungssignal VER_H = 0 VER_L = 1 VER_S = 1 'subversion "wave" LED_OPEN = HBEAT SD_BASE = ADM_SDD0 'baspin cardreader DB_WAIT = %00000001_00000000_00000000_00000000 'dira-wert für datenbuseingabe DB_IN = %00001001_00000000_00000000_00000000 'dira-wert für datenbuseingabe DB_OUT = %00001001_00000000_00000000_11111111 'dira-wert für datenbusausgabe CNT_HBEAT = 5_000_0000 'blinkgeschw. front-led MPLEN = 16384 'größe des musikpuffers SECTORSIZE = 512 SCREENSIZE = 1024 'screengröße SECCOUNT = SCREENSIZE / SECTORSIZE 'anzahl sektoren pro screen SDWBUFSIZE = 100 OBJ sdfat : "admflash-fsrw" 'sd-card fat16 hss : "admflash-hss" 'hydra-sound-system wav : "admflash-wav" 'sd-wave VAR long stackhb[9] 'stack für hbeat-cog byte tbuf[20] 'stringpuffer byte bgmusic[MPLEN] 'hss-puffer byte sfxdat[16 * 32] 'sfx-slotpuffer byte fl_eof '1 = eof byte fl_snd '1 = systemtöne an byte fl_sndback byte cogs byte cog[8] ' variablen für screeninterface long s_start long s_maxscreen long s_screen long s_pos byte s_err byte s_pscreen[SCREENSIZE] ' variablen für sdwav-player long sdwp1 'parameter für play-cog long sdwp2 'müssen hintereinander liegen long sdwp3 long sdwp4 long sdwbuff1[SDWBUFSIZE] long sdwbuff2[SDWBUFSIZE] long sdwstack[10] byte sdwcog byte sdwflag byte sdwh[44] PUB main | zeichen {{interpreter für hostdialog}} init_subsysteme 'bus/vga/keyboard/maus initialisieren repeat zeichen := bus_getchar '1. zeichen empfangen case zeichen 0: !outa[LED_OPEN] 'led blinken 'fat16 filesystem 1: sd_mount 'sd-card mounten ' 2: sd_opendir 'direktory öffnen 3: sd_nextfile 'verzeichniseintrag lesen 4: sd_open 'datei öffnen 5: sd_close 'datei schließen 6: sd_getc 'zeichen lesen 7: sd_putc 'zeichen schreiben 8: sd_getblk 'block lesen 9: sd_putblk 'block schreiben 10: sd_eof 'eof-flag abfragen 11: sd_seek 'zeiger in datei positionieren 12: sd_fattrib 'attribute übergeben 13: sd_ftime 'zeitstempel übergeben 14: sd_fsize 'dateigröße übergeben 'screeninterface 50: scr_open 'containerdatei öffnen 51: scr_fill 'screenpuffer mit zeichen füllen 52: scr_read 'screen in den puffer laden 53: scr_write 'screen auf disk schreiben 54: scr_getnr 'nummer des aktuellen screens abfragen 55: scr_setpos 'zeiger auf position im puffer setzen 56: scr_getpos 'aktuelle position im puffer abfragen 57: scr_getc 'zeichen wird aus dem puffer gelesen 58: scr_putc 'zeichen wird in den puffer geschrieben 59: scr_flush 'aktuellen puffer auf disk schreiben 60: scr_err 'fehlerstatus abfragen 61: scr_maxscr 'screenanzahl in containerdatei abfragen 'global 80: getcogs 'freie cogs abfragen bus_putchar(cogs) 98: '98: codeversion abfragen bus_putchar(VER_H) bus_putchar(VER_L) bus_putchar(VER_S) 99: reboot '99: neu starten 'musikinterface 100: hss_load 'hss-datei in puffer laden 101: hss.hmus_load(@bgmusic) 'play hss.hmus_play 102: hss.hmus_stop 'stop 103: hss.hmus_pause 'pause 104: hss_peek 'register lesen 105: hss_intreg 'interfaceregister auslesen 106: hss_vol 'sound-fx 107: sfx_fire 108: sfx_setslot 109: sfx_keyoff 110: sfx_stop 'sdwav-player 150: sdw_start 'spielt wav-datei direkt von sd-card ab 151: sdw_stop 'stopt wav-cog 152: sdw_status 'fragt status des players ab PUB getcogs |i,c 'glob: abfragen wie viele cogs in benutzung sind {{ fragt freie cogs ab }} i :=0 cogs := 0 repeat 'loads as many cogs as possible and stores their cog numbers c := cog[i] := cognew(@entry, 0) if c=>0 i++ while c => 0 cogs := i repeat 'unloads the cogs and updates the string i-- if i=>0 cogstop(cog[i]) while i=>0 PUB sdw_play | err,srate,sam,n,j,w 'sdw: wav von sd-card abspielen ' - testcode!!! ' - sollte in einer extra cog laufen um nicht den interpreter zu blockieren ' - läuft leider nicht parallel zum hss!!! hss.stop 'hss stopen da sie sich sonst stören fl_sndback := fl_snd 'status der systemsounds merken fl_snd := 0 'sytemsound aus sdwflag := 1 outa[LED_OPEN] := 1 err := sdfat.pread(@sdwh, 44) 'headerdaten einlesen srate := sdwh[27]<<24+sdwh[26]<<16+sdwh[25]<<8+sdwh[24] 'samplerate auslesen sam := sdwh[43]<<24+sdwh[42]<<16+sdwh[41]<<8+sdwh[40] 'samples auslesen sam := sam >> 2 sdwp1 := @sdwbuff1[0] sdwp2 := @sdwbuff2[0] sdwp3 := (80_000_000)/(srate) '#clocks between samples'1814'for 44100ksps, 5000 'for 16ksps sdwp4 := sam wav.start(@sdwp1) 'wavcog starten w := 0 n:=SDWBUFSIZE-1 'nummer des letzten indexelements im puffer j:=SDWBUFSIZE*4 'number of bytes to read repeat while (j==SDWBUFSIZE*4) 'schleife bis unvollständiger puffer gelesen wurde (eof) if (sdwbuff1[n]==0) and w == 0 j:=sdfat.pread(@sdwbuff1, SDWBUFSIZE*4) 'read data words to input stereo buffer 'if(sdwbuff1[n]==0) ' sdwbuff1[n]:=1 outa[LED_OPEN] := 1 w := 1 if (sdwbuff2[n]==0) and w == 1 j:=sdfat.pread(@sdwbuff2, SDWBUFSIZE*4) 'read data words to input stereo buffer 'if (sdwbuff2[n]==0) ' sdwbuff2[n]:=1 outa[LED_OPEN] := 0 w := 0 wav.stop 'wavcog stopen sdfat.pclose 'datei schließen hss.start 'hss wieder starten fl_snd := fl_sndback 'status systemsound wiederherstellen outa[LED_OPEN] := 0 sdwflag := 0 'status des players auf inaktiv setzen repeat PUB sdw_start | len,j,err 'sdw: startet extra cog mit sdwav-engine sdw_stop 'ein evtl. noch laufenden player stopen clr_tbuf len := bus_getchar 'längenbyte name empfangen repeat j from 0 to len - 1 'dateiname einlesen tbuf[j] := bus_getchar sdfat.mount(SD_BASE) err := sdfat.popen(@tbuf, "r") 'datei öffnen bus_putchar(err) 'ergebnis der operation senden if err == 0 sdwcog := cognew(sdw_play,@sdwstack) + 1 'cog mit wavplayer starten PUB sdw_stop 'sdw: stopt cog mit sdwav-engine wav.stop 'wavcog stopen if sdwcog cogstop(sdwcog~ - 1) 'player stopen sdwflag := 0 'status des players auf inaktiv setzen outa[LED_OPEN] := 0 fl_snd := fl_sndback 'systemsound evtl. wieder einschlten hss.start 'hss wieder starten PUB sdw_status 'sdw: sendet status des wav-players bus_putchar(sdwflag) PUB scr_open | len,i,wert 'scr: containerdatei öffnen clr_tbuf 'stringpuffer löschen len := bus_getchar 'längenbyte name empfangen repeat i from 0 to len - 1 'dateiname einlesen tbuf[i] := bus_getchar wert := sdfat.sec_start(@tbuf) 'datei öffnen if wert == -1 'fehler bei öffnen der containerdatei if fl_snd == 1 hss.sfx_play(1, @SoundFX1) 'fehlersound s_start := 0 s_err := -1 else 'container vorhanden if fl_snd == 1 hss.sfx_play(1, @SoundFX4) 'heartbeat high s_start := wert 'startsektor setzen s_maxscreen := sdfat.getfsize s_maxscreen := s_maxscreen / SECTORSIZE /SECCOUNT - 1 'maximale screenzahl berechnen s_err := 0 bus_putchar(s_err) 'fehlernummer senden PUB scr_fill | i,char 'scr: screenpuffer mit zeichen füllen char := bus_getchar 'füllzeichen empfangen repeat i from 0 to SCREENSIZE - 1 'screenpuffer mit zeichen füllen s_pscreen[i] := char PUB scr_read | i,snr,badr 'scr: screen in den puffer laden if fl_snd == 1 hss.sfx_play(1, @SoundFX4) 'heartbeat high outa[LED_OPEN] := 1 s_screen := bus_getchar << 8 '16 bit screennnummer einlesen s_screen += bus_getchar if s_screen =< s_maxscreen repeat i from 0 to SECCOUNT-1 'sektoren in puffer einlesen snr := s_start + (s_screen * SECCOUNT) + i 'sektornummer berechnen badr := @s_pscreen + (i * SECTORSIZE) 'pufferadresse berechnen sdfat.sec_readblock(snr, badr) 'sektor einlesen s_err := 0 else s_err := 2 outa[LED_OPEN] := 0 PUB scr_write | i,snr,badr 'scr: screenpuffer auf disk schreiben if fl_snd == 1 hss.sfx_play(1, @SoundFX4) 'heartbeat high outa[LED_OPEN] := 1 s_screen := bus_getchar << 8 '16 bit screennnummer einlesen s_screen += bus_getchar if s_screen =< s_maxscreen scr_flush 'puffer auf disk schreiben s_err := 0 else s_err := 2 outa[LED_OPEN] := 0 PUB scr_flush | i,snr,badr 'scr: aktuellen puffer auf disk schreiben repeat i from 0 to SECCOUNT-1 'sektoren in puffer einlesen snr := s_start + (s_screen * SECCOUNT) + i 'sektornummer berechnen badr := @s_pscreen + (i * SECTORSIZE) 'pufferadresse berechnen sdfat.sec_writeblock(snr, badr) 'sektor einlesen PUB scr_getnr 'scr: nummer des aktuellen screens abfragen bus_putchar(s_screen >> 8) 'aktuelle screennummer senden bus_putchar(s_screen) PUB scr_setpos 'scr: zeiger auf position im puffer setzen s_pos := bus_getchar << 8 '16 bit position im puffer s_pos += bus_getchar PUB scr_getpos 'scr: aktuelle position im puffer abfragen bus_putchar(s_pos >> 8) bus_putchar(s_pos) PUB scr_getc 'scr: zeichen wird aus dem puffer gelesen bus_putchar(s_pscreen[s_pos++]) PUB scr_putc 'scr: zeichen wird in den puffer geschrieben s_pscreen[s_pos++] := bus_getchar PUB scr_err 'scr: fehlerstatus abfragen bus_putchar(s_err) PUB scr_maxscr 'scr: screenanzahl des containers abfragen bus_putchar(s_maxscreen >> 8) 'aktuelle screennummer senden bus_putchar(s_maxscreen) PUB sfx_fire | slot, chan, slotadr 'sfx: effekt im puffer abspielen slot := bus_getchar chan := bus_getchar 'channelnummer lesen if slot == $f0 hss.sfx_play(1, @SoundFX1) 'Play a sound effect on FX channel (1) if slot == $f1 hss.sfx_play(1, @SoundFX2) 'Play a sound effect on FX channel (1) if slot == $f2 hss.sfx_play(1, @SoundFX3) 'Play a sound effect on FX channel (1) if slot == $f3 hss.sfx_play(1, @SoundFX4) 'Play a sound effect on FX channel (1) if slot == $f4 hss.sfx_play(1, @SoundFX5) 'Play a sound effect on FX channel (1) if slot == $f5 hss.sfx_play(1, @SoundFX6) 'Play a sound effect on FX channel (1) if slot < $f0 slotadr := @sfxdat + (slot * 32) 'slotnummer lesen und adresse berechnen hss.sfx_play(chan, slotadr) PUB sfx_setslot | slotadr, i 'sfx: daten in sfx-slotpuffer schreiben slotadr := @sfxdat + (bus_getchar * 32) 'slotnummer lesen und adresse berechnen repeat i from 0 to 31 byte[slotadr + i] := bus_getchar 'sfx-daten einlesen PUB sfx_keyoff | chan 'sfx-keyoff chan := bus_getchar 'channelnummer lesen hss.sfx_keyoff(chan) PUB sfx_stop | chan 'sfx-keyoff chan := bus_getchar 'channelnummer lesen hss.sfx_stop(chan) PUB hss_vol 'hss: volume 0..15 einstellen hss.hmus_vol(bus_getchar) PUB hss_intreg | regnr,wert 'hss: auslesen der player-register {{hss_peek - hss: auslesen der player-register}} regnr := bus_getchar 'registernummer einlesen wert := hss.intread(regnr) bus_putchar(wert >> 8) '16-bit-wert senden hsb/lsb bus_putchar(wert) PUB hss_peek | regnr,wert 'hss: auslesen der player-register {{hss_peek - hss: auslesen der player-register}} regnr := bus_getchar 'registernummer einlesen wert := hss.peek(regnr) bus_putchar(wert >> 24) '32bit-registerwert senden hsb/lsb bus_putchar(wert >> 16) bus_putchar(wert >> 8) bus_putchar(wert) PUB hss_load | len,i,err 'hss: musikdatei in puffer laden {{hss_load - hss: musikdatei in puffer laden}} clr_tbuf len := bus_getchar 'längenbyte name empfangen repeat i from 0 to len - 1 'dateiname einlesen tbuf[i] := bus_getchar err := sdfat.popen(@tbuf, "r") 'datei öffnen bus_putchar(err) 'ergebnis der operation senden if err == 0 outa[LED_OPEN] := 1 sdfat.pread(@bgmusic, MPLEN) 'datei laden sdfat.pclose 'datei schließen outa[LED_OPEN] := 0 PUB sd_open | err,modus,len,i 'sd: datei öffnen {{sd_open - sd: datei öffnen}} clr_tbuf 'stringpuffer löschen modus := bus_getchar 'modus empfangen len := bus_getchar 'längenbyte name empfangen repeat i from 0 to len - 1 'dateiname einlesen tbuf[i] := bus_getchar err := sdfat.popen(@tbuf, modus) 'datei öffnen if err == 0 if fl_snd == 1 hss.sfx_play(1, @SoundFX3) 'Heartbeat High outa[LED_OPEN] := 1 if err <> 0 if fl_snd == 1 hss.sfx_play(1, @SoundFX1) 'Error bus_putchar(err) 'ergebnis der operation senden PUB sd_close | err 'sd: datei schließen {{sd_close - sd: datei schließen}} err := sdfat.pclose if err == 0 outa[LED_OPEN] := 0 if fl_snd == 1 hss.sfx_play(1, @SoundFX4) 'Heartbeat Low bus_putchar(err) 'ergebnis der operation senden PUB sd_getc | n 'sd: zeichen aus datei lesen {{sd_getc - sd: zeichen aus datei lesen}} n := sdfat.pgetc bus_putchar(n) if n == -1 fl_eof := 1 else fl_eof := 0 PUB sd_eof 'sd: abfragen ob eof erreicht ist {{sd_eof - sd: abfragen ob eof erreicht ist}} bus_putchar(fl_eof) PUB sd_putc 'sd: zeichen in datei schreiben {{sd_putc - sd: zeichen in datei schreiben}} sdfat.pputc(bus_getchar) PUB sd_getblk | len,i 'sd: block aus datei lesen {{sd_getblk - sd: block aus datei lesen}} len := bus_getchar 'niederwertiges byte empfangen len += bus_getchar << 8 'höherwertiges byte empfangen repeat i from 1 to len bus_putchar(sdfat.pgetc) PUB sd_putblk | len,i 'sd: block in datei schreiben {{sd_putblk - sd: block in datei schreiben}} len := bus_getchar repeat i from 1 to len sdfat.pputc(bus_getchar) PUB sd_nextfile | flag,i,len 'sd: nächsten eintrag aus verzeichnis holen {{sd_nextfile - sd: nächsten eintrag aus verzeichnis holen}} clr_tbuf 'stringpuffer löschen flag := sdfat.nextfile(@tbuf) 'nächsten eintrag holen bus_putchar(flag) 'status senden len := strsize(@tbuf) bus_putchar(len) if flag == 0 'flag = 0 - eintrag gültig repeat i from 0 to len - 1 'len byte dateinamen senden bus_putchar(tbuf[i]) PUB sd_opendir 'sd: verzeichnis öffnen {{sd_opendir - sd: verzeichnis öffnen}} sdfat.opendir if fl_snd == 1 hss.sfx_play(1, @SoundFX4) 'Heartbeat Low PUB sd_mount | err 'sd: sd-card mounten {{sd_mount - sd: sd-card mounten}} err := sdfat.mount(SD_BASE) 'karte mounten if err <> 0 if fl_snd == 1 hss.sfx_play(1, @SoundFX1) 'Play a sound effect on FX channel (1) bus_putchar(err) 'fehlerstatus senden PUB sd_seek | wert 'sd: zeiger in datei positionieren 'sd: zeiger in datei positionieren wert := bus_getchar << 24 '32bit wert empfangen hsb/lsb wert := wert + bus_getchar << 16 wert := wert + bus_getchar << 8 wert := wert + bus_getchar sdfat.pseek(wert) 'byteposition PUB sd_fattrib | wert 'sd: dateiattribute übergeben 'sd: dateiattribute übergeben wert := sdfat.getfattrib bus_putchar(wert) '1 byte PUB sd_ftime | wert 'sd: zeitstempel übergeben 'sd: zeitstempel übergeben wert := sdfat.getftime bus_putchar(wert >> 24) '32bit wert senden hsb/lsb bus_putchar(wert >> 16) bus_putchar(wert >> 8) bus_putchar(wert) PUB sd_fsize | wert 'sd: dateigröße übergeben 'sd: dateigröße übergeben wert := sdfat.getfsize bus_putchar(wert >> 24) '32bit wert senden hsb/lsb bus_putchar(wert >> 16) bus_putchar(wert >> 8) bus_putchar(wert) PUB init_subsysteme 'system: initialisierung des administra-chips {{init_subsysteme - initialisierung des administra-chips}} 'cognew(led_hbeat, @stackhb) 'heartbeat aktivieren bus_init 'bussignale initialisieren hss.start 'soundsystem starten fl_snd := 1 'systemsound an PUB bus_init 'system: initialisierung des bussystems {{bus_init - initialisierung des bussystems}} dira := db_in 'datenbus auf eingabe schalten outa[bus_hs] := 1 'handshake inaktiv PUB bus_putchar(zeichen) 'system: ein byte über bus ausgeben {{bus_putchar - ein byte über bus ausgeben}} waitpeq(%00000010_00000000_00000000_00000000,%00000010_10000000_00000000_00000000,0) 'busclk=1? & prop1=0? dira := db_out 'datenbus auf ausgabe stellen outa[7..0] := zeichen 'daten ausgeben outa[bus_hs] := 0 'daten gültig waitpeq(%00000000_00000000_00000000_00000000,%00000010_00000000_00000000_00000000,0) 'busclk=0? 'waitcnt(1_000 + cnt) 'zeit für master outa[bus_hs] := 1 'daten ungültig dira := db_in 'bus freigeben PUB bus_getchar : zeichen 'system: ein byte über bus empfangen {{bus_getchar - ein byte über bus empfangen}} waitpeq(%00000010_00000000_00000000_00000000,%00000010_10000000_00000000_00000000,0) 'busclk=1? & prop1=0? zeichen := ina[7..0] 'daten einlesen outa[bus_hs] := 0 'daten quittieren outa[bus_hs] := 1 waitpeq(%00000000_00000000_00000000_00000000,%00000010_00000000_00000000_00000000,0) 'busclk=0? PUB led_hbeat 'system: frontled {{led_hbeat - herzschlag für front-led}} dira := db_in repeat !outa[hbeat] waitcnt(cnt_hbeat + cnt) PRI clr_tbuf | i 'system: löscht textpuffer repeat i from 0 to 19 'puffer löschen tbuf[i] := 0 DAT 'dummyroutine für getcogs org ' ' Entry: dummy-assemblercode fuer cogtest ' entry jmp entry 'just loops DAT 'feste sfx-slots 'Wav 'Len 'Fre 'Vol 'LFO 'LFW 'FMa 'AMa SoundFX1 byte $01, $FF, $80, $0F, $0F, $00, $07, $90 'Att 'Dec 'Sus 'Rel byte $FF, $10, $00, $FF 'Wav 'Len 'Fre 'Vol 'LFO 'LFW 'FMa 'AMa SoundFX2 byte $05, $FF, $00, $0F, $04, $FF, $01, $05 'Att 'Dec 'Sus 'Rel byte $F1, $24, $00, $FF '16step Sequencer Table byte $F1, $78, $3C, $00, $00, $00, $F1, $78, $3C, $00, $00, $00, $00, $00, $00, $00 'Wav 'Len 'Fre 'Vol 'LFO 'LFW 'FMa 'AMa 'Heartbeat SoundFX3 byte $00, $FF, $06, $0F, $09, $FF, $04, $05 'Att 'Dec 'Sus 'Rel byte $F1, $F4, $F0, $0F byte $F1, $78, $3C, $00, $00, $00, $F1, $78, $3C, $00, $00, $00, $00, $00, $00, $00 'Wav 'Len 'Fre 'Vol 'LFO 'LFW 'FMa 'AMa 'Heartbeat low SoundFX4 byte $00, $FE, $06, $0f, $15, $FF, $04, $05 'Att 'Dec 'Sus 'Rel byte $F1, $F4, $F0, $0F byte $F1, $78, $3C, $00, $00, $00, $F1, $78, $3C, $00, $00, $00, $00, $00, $00, $00 'Wav 'Len 'Fre 'Vol 'LFO 'LFW 'FMa 'AMa 'Telefon SoundFX5 byte $05, $15, $4F, $0F, $01, $04, $05, $00 'Att 'Dec 'Sus 'Rel byte $FF, $00, $00, $FF 'Wav 'Len 'Fre 'Vol 'LFO 'LFW 'FMa 'AMa SoundFX6 byte $06, $FF, $5F, $0F, $01, $03, $01, $00 'Teleport 'Att 'Dec 'Sus 'Rel byte $FF, $14, $00, $FF {{ ┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ │ TERMS OF USE: MIT License │ ├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤ │Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation │ │files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, │ │modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software│ │is furnished to do so, subject to the following conditions: │ │ │ │The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.│ │ │ │THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE │ │WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR │ │COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, │ │ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ }}