From 7438cf59e844bd608ebe54ad84b90e02701a449c Mon Sep 17 00:00:00 2001 From: Nihilazo Date: Wed, 24 Nov 2021 07:58:18 +0000 Subject: [PATCH] nibble dice stuff --- dice.chr | Bin 0 -> 3968 bytes dice.tal | 13 + nibble-dice.tal | 618 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 631 insertions(+) create mode 100644 dice.chr create mode 100644 dice.tal create mode 100644 nibble-dice.tal diff --git a/dice.chr b/dice.chr new file mode 100644 index 0000000000000000000000000000000000000000..3b1d2ae78bf35ba512fbd6e416108b34945fedc4 GIT binary patch literal 3968 zcmeIuu?@g52t-jfVHD5e89V@;$MZZcEEKRpmdK~M;&c>GghK!U1Q0*~0R#|0009IL uK;Q=g+AL2h_whV=^OjAe@|I^y<+sx|dLLH1$TjEk+F7>or*@ug{CNOtmP*k8 literal 0 HcmV?d00001 diff --git a/dice.tal b/dice.tal new file mode 100644 index 0000000..7df7e3a --- /dev/null +++ b/dice.tal @@ -0,0 +1,13 @@ +|1000 + +@nibble-dice-empty ( top left, top right, bottom left, bottom right ) +&tl 00 1f 3f 7f 7f 7f 7f 7f 00 1f 3f 7f 7f 7f 7f 7f +&tr 00 f8 fc fe fe fe fe fe 00 f8 fc fe fe fe fe fe +&bl 7f 7f 7f 7f 7f 3f 1f 00 7f 7f 7f 7f 7f 3f 1f 00 +&br fe fe fe fe fe fc f8 00 fe fe fe fe fe fc f8 00 + +@nibble-dice-dot ( top left, top right, bottom left, bottom right ) +&tl 00 1f 3f 7f 7f 7f 7f 7f 00 1f 3f 73 61 61 73 7f +&tr 00 f8 fc fe fe fe fe fe 00 f8 fc ce 86 86 ce fe +&bl 7f 7f 7f 7f 7f 3f 1f 00 7f 73 61 61 73 3f 1f 00 +&br fe fe fe fe fe fc f8 00 fe ce 86 86 ce fc f8 00 diff --git a/nibble-dice.tal b/nibble-dice.tal new file mode 100644 index 0000000..2434f49 --- /dev/null +++ b/nibble-dice.tal @@ -0,0 +1,618 @@ +( nibble-dice-tracker.tal ) +( 3-channel music tracker based on the nibble dice described by maleza ) +( sejo cc0 12021 ) +( +# controls + +* Arrow key up, or 'k' : move cursor to previous byte +* Arrow key down, or 'j': move cursor to next byte +* Arrow key left, or 'h': move cursor to previous nibble +* Arrow key right, or 'l': move cursor to next nibble +* 'Ctrl' or '+': increment nibble +* 'Alt' or '-': decrement nibble +* '0' to '9' and 'a' to 'f': assign value to nibble + +more info: https://compudanzas.net/nibble_dice_tracker.html +) + +%RTN { JMP2r } + +%inc-ptr-reg-nib { .ptr-register-nibbles STHk LDZ #01 ADD #7f AND STHr STZ } +%inc-ptr-reg-byt { .ptr-register-nibbles STHk LDZ #02 ADD #7f AND STHr STZ } +%dec-ptr-reg-nib { .ptr-register-nibbles STHk LDZ #01 SUB #7f AND STHr STZ } +%dec-ptr-reg-byt { .ptr-register-nibbles STHk LDZ #02 SUB #7f AND STHr STZ } +%PRINT-DIGIT { DUP #30 ADD .Console/write DEO } +%PRINT-NL { #0a .Console/write DEO } +%MOD { DIVk MUL SUB } +%MOD2 { DIV2k MUL2 SUB2 } + +%ADD-OFFSET { .devoffset LDZ ADD } + +( devices ) + +|00 @System [ &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 ] +|10 @Console [ &vector $2 &read $1 &pad $5 &write $1 ] +|20 @Screen [ &vector $2 &width $2 &height $2 &pad $2 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1 ] +|30 @Audio0 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] +|40 @Audio1 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] +|50 @Audio2 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] +|60 @Audio3 [ &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1 ] +|70 @Midi [ &vector $2 &channel $1 ¬e $1 &velocity $1 ] +|80 @Controller [ &vector $2 &button $1 &key $1 ] +|90 @Mouse [ &vector $2 &x $2 &y $2 &state $1 &wheel $1 ] +|a0 @File [ &vector $2 &success $2 &offset $2 &pad $2 &name $2 &length $2 &load $2 &save $2 ] +|b0 @DateTime [ &year $2 &month $1 &day $1 &hour $1 &minute $1 &second $1 &dotw $1 &doty $2 &isdst $1 ] + +( constants ) + +%die-color-normal { #c1 } +%die-color-invert { #c4 } +%beat-color-played { #02 } +%beat-color-notplayed { #01 } +%column-size { #08 } +%num-bytes { #30 } ( number of bytes shown as dice ) + +%col-sep { #0024 } ( separation between byte columns: 20 for the byte, 4 as space ) +%col-height { #0080 } ( 8 rows of 2x8 pixels each ) +%col-width { #0020 } ( 2 columns of 2x8 pixels each ) +%dev-width { #0044 } ( col-sep + col-width ) +%num-devices { #03 } +%num-cols { #06 } +%dev-total-width { #00cc } ( 204: 3*(col-sep + col-width) + + +( variables ) + +|0000 +( ) +@ptr-register-nibbles $1 +@framecount $2 + +@pos-x-devsep 0000 +@pos-y-dev $2 +@pos-x-dev +&dev00 $2 &dev01 $2 ( short pos x of each column ) +&dev10 $2 &dev11 $2 +&dev20 $2 &dev21 $2 + + +( temp variables ) +@die-color $1 +@high-nibble $1 +@low-nibble $1 +@devoffset $1 +@shortoffset $1 +@offset $1 + +( registers ) +@registers +@dev0 +&period $1 &pattern $1 &beatcount $1 &adsr $2 &volume $1 &sample $2 +&melody $8 +@dev1 +&period $1 &pattern $1 &beatcount $1 &adsr $2 &volume $1 &sample $2 +&melody $8 +@dev2 +&period $1 &pattern $1 &beatcount $1 &adsr $2 &volume $1 &sample $2 +&melody $8 + + +( program ) +@main +|0100 ( -> ) + + ( theme ) + #17ce .System/r DEO2 + #118d .System/g DEO2 + #173c .System/b DEO2 + + ( center y axis ) + .Screen/height DEI2 + col-height SUB2 #0002 DIV2 + .pos-y-dev STZ2 + + .Screen/width DEI2 + dev-total-width + SUB2 #0004 DIV2 ( calculate separation between devices ) + DUP2 + .pos-x-devsep STZ2 + + ( assign x positions ) + ( pos-x-devsep is in the stack ) + STH2k + DUP2 .pos-x-dev/dev00 STZ2 + DUP2 #0024 ADD2 .pos-x-dev/dev01 STZ2 + + DUP2 ADD2 ( 2* pos-x-devsep ) + + DUP2 #0044 ADD2 .pos-x-dev/dev10 STZ2 + DUP2 #0068 ADD2 .pos-x-dev/dev11 STZ2 + + STH2r ADD2 ( 3* pos-x-devsep ) + + DUP2 #0088 ADD2 .pos-x-dev/dev20 STZ2 + #00ac ADD2 .pos-x-dev/dev21 STZ2 + + + ( set initial values ) + #00 + &loop-load + STHk ( store and keep counter ) + #00 SWP ( make short ) + ;initial-values ADD2 LDA ( load value ) + STHkr ( retrieve and keep counter ) + .dev0 ADD ( add counter to address ) + STZ ( store byte ) + STHr #01 ADD ( retrieve and increment counter ) + DUP num-bytes LTH ,&loop-load JCN + POP + + #00 .ptr-register-nibbles STZ + + ;on-frame .Screen/vector DEO2 + ;on-controller .Controller/vector DEO2 + ,draw-columns JSR +BRK + +@draw-columns ( -- ) + #00 + &loop + STHk + ;draw-column JSR2 + STHr #01 ADD DUP + #06 LTH ,&loop JCN + POP +RTN + +@initial-values +( period pattern beatcount adsr volume sample melody ) +&dev0 10 77 08 1ff1 77 0100 2d29 2629 2d29 262d +&dev1 08 f7 08 1ff1 aa 2100 3935 3235 3935 3239 +&dev2 10 55 08 1121 77 18ff 4541 3e45 413e 4541 +00 + + + +@samples +:saw ( 0 ) +:main ( 1 ) +:piano ( 2 ) +:tri ( 3 ) + +@on-frame ( -> ) + #00 ;update-dev JSR2 + #01 ;update-dev JSR2 + #02 ;update-dev JSR2 + + ( inc framecount ) + .framecount LDZ2 #0001 ADD2 .framecount STZ2 +BRK + +@on-controller ( -> ) + .Controller/button DEI + DUP #10 AND ;&up JCN2 + DUP #20 AND ;&down JCN2 + DUP #40 AND ;&left JCN2 + DUP #80 AND ;&right JCN2 + DUP #01 AND ;&inc-nibble JCN2 ( ctrl ) + DUP #02 AND ;&dec-nibble JCN2 ( alt ) + POP + + .Controller/key DEI + DUP LIT 'j EQU ,&down JCN + DUP LIT 'k EQU ,&up JCN + DUP LIT 'h EQU ,&left JCN + DUP LIT 'l EQU ,&right JCN + DUP LIT '+ EQU ,&inc-nibble JCN + DUP LIT '- EQU ,&dec-nibble JCN + DUP #2f GTH ,&check-dec-digit JCN + POP BRK + &check-dec-digit + DUP #3a LTH ,&assign-dec-digit JCN + DUP #60 GTH ,&check-hex-digit JCN + POP BRK + &check-hex-digit + DUP LIT 'g LTH ,&assign-hex-digit JCN + &done + POP BRK + + &down + inc-ptr-reg-byt + ,&close JMP + &up + dec-ptr-reg-byt + ,&close JMP + &left + inc-ptr-reg-nib + ,&close JMP + &right + dec-ptr-reg-nib + ,&close JMP + &inc-nibble ( increment nibble ) + #01 ;add-to-nibble JSR2 + ,&close JMP + &dec-nibble ( dec nibble ) + #ff ;add-to-nibble JSR2 + ,&close JMP + &assign-dec-digit + DUP ( previous cases still carry the key in the stack ) + #30 SUB + ;assign-to-nibble JSR2 + ,&close JMP + &assign-hex-digit + DUP ( previous cases still carry the key in the stack ) + #57 SUB + ;assign-to-nibble JSR2 + + &close + ( only draw updated columns ) + .ptr-register-nibbles LDZ DUP + #10 MOD DUP #01 GTH ,&check-mod-is-0f JCN + &mod-is-0-or-1 + POP ( if the pointer is at 0 or 1 of a column, also update previous column ) + DUP #02 SUB #10 DIV ;draw-column JSR2 + ,&draw-current-column JMP + + &check-mod-is-0f + ( if the pointer is at e or f of a column, also update next column ) + #0e LTH ,&draw-current-column JCN + DUP #02 ADD #10 DIV ;draw-column JSR2 + ,&draw-current-column JMP + + &draw-current-column + #10 DIV ( divide pointer over 16 to find column number ) + ;draw-column JSR2 +BRK + + + +@update-dev ( devnum -- ) + ( transform devnum to offsets ) + DUP #01 ADD .offset STZ + DUP #02 MUL .shortoffset STZ + #10 MUL .devoffset STZ + + .dev0/period ADD-OFFSET LDZ DUP ,&apply-period JCN + &no-period + POP + &done + RTN + &apply-period + #00 SWP ( build period as short ) + .framecount LDZ2 SWP2 MOD2 ( apply period ) + SWP POP ( remove high nibble ) + ,&done JCN + + &check-beatcount + .dev0/beatcount ADD-OFFSET LDZ #0f AND DUP ,&apply-beatcount JCN + &no-beatcount + POP RTN + &apply-beatcount + #00 SWP ( build beatcount as short ) + + .framecount LDZ2 ( load framecount ) + #00 .dev0/period ADD-OFFSET LDZ DIV2 ( get framecount/period ) + + SWP2 MOD2 ( apply mod beatcount ) + + SWP POP ( remove high nibble ) + .dev0/beatcount ADD-OFFSET LDZ #04 SFT ( get beat offset ) + ADD #07 AND ( apply offset and mask beat ) + STHk ( stash + keep current beat ) ( PRINT-DIGIT ) + + ( check pattern ) + .dev0/pattern ADD-OFFSET LDZ + SWP SFT #01 AND ( shift pattern beat bits to the right, and mask bit ) + ,&play-sound JCN + &no-play + #00 STH ( didn't play ) + ,&draw-beat JMP + + &play-sound + #00 .dev0/sample ADD-OFFSET LDZ #30 AND #03 SFT ;samples ADD2 LDA2 ( get sample offset to play ) + .Audio0/addr ADD-OFFSET DEO2 ( set sample address ) + .dev0/sample ADD-OFFSET LDZ2 #0fff AND2 .Audio0/length ADD-OFFSET DEO2 ( set sample length ) + .dev0/volume ADD-OFFSET LDZ .Audio0/volume ADD-OFFSET DEO + .dev0/adsr ADD-OFFSET LDZ2 .Audio0/adsr ADD-OFFSET DEO2 + .dev0/melody ADD-OFFSET STHkr ( get beat ) ADD LDZ .Audio0/pitch ADD-OFFSET DEO + + #01 STH ( played ) + + &draw-beat + ( draw beat ) + ;pos-x-devsep LDA2 col-sep ADD2 + #00 .offset LDZ MUL2 ( calculate x ) + #00 .offset LDZ #01 SUB col-width MUL2 ADD2 + #000c ADD2 ( center in column ) + STHr ( get played ) STHr ( get beat ) SWP ,draw-beat JSR +RTN + + +@draw-beat ( x2 beat played -- ) + ,&played JCN + ¬played + beat-color-notplayed ,&color STR + ,&start JMP + &played + beat-color-played ,&color STR + ,&start JMP + &color $1 + + &start + ;square .Screen/addr DEO2 + STH ( store beat ) + + ( col-sep ADD2 #000c ADD2 ) + .Screen/x DEO2 + + ( clear beats ) + #00 + &loop + STHk + #00 SWP #10 MUL ;pos-y-dev LDA2 ADD2 STH2k .Screen/y DEO2 + #00 .Screen/sprite DEO + STH2r #0008 ADD2 .Screen/y DEO2 + #00 .Screen/sprite DEO + + STHr #01 ADD DUP + #08 LTH ,&loop JCN + POP + + STHr ( recover beat ) + #00 SWP #10 MUL ;pos-y-dev LDA2 ADD2 STH2k .Screen/y DEO2 + ,&color LDR .Screen/sprite DEO + STH2r #0008 ADD2 .Screen/y DEO2 + ,&color LDR .Screen/sprite DEO +RTN + + + + +@draw-column ( num -- ) + STHk + #02 MUL ( create offset for x position ) + .pos-x-dev ADD LDZ2 + .pos-y-dev LDZ2 + STHr #08 MUL ( calculate pointer offset ) + ;draw-bytes JSR2 +RTN + +@add-to-nibble ( a -- ) ( add a to nibble pointed by ptr-register-nibbles ) + ,&num STR + ,&start JMP + &num $1 + &start + #00 + .ptr-register-nibbles LDZ ( get register address ) + #01 SFT ;registers ADD2 ( calculate register address+offset ) + STH2k ( store and keep address+offset ) + LDA ( get register contents ) + DUP ( duplicate byte ) + #04 SFT .high-nibble STZ ( store high nibble ) + #0f AND .low-nibble STZ ( store low nibble ) + .ptr-register-nibbles LDZ + #01 AND ( are we in high 1 or low 0 nibble? ) + ,&inc-high-nibble JCN + &inc-low-nibble + .low-nibble STHk LDZ ,&num LDR ADD #0f AND ( increment and mask low nibble ) + STHr STZ + ,&finish JMP + &inc-high-nibble + .high-nibble STHk LDZ ,&num LDR ADD #0f AND ( increment and mask low nibble ) + STHr STZ + &finish + .high-nibble LDZ #40 SFT .low-nibble LDZ ORA ( reassemble byte ) + STH2r ( recover byte address ) + STA +RTN + +@assign-to-nibble ( x -- ) ( assing x to nibble pointed by ptr-register-nibbles ) + ,&num STR + ,&start JMP + &num $1 + &start + #00 + .ptr-register-nibbles LDZ ( get register address ) + #01 SFT ;registers ADD2 ( calculate register address+offset ) + STH2k ( store and keep address+offset ) + LDA ( get register contents ) + DUP ( duplicate byte ) + #04 SFT .high-nibble STZ ( store high nibble ) + #0f AND .low-nibble STZ ( store low nibble ) + .ptr-register-nibbles LDZ + #01 AND ( are we in high 1 or low 0 nibble? ) + ,&inc-high-nibble JCN + &inc-low-nibble + ,&num LDR .low-nibble STZ + ,&finish JMP + &inc-high-nibble + ,&num LDR .high-nibble STZ + &finish + .high-nibble LDZ #40 SFT .low-nibble LDZ ORA ( reassemble byte ) + STH2r ( recover byte address ) + STA +RTN + +@draw-bytes ( x2 y2 ptr-offset -- ) + ( can be modified to be: x2 y2 ptr-addrZ ptr-offset bytesaddrA -- ) + ;registers ,&addr STR2 ( starting address of bytes ) + ,&offset STR ( starting offset of these bytes ) + .ptr-register-nibbles ,&ptr-addr STR ( address of pointer to bytes ) + ,&start JMP + &addr $2 + &offset $1 + &ptr-addr $1 + &start + ,&offset LDR +( #00 ) + &loop + STH + OVR2 OVR2 ( duplicate x2 y2 ) + STHkr ( copy counter ) + #00 SWP ,&addr LDR2 ADD2 LDA ( add counter as offset to address ) + ,&ptr-addr LDR LDZ ( load pointer ) + #01 SFT ( shift right to get byte number ) + STHkr ( retrieve counter, copying ) + NEQ ,&normal-mode JCN + ( byte is selected ) + ,&ptr-addr LDR LDZ ( load pointer ) + #01 AND #01 ADD ( get rightmost bit and add one to get mode ) + ,&draw JMP + &normal-mode + #00 ( mode ) + &draw + ,draw-byte JSR + #0010 ADD2 ( increment y ) + STHr ( recover counter ) + #01 ADD DUP column-size ,&offset LDR ADD NEQ ,&loop JCN + POP POP2 POP2 ( pop counter, x and y ) +RTN + +@draw-byte ( x2 y2 byte mode -- ) + DUP + #01 AND ,&low-nibble-mode STR ( mode 1 ) + #01 SFT #01 AND ,&high-nibble-mode STR ( mode 2 ) + ,&start JMP + + &high-nibble-mode $1 + &low-nibble-mode $1 + + &start + STH ( stash byte ) + OVR2 OVR2 ( duplicate coordinates ) + STHr DUP STH ( restore, duplicate, stash byte ) + #04 SFT #0f AND ( get high nibble ) + ,&high-nibble-mode LDR + ,draw-nibble JSR ( draw high nibble ) + + SWP2 #0010 ADD2 SWP2 ( increment x ) + + STHr ( restore byte ) + #0f AND ( get low nibble ) + ,&low-nibble-mode LDR + ,draw-nibble JSR ( draw low nibble ) + +RTN + + +@draw-nibble ( x2 y2 num mode -- ) + ,&set-invert JCN ( check mode: 0 is normal, nonzero is inverted ) + &set-normal + die-color-normal .die-color STZ + ,&start JMP + + &set-invert + die-color-invert .die-color STZ + + &start + ( bit 3 ) + STH + .Screen/y DEO2 + .Screen/x DEO2 + STHkr + #03 SFT ( get bit ) + ;nibble-dice-empty/tl + ,draw-bit JSR + + ( bit 2 ) + STHkr + .Screen/x DEI2 #0008 ADD2 .Screen/x DEO2 ( increment x ) + #02 SFT ( get bit ) + ;nibble-dice-empty/tr + ,draw-bit JSR + + ( bit 0 ) + STHkr + .Screen/y DEI2 #0008 ADD2 .Screen/y DEO2 ( increment y ) + ;nibble-dice-empty/br + ,draw-bit JSR + + ( bit 1 ) + STHr + .Screen/x DEI2 #0008 SUB2 .Screen/x DEO2 ( decrement x ) + #01 SFT ( get bit ) + ;nibble-dice-empty/bl + ,draw-bit JSR +RTN + +@draw-bit ( number empty-tile-addr -- ) + STH2 ( stash address ) + #01 AND ( get lsb from number ) + #40 MUL #00 SWP ( convert to offset ) + STH2r ( retrieve address ) + ADD2 ( add offset to address ) + .Screen/addr DEO2 + .die-color LDZ .Screen/sprite DEO +RTN + +( sprites ) +@square +ffff ffff ffff ffff + +@nibble-dice-empty ( top left, top right, bottom left, bottom right ) +&tl 00 1f 3f 7f 7f 7f 7f 7f 00 1f 3f 7f 7f 7f 7f 7f +&tr 00 f8 fc fe fe fe fe fe 00 f8 fc fe fe fe fe fe +&bl 7f 7f 7f 7f 7f 3f 1f 00 7f 7f 7f 7f 7f 3f 1f 00 +&br fe fe fe fe fe fc f8 00 fe fe fe fe fe fc f8 00 + +@nibble-dice-dot ( top left, top right, bottom left, bottom right ) +&tl 00 1f 3f 7f 7f 7f 7f 7f 00 1f 3f 73 61 61 73 7f +&tr 00 f8 fc fe fe fe fe fe 00 f8 fc ce 86 86 ce fe +&bl 7f 7f 7f 7f 7f 3f 1f 00 7f 73 61 61 73 3f 1f 00 +&br fe fe fe fe fe fc f8 00 fe ce 86 86 ce fc f8 00 + + +( samples ) + +( from the audio.channels.tal uxn example ) +@saw + 0003 0609 0c0f 1215 181b 1e21 2427 2a2d + 3033 3639 3b3e 4143 4649 4b4e 5052 5557 + 595b 5e60 6264 6667 696b 6c6e 7071 7274 + 7576 7778 797a 7b7b 7c7d 7d7e 7e7e 7e7e + 7f7e 7e7e 7e7e 7d7d 7c7b 7b7a 7978 7776 + 7574 7271 706e 6c6b 6967 6664 6260 5e5b + 5957 5552 504e 4b49 4643 413e 3b39 3633 + 302d 2a27 2421 1e1b 1815 120f 0c09 0603 + 00fd faf7 f4f1 eeeb e8e5 e2df dcd9 d6d3 + d0cd cac7 c5c2 bfbd bab7 b5b2 b0ae aba9 + a7a5 a2a0 9e9c 9a99 9795 9492 908f 8e8c + 8b8a 8988 8786 8585 8483 8382 8282 8282 + 8182 8282 8282 8383 8485 8586 8788 898a + 8b8c 8e8f 9092 9495 9799 9a9c 9ea0 a2a5 + a7a9 abae b0b2 b5b7 babd bfc2 c5c7 cacd + d0d3 d6d9 dcdf e2e5 e8eb eef1 f4f7 fafd +@tri + 8082 8486 888a 8c8e 9092 9496 989a 9c9e + a0a2 a4a6 a8aa acae b0b2 b4b6 b8ba bcbe + c0c2 c4c6 c8ca ccce d0d2 d4d6 d8da dcde + e0e2 e4e6 e8ea ecee f0f2 f4f6 f8fa fcfe + fffd fbf9 f7f5 f3f1 efed ebe9 e7e5 e3e1 + dfdd dbd9 d7d5 d3d1 cfcd cbc9 c7c5 c3c1 + bfbd bbb9 b7b5 b3b1 afad aba9 a7a5 a3a1 + 9f9d 9b99 9795 9391 8f8d 8b89 8785 8381 + 7f7d 7b79 7775 7371 6f6d 6b69 6765 6361 + 5f5d 5b59 5755 5351 4f4d 4b49 4745 4341 + 3f3d 3b39 3735 3331 2f2d 2b29 2725 2321 + 1f1d 1b19 1715 1311 0f0d 0b09 0705 0301 + 0103 0507 090b 0d0f 1113 1517 191b 1d1f + 2123 2527 292b 2d2f 3133 3537 393b 3d3f + 4143 4547 494b 4d4f 5153 5557 595b 5d5f + 6163 6567 696b 6d6f 7173 7577 797b 7d7f +@piano + 8182 8588 8d91 959b a1a6 aaad b2b5 b8bd + c1c7 cbd0 d5d9 dde1 e5e5 e4e4 e1dc d7d1 + cbc5 bfb8 b2ac a6a2 9c97 928d 8884 807c + 7977 7574 7372 7272 7273 7372 706d 6964 + 605b 5650 4d49 4643 4342 4244 4548 4a4d + 5052 5556 5758 5554 5150 4c4a 4744 423f + 3d3c 3a38 3835 3431 3030 2f31 3336 393e + 4449 4e54 5a60 666b 7175 7b82 8990 989e + a6ab b1b6 babd bebf bfbe bbb9 b6b3 b0ae + aaa8 a6a3 a19e 9c9a 9997 9696 9798 9b9e + a1a4 a6a9 a9ac adad adae aeaf b0b0 b1b1 + b3b3 b4b4 b4b3 b3b1 b0ad abab a9a9 a8a8 + a7a5 a19d 9891 8b84 7e77 726e 6b6b 6b6c + 6f71 7477 7776 7370 6c65 5e56 4e48 423f + 3d3c 3b3a 3a39 3838 3839 393a 3c3e 4146 + 4a50 575b 6064 686a 6e70 7274 7677 7a7d