From 3ae2597261c581583faf4fd932eb91f9cb9d86c1 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 17 Aug 2019 11:49:30 +0200 Subject: [PATCH] irq driven music player example --- .../target/c64/codegen/ForLoopsAsmGen.kt | 2 + docs/source/todo.rst | 3 + examples/arithmetic/bitshift.p8 | 2 + examples/bdmusic_irq.p8 | 74 +++++++++++++++++++ examples/cube3d-sprites.p8 | 19 ++--- examples/cube3d.p8 | 30 ++++---- examples/testforloops.p8 | 2 + 7 files changed, 108 insertions(+), 24 deletions(-) create mode 100644 examples/bdmusic_irq.p8 diff --git a/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt b/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt index 741c5f1dd..a2f33cc47 100644 --- a/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/codegen/ForLoopsAsmGen.kt @@ -250,6 +250,7 @@ $continueLabel inc $loopLabel+1 $endLabel""") } DataType.ARRAY_UB, DataType.ARRAY_B -> { + // TODO: optimize loop code when the length of the array is < 256, don't need a separate counter in such cases val length = decl.arraysize!!.size()!! if(stmt.loopRegister!=null && stmt.loopRegister!= Register.A) throw AssemblyError("can only use A") @@ -276,6 +277,7 @@ $counterLabel .byte 0 $endLabel""") } DataType.ARRAY_W, DataType.ARRAY_UW -> { + // TODO: optimize loop code when the length of the array is < 256, don't need a separate counter in such cases val length = decl.arraysize!!.size()!! * 2 if(stmt.loopRegister!=null) throw AssemblyError("can't use register to loop over words") diff --git a/docs/source/todo.rst b/docs/source/todo.rst index 8b3b8f1f0..75184fbc5 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -48,6 +48,9 @@ without having to to index into the stack? Misc ^^^^ +Add sort() function that can sort an array (ascending and descending) + + Several ideas were discussed on my reddit post https://www.reddit.com/r/programming/comments/alhj59/creating_a_programming_language_and_cross/ diff --git a/examples/arithmetic/bitshift.p8 b/examples/arithmetic/bitshift.p8 index a505547ba..effefe995 100644 --- a/examples/arithmetic/bitshift.p8 +++ b/examples/arithmetic/bitshift.p8 @@ -1,6 +1,8 @@ %import c64utils %zeropage basicsafe +; TODO implement asm generation for all operation in here + main { byte bb diff --git a/examples/bdmusic_irq.p8 b/examples/bdmusic_irq.p8 new file mode 100644 index 000000000..c21994f09 --- /dev/null +++ b/examples/bdmusic_irq.p8 @@ -0,0 +1,74 @@ +%zeropage basicsafe +%import c64lib + +main { + + sub start() { + c64scr.print("playing the music from boulderdash,\nmade in 1984 by peter liepa.\n\n") + c64utils.set_rasterirq(60) ; enable raster irq + } +} + +irq { + const ubyte waveform = %0001 ; triangle + ubyte note_index = 0 + ubyte delay = 0 + + sub irq() { + c64.EXTCOL++ + delay++ + if delay >= 8 { + delay = 0 + c64.AD1 = %00011010 + c64.SR1 = %00000000 + c64.AD2 = %00011010 + c64.SR2 = %00000000 + c64.MVOL = 15 + + uword note = notes[note_index] + note_index++ + ubyte note1 = lsb(note) + ubyte note2 = msb(note) + c64.FREQ1 = music_freq_table[note1] ; set lo+hi freq of voice 1 + c64.FREQ2 = music_freq_table[note2] ; set lo+hi freq of voice 2 + + ; retrigger voice 1 and 2 ADSR + c64.CR1 = waveform <<4 | 0 + c64.CR2 = waveform <<4 | 0 + c64.CR1 = waveform <<4 | 1 + c64.CR2 = waveform <<4 | 1 + } + + c64.EXTCOL-- + } + + ; details about the boulderdash music can be found here: + ; https://www.elmerproductions.com/sp/peterb/sounds.html#Theme%20tune + + uword[] notes = [ + $1622, $1d26, $2229, $252e, $1424, $1f27, $2029, $2730, + $122a, $122c, $1e2e, $1231, $202c, $3337, $212d, $3135, + $1622, $162e, $161d, $1624, $1420, $1430, $1424, $1420, + $1622, $162e, $161d, $1624, $1e2a, $1e3a, $1e2e, $1e2a, + $142c, $142c, $141b, $1422, $1c28, $1c38, $1c2c, $1c28, + $111d, $292d, $111f, $292e, $0f27, $0f27, $1633, $1627, + $162e, $162e, $162e, $162e, $222e, $222e, $162e, $162e, + $142e, $142e, $142e, $142e, $202e, $202e, $142e, $142e, + $162e, $322e, $162e, $332e, $222e, $322e, $162e, $332e, + $142e, $322e, $142e, $332e, $202c, $302c, $142c, $312c, + $162e, $163a, $162e, $3538, $222e, $2237, $162e, $3135, + $142c, $1438, $142c, $1438, $202c, $2033, $142c, $1438, + $162e, $322e, $162e, $332e, $222e, $322e, $162e, $332e, + $142e, $322e, $142e, $332e, $202c, $302c, $142c, $312c, + $2e32, $292e, $2629, $2226, $2c30, $272c, $2427, $1420, + $3532, $322e, $2e29, $2926, $2730, $242c, $2027, $1420 + ] + + uword[] music_freq_table = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 732, 778, 826, 876, 928, 978, 1042, 1100, 1170, 1238, 1312, 1390, 1464, 1556, + 1652, 1752, 1856, 1956, 2084, 2200, 2340, 2476, 2624, 2780, 2928, 3112, 3304, + 3504, 3712, 3912, 4168, 4400, 4680, 4952, 5248, 5560, 5856, 6224, 6608, 7008, + 7424, 7824, 8336, 8800, 9360, 9904, 10496, 11120, 11712 + ] +} diff --git a/examples/cube3d-sprites.p8 b/examples/cube3d-sprites.p8 index 9fe132179..ed2840c0a 100644 --- a/examples/cube3d-sprites.p8 +++ b/examples/cube3d-sprites.p8 @@ -1,7 +1,7 @@ %import c64lib %import c64utils -; TODO: some optimizer breaks this.. the 3d sorting seems broken? or maybe more? runs fine without optimization +; TODO: some optimizer breaks this.. runs fine without optimization spritedata $2000 { ; this memory block contains the sprite data @@ -102,12 +102,12 @@ main { ; rotate around origin (0,0,0) ; set up the 3d rotation matrix values - word wcosa = cos8(ax) as word - word wsina = sin8(ax) as word - word wcosb = cos8(ay) as word - word wsinb = sin8(ay) as word - word wcosc = cos8(az) as word - word wsinc = sin8(az) as word + word wcosa = cos8(ax) + word wsina = sin8(ax) + word wcosb = cos8(ay) + word wsinb = sin8(ay) + word wcosc = cos8(az) + word wsinc = sin8(az) word wcosa_sinb = wcosa*wsinb / 128 word wsina_sinb = wsina*wsinb / 128 @@ -136,7 +136,8 @@ main { ; set each of the 8 sprites to the correct vertex of the cube ; first sort vertices to sprite order so the back/front order is correct as well - ; (chose to do a simple bubble sort it's only 8 items to sort) + ; (simple bubble sort as it's only 8 items to sort) + ; TODO make a builtin function sort() for ubyte sorti in 6 to 0 step -1 { for ubyte i1 in 0 to sorti { ubyte i2 = i1+1 @@ -163,7 +164,7 @@ main { else c64.SPRPTR[i] = $2000/64 ; small ball - c64.SPCOL[i] = spritecolors[zc>>13 as byte + 4] ; further away=darker color + c64.SPCOL[i] = spritecolors[(zc>>13) as byte + 4] ; further away=darker color } } } diff --git a/examples/cube3d.p8 b/examples/cube3d.p8 index 56263a290..8248e4f17 100644 --- a/examples/cube3d.p8 +++ b/examples/cube3d.p8 @@ -41,12 +41,12 @@ main { ; rotate around origin (0,0,0) ; set up the 3d rotation matrix values - word wcosa = cos8(ax) as word - word wsina = sin8(ax) as word - word wcosb = cos8(ay) as word - word wsinb = sin8(ay) as word - word wcosc = cos8(az) as word - word wsinc = sin8(az) as word + word wcosa = cos8(ax) + word wsina = sin8(ax) + word wcosb = cos8(ay) + word wsinb = sin8(ay) + word wcosc = cos8(az) + word wsinc = sin8(az) word wcosa_sinb = wcosa*wsinb / 128 word wsina_sinb = wsina*wsinb / 128 @@ -62,14 +62,13 @@ main { word Azz = wcosb*wcosc / 128 for ubyte i in 0 to len(xcoor)-1 { - rotatedx[i] = (Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]) / 128 - rotatedy[i] = (Ayx*xcoor[i] + Ayy*ycoor[i] + Ayz*zcoor[i]) / 128 - rotatedz[i] = (Azx*xcoor[i] + Azy*ycoor[i] + Azz*zcoor[i]) / 128 + ; don't normalize by dividing by 128, instead keep some precision for perspective calc later + rotatedx[i] = (Axx*xcoor[i] + Axy*ycoor[i] + Axz*zcoor[i]) + rotatedy[i] = (Ayx*xcoor[i] + Ayy*ycoor[i] + Ayz*zcoor[i]) + rotatedz[i] = (Azx*xcoor[i] + Azy*ycoor[i] + Azz*zcoor[i]) } } - ubyte[] vertexcolors = [1,7,7,12,11,6] - sub draw_edges() { ; plot the points of the 3d cube @@ -80,24 +79,25 @@ main { word persp byte sx byte sy + ubyte color for i in 0 to len(xcoor)-1 { rz = rotatedz[i] if rz >= 10 { - persp = (rz+200) / height + persp = 900 + rz/32 sx = rotatedx[i] / persp as byte + width/2 sy = rotatedy[i] / persp as byte + height/2 - c64scr.setcc(sx as ubyte, sy as ubyte, 46, vertexcolors[(rz as byte >>5) + 3]) + c64scr.setcc(sx as ubyte, sy as ubyte, 46, 7) } } for i in 0 to len(xcoor)-1 { rz = rotatedz[i] if rz < 10 { - persp = (rz+200) / height + persp = 900 + rz/32 sx = rotatedx[i] / persp as byte + width/2 sy = rotatedy[i] / persp as byte + height/2 - c64scr.setcc(sx as ubyte, sy as ubyte, 81, vertexcolors[(rz as byte >>5) + 3]) + c64scr.setcc(sx as ubyte, sy as ubyte, 81, 7) } } } diff --git a/examples/testforloops.p8 b/examples/testforloops.p8 index 286aa29c6..f0f5155f2 100644 --- a/examples/testforloops.p8 +++ b/examples/testforloops.p8 @@ -1,5 +1,7 @@ %zeropage basicsafe +; TODO implement asm generation for all loops here + main { sub start() {