mirror of
https://github.com/irmen/prog8.git
synced 2026-04-21 02:16:41 +00:00
psg module: the envelope handler no longer writes to vera PSG voices that haven't been enabled
This commit is contained in:
@@ -15,14 +15,22 @@ psg {
|
||||
const ubyte NOISE = %11000000
|
||||
const ubyte LEFT = %01000000
|
||||
const ubyte RIGHT = %10000000
|
||||
const ubyte DISABLED = %11111111
|
||||
|
||||
sub init() {
|
||||
; -- initializes the psg module (all 16 voices set to disabled)
|
||||
for cx16.r1L in 0 to 15
|
||||
voice_enabled[cx16.r1L] = false
|
||||
}
|
||||
|
||||
sub voice(ubyte voice_num, ubyte channel, ubyte vol, ubyte waveform, ubyte pulsewidth) {
|
||||
; -- Enables a 'voice' on the PSG.
|
||||
; voice_num = 0-15, the voice number.
|
||||
; channel = either LEFT or RIGHT or (LEFT|RIGHT). Specifies the stereo channel(s) to use.
|
||||
; channel = either LEFT or RIGHT or (LEFT|RIGHT). Specifies the stereo channel(s) to use. DISABLED=disable the voice.
|
||||
; vol = 0-63, the starting volume for the voice
|
||||
; waveform = one of PULSE,SAWTOOTH,TRIANGLE,NOISE.
|
||||
; pulsewidth = 0-63. Specifies the pulse width for waveform=PULSE.
|
||||
voice_enabled[voice_num] = false
|
||||
envelope_states[voice_num] = 255
|
||||
sys.irqsafe_set_irqd()
|
||||
cx16.r0 = $f9c2 + voice_num * 4
|
||||
@@ -30,11 +38,19 @@ psg {
|
||||
cx16.VERA_ADDR_L = lsb(cx16.r0)
|
||||
cx16.VERA_ADDR_M = msb(cx16.r0)
|
||||
cx16.VERA_ADDR_H = 1
|
||||
cx16.VERA_DATA0 = channel | vol
|
||||
cx16.VERA_ADDR_L++
|
||||
cx16.VERA_DATA0 = waveform | pulsewidth
|
||||
envelope_volumes[voice_num] = mkword(vol, 0)
|
||||
envelope_maxvolumes[voice_num] = vol
|
||||
if channel!=DISABLED {
|
||||
cx16.VERA_DATA0 = channel | vol
|
||||
cx16.VERA_ADDR_L++
|
||||
cx16.VERA_DATA0 = waveform | pulsewidth
|
||||
envelope_volumes[voice_num] = mkword(vol, 0)
|
||||
envelope_maxvolumes[voice_num] = vol
|
||||
voice_enabled[voice_num] = true
|
||||
} else {
|
||||
cx16.VERA_DATA0 = 0
|
||||
envelope_volumes[voice_num] = 0
|
||||
envelope_maxvolumes[voice_num] = 0
|
||||
voice_enabled[voice_num] = false
|
||||
}
|
||||
sys.irqsafe_clear_irqd()
|
||||
}
|
||||
|
||||
@@ -99,10 +115,12 @@ psg {
|
||||
}
|
||||
|
||||
sub silent() {
|
||||
; -- Shut down all PSG voices.
|
||||
; -- Silence all active PSG voices.
|
||||
for cx16.r1L in 0 to 15 {
|
||||
envelope_states[cx16.r1L] = 255
|
||||
volume(cx16.r1L, 0)
|
||||
if voice_enabled[cx16.r1L] {
|
||||
envelope_states[cx16.r1L] = 255
|
||||
volume(cx16.r1L, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,6 +140,8 @@ psg {
|
||||
sys.pushw(cx16.r9)
|
||||
; calculate new volumes
|
||||
for cx16.r1L in 0 to 15 {
|
||||
if not voice_enabled[cx16.r1L]
|
||||
continue
|
||||
when envelope_states[cx16.r1L] {
|
||||
0 -> {
|
||||
; attack
|
||||
@@ -165,7 +185,10 @@ psg {
|
||||
cx16.VERA_ADDR_M = $f9
|
||||
cx16.VERA_ADDR_H = 1 | %00110000
|
||||
for cx16.r1L in 0 to 15 {
|
||||
cx16.VERA_DATA0 = cx16.VERA_DATA1 & %11000000 | msb(envelope_volumes[cx16.r1L])
|
||||
if voice_enabled[cx16.r1L]
|
||||
cx16.VERA_DATA0 = cx16.VERA_DATA1 & %11000000 | msb(envelope_volumes[cx16.r1L])
|
||||
else
|
||||
cx16.VERA_DATA0 = cx16.VERA_DATA1
|
||||
}
|
||||
cx16.restore_vera_context()
|
||||
cx16.r9 = sys.popw()
|
||||
@@ -175,6 +198,7 @@ psg {
|
||||
return true ; run the system IRQ handler afterwards
|
||||
}
|
||||
|
||||
bool[16] voice_enabled
|
||||
ubyte[16] envelope_states
|
||||
uword[16] envelope_volumes ; scaled by 256
|
||||
ubyte[16] envelope_attacks
|
||||
|
||||
@@ -89,7 +89,9 @@ main {
|
||||
}
|
||||
}
|
||||
"""
|
||||
@Suppress("DEPRECATION") // Thread.currentThread().id
|
||||
val filenameBase = "on_the_fly_test_" + Thread.currentThread().id.toString() + "_" + sourceText.hashCode().toUInt().toString(16)
|
||||
|
||||
val filepath = outputDir.resolve("$filenameBase.p8")
|
||||
filepath.toFile().writeText(sourceText)
|
||||
val (program, options, importedfiles) = parseMainModule(filepath, errors, C64Target(), emptyList(), emptyList())
|
||||
|
||||
@@ -60,6 +60,7 @@ internal fun compileText(
|
||||
errors: IErrorReporter? = null,
|
||||
writeAssembly: Boolean = true,
|
||||
) : CompilationResult? {
|
||||
@Suppress("DEPRECATION") // Thread.currentThread().id
|
||||
val filePath = outputDir.resolve("on_the_fly_test_" + Thread.currentThread().id.toString() + "_" + sourceText.hashCode().toUInt().toString(16) + ".p8")
|
||||
// we don't assumeNotExists(filePath) - should be ok to just overwrite it
|
||||
filePath.toFile().writeText(sourceText)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
Prog8 compiler v11.2 by Irmen de Jong (irmen@razorvine.net)
|
||||
Prog8 compiler v11.3-SNAPSHOT by Irmen de Jong (irmen@razorvine.net)
|
||||
Prerelease version from git commit 8e31b622 in branch master
|
||||
This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html
|
||||
|
||||
Compiling program import-all-c128.p8
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
Prog8 compiler v11.2 by Irmen de Jong (irmen@razorvine.net)
|
||||
Prog8 compiler v11.3-SNAPSHOT by Irmen de Jong (irmen@razorvine.net)
|
||||
Prerelease version from git commit 8e31b622 in branch master
|
||||
This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html
|
||||
|
||||
Compiling program import-all-c64.p8
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
Prog8 compiler v11.2 by Irmen de Jong (irmen@razorvine.net)
|
||||
Prog8 compiler v11.3-SNAPSHOT by Irmen de Jong (irmen@razorvine.net)
|
||||
Prerelease version from git commit 8e31b622 in branch master
|
||||
This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html
|
||||
|
||||
Compiling program import-all-cx16.p8
|
||||
@@ -586,6 +587,7 @@ LIBRARY MODULE NAME: psg
|
||||
------------------------
|
||||
|
||||
psg {
|
||||
const ubyte DISABLED
|
||||
const ubyte LEFT
|
||||
const ubyte NOISE
|
||||
const ubyte PULSE
|
||||
@@ -598,9 +600,11 @@ psg {
|
||||
ubyte[] envelope_states
|
||||
ubyte[] envelope_sustains
|
||||
uword[] envelope_volumes
|
||||
bool[] voice_enabled
|
||||
envelope (ubyte voice_num, ubyte maxvolume, ubyte attack, ubyte sustain, ubyte release)
|
||||
envelopes_irq () -> bool
|
||||
freq (ubyte voice_num, uword vera_freq)
|
||||
init ()
|
||||
pulse_width (ubyte voice_num, ubyte pw)
|
||||
silent ()
|
||||
voice (ubyte voice_num, ubyte channel, ubyte vol, ubyte waveform, ubyte pulsewidth)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
Prog8 compiler v11.2 by Irmen de Jong (irmen@razorvine.net)
|
||||
Prog8 compiler v11.3-SNAPSHOT by Irmen de Jong (irmen@razorvine.net)
|
||||
Prerelease version from git commit 8e31b622 in branch master
|
||||
This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html
|
||||
|
||||
Compiling program import-all-pet32.p8
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
Prog8 compiler v11.2 by Irmen de Jong (irmen@razorvine.net)
|
||||
Prog8 compiler v11.3-SNAPSHOT by Irmen de Jong (irmen@razorvine.net)
|
||||
Prerelease version from git commit 8e31b622 in branch master
|
||||
This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html
|
||||
|
||||
Compiling program import-all-virtual.p8
|
||||
@@ -293,6 +294,7 @@ strings {
|
||||
lstripped (str s) -> str
|
||||
ltrim (str s)
|
||||
ltrimmed (str s) -> str
|
||||
ncompare (str st1, str st2, ubyte length) -> byte
|
||||
rfind (uword stringptr, ubyte character) -> ubyte
|
||||
right (str source, ubyte slen, str target)
|
||||
rstrip (str s)
|
||||
|
||||
@@ -9,6 +9,7 @@ TODO
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
- in unit test helpers: replace own temp file name creation by kotest tempfile()/tempdir() , instead of using Thread.currentThread().id, which is deprecated in newer Java versions
|
||||
- allow integer range as when choice? because 1,2,3,4,5 is already allowed, so perhaps 1 to 5 should be allowed too? However, [1,2,3,4,5] usually is the desugared equivalent of 1 to 5 and choice values can't be arrays.
|
||||
- const values should always either be of type long or float, this is how they were usually treated in const expression evaluation already anyway
|
||||
- Kotlin: can we use inline value classes in certain spots?
|
||||
|
||||
+20
-21
@@ -1,32 +1,31 @@
|
||||
%import textio
|
||||
%import strings
|
||||
%import psg
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
main {
|
||||
|
||||
str name1 = "irmen"
|
||||
str name2 = "irmen de jong"
|
||||
|
||||
sub start() {
|
||||
psg.init()
|
||||
|
||||
txt.print_b(strings.compare(name1, name2))
|
||||
txt.spc()
|
||||
txt.print_b(strings.compare(name2, name1))
|
||||
txt.nl()
|
||||
psg.voice(5, psg.LEFT, 0, psg.TRIANGLE, 0)
|
||||
psg.freq(5, 1600)
|
||||
psg.envelope(5, 63, 10, 50, 2)
|
||||
|
||||
txt.print_b(strings.ncompare(name1, name2, 6))
|
||||
txt.spc()
|
||||
txt.print_b(strings.ncompare(name2, name1, 6))
|
||||
txt.nl()
|
||||
psg.voice(6, psg.RIGHT, 0, psg.SAWTOOTH, 0)
|
||||
psg.freq(6, 1200)
|
||||
psg.envelope(6, 63, 2, 50, 10)
|
||||
|
||||
txt.print_b(strings.ncompare(name1, name2, 5))
|
||||
txt.spc()
|
||||
txt.print_b(strings.ncompare(name2, name1, 5))
|
||||
txt.nl()
|
||||
repeat 140 {
|
||||
sys.waitvsync()
|
||||
psg.envelopes_irq()
|
||||
}
|
||||
|
||||
txt.print_b(strings.ncompare(name1, name2, 4))
|
||||
txt.spc()
|
||||
txt.print_b(strings.ncompare(name2, name1, 4))
|
||||
txt.nl()
|
||||
psg.voice(5, psg.DISABLED, 0, 0, 0)
|
||||
psg.voice(6, psg.DISABLED, 0, 0, 0)
|
||||
psg.silent()
|
||||
repeat {
|
||||
sys.waitvsync()
|
||||
psg.envelopes_irq()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -3,4 +3,4 @@ org.gradle.console=rich
|
||||
org.gradle.parallel=true
|
||||
org.gradle.daemon=true
|
||||
kotlin.code.style=official
|
||||
version=11.2
|
||||
version=11.3-SNAPSHOT
|
||||
|
||||
Reference in New Issue
Block a user