Why did Castlevania 3 do this? (Triangle timing)

Discuss NSF files, FamiTracker, MML tools, or anything else related to NES music.

Moderator: Moderators

Post Reply
TheouAegis
Posts: 4
Joined: Tue May 17, 2022 1:54 pm

Why did Castlevania 3 do this? (Triangle timing)

Post by TheouAegis »

This question is to help me understand CV3's programming, but also to help me understand how the linear counter works in the Triangle channel. Sorry, I'm one of those people that still doesn't understand it.

I was mapping out RAM use in Castlevania games (just as a very boring hobby of mine) and decided to tackle Castlevania 3's audio variables. I noticed 2 variables related to the Triangle channel in CV3 that had no correlation to anything in AkuDen that I could tell (which doesn't use the Triangle channel).
  • Byte $194 holds a copy of the linear counter. It's very rarely read from, but always written to.
  • Byte $193 is set to 1 whenever a new note plays and increments every frame. After 15 frames (i.e., when $193 equals #10), if the control value ($15D) is set, the program will take the linear counter in $194, subtract #40 from it, and make that the new linear counter value.
So I have two questions:

1) Why do the programmers do this? In the "Clockwork" track for example, this code toggles the linear counter from #50 to #10. This equates to a series of quarter notes in the track. If I freeze $193 in order to prevent the #10 write, I personally cannot hear the difference. What's the difference between #50 for 15 frames then #10 for 16 frames, as opposed to #60 for 31 frames?

2) If the control value is set, the linear counter is set to ($15D+1)*N, where N is some multiplier specified in the track's data. However, if the control value is not set, the default value of #90 is used for the linear counter. My question is thus: WHY? Why #90? Why not #81 or #FF? Is there even any difference between them? For that matter, what's the difference between #80 and #00?
Drag
Posts: 1615
Joined: Mon Sep 27, 2004 2:57 pm
Contact:

Re: Why did Castlevania 3 do this? (Triangle timing)

Post by Drag »

I suspect the music engine might be using the same code it uses for driving registers 4000 and 4004 in order to also drive register 4008, even though it doesn't quite make sense. For the square channels, you can create a duty cycle and volume envelope by writing a list of values to 4000 or 4004 on each frame (sounds a lot like how $193 and $194 are behaving).

Take a look at which values you're seeing written to 4008, and try thinking about what those values would do if you wrote them to 4000 or 4004 instead, and you'll see why I'm suspecting this. :P A big clue for me is, bit 4 (#$10) is how you enable the volume control on the square channels (versus the hardware envelope), that lines up with how many of the values you're seeing seem to have that bit set.

If my guess is correct, then the music engine isn't doing this for any important reason, just that it's convenient to reuse code and it just coincidentally happens to work on the triangle channel to unmute it so they went with it, even though it ends up looking like they're writing a lot of redundant and/or confusing values to the register. :P
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: Why did Castlevania 3 do this? (Triangle timing)

Post by Pokun »

The wiki might still be a bit confusing regarding the APU.
This is how $4008 works:

Code: Select all

$4008 (W)
Triangle Channel Linear Counter.
  CRRR RRRR
  |+++-++++- Counter Reload Value ($00~$7F)
  +--------- Control Flag and Length Counter Halt Flag
Whenever the Length Counter Halt Flag is set, the hardware length counter (high 5 bits of $400B) is unused and the 7-bit Counter Reload Value is what controls if the triangle is muted or not. A 0 here mutes it and any non-zero value unmutes it, making it play whatever note is in $400A and low 3 bits of $400B until you manually mute it by writing $80 to $4008. So the difference between $80 and $90 is that former mutes the channel and the latter does not. There is no difference between $90, $91, $81 or $FF since they all use a non-zero Counter Reload Value, unmuting the triangle.

The difference between $80 and $00 is that in the latter case, Length Counter Halt Flag is clear and thus the hardware length counter is used to control note length.
Post Reply