|
I first got the idea from Brad's doc:
________________________________________ $4008(tri) bits --------------- 0-6 linear counter load register 7 length counter clock disable / linear counter start ________________________________________
$4007.7 = "Length counter clock disable". You had the 'bLengthDisable' identifier in your own code snippet. If I just make the condition (Length || Linear), the channel never goes silent. This may be due to some other bug where I ought to set LengthCounter = 0, but it seems right to me. And most of all, it works. I haven't checked out Mega Man yet, I just responded immediatly to this post.
For what it's worth, I'm posting a part of my source. It's written with the _excellent_ assembler SpAsm. I know that people generally aren't very fond of assembly, but its ease of use and clarity is perfect for almost every software project. Personally I used C++ for one or two years before I came across SpAsm, which revolutionized my programming. Anyway, here's my triangle code:
; Regs Write4008: ; 0 - 6: Linear counter, 7: Linear counter start mov B$Triangle@Reg0 al
; Linear counter mode? and B$Triangle@Reg0 al ifNotFlag B$Triangle@Reg0 080, mov B$Triangle@LinearCounterMode LCM_COUNT
; Load linear counter latch clearFlag al 080 mov B$Triangle@LinearCounterLatch al if D$Triangle@LinearCounterMode = LCM_LOAD, mov B$Triangle@LinearCounter al
; Enabled? call TriangleEnabled ret
Write4009: ret Write400A: ; 0 - 7: Low bits of frequency
; Update frequency mov B$Triangle@TimerLatch al call TriangleUpdateTimer
; Enabled? call TriangleEnabled ret
Write400B: ; 0 - 2: High bits of frequency, 3 - 7: length counter
; Update length counter mov edx eax shr dl 3 | and eax 01F mov dl B$edx+LengthCounterTable mov B$Triangle@LengthCounter dl
; Update frequency and al 7 mov B$Triangle@TimerLatch+1 al call TriangleUpdateTimer
; Update linear counter mov D$Triangle@LinearCounterMode LCM_LOAD copy D$Triangle@LinearCounterLatch D$Triangle@LinearCounter test D$Triangle@Reg0 080 | setz B$Triangle@ChangeMode
; Enabled? call TriangleEnabled ret ____________________________________________________________________________________________ [LCM_LOAD 0 LCM_COUNT 1] ; Counters TriangleClockLinearCounter: ; Mode = count longIf D$Triangle@LinearCounterMode = LCM_COUNT if D$Triangle@LinearCounter = 0, ret dec D$Triangle@LinearCounter jz TriangleEnabled ret endif
; Mode = load copy D$Triangle@LinearCounterLatch D$Triangle@LinearCounter
; Change mode if D$Triangle@ChangeMode = &FALSE, ret mov D$Triangle@ChangeMode &FALSE mov D$Triangle@LinearCounterMode LCM_COUNT ret
TriangleClockLengthCounter: ; Active? if D$Triangle@LengthCounter = 0, ret if D$Triangle@Silenced = &TRUE, ret
; Count down dec D$Triangle@LengthCounter jz TriangleEnabled ret
TriangleEnabled: mov eax 0 or eax D$Triangle@LinearCounter ifFlag B$Triangle@Reg0 080, or eax D$Triangle@LengthCounter if D$Triangle@Silenced = &TRUE, mov eax 0 ; Silenced through $4015
test eax eax | setnz B$Triangle@Enabled ret
|