|
Ugh... the painful linear counter...
I followed the doc to the letter and it still didn't work completely. After checking other nsf players I found 3 things that needed to be changed:
- When a write to $400B takes place... the counter goes into load mode (and anything in the load register gets loaded into the counter). If $4008.7 was 0, it signals the counter to enter count mode on the next linear counter clock. This is what the NESSOUND doc specifies... however... in that next linear clock, you only go to count mode if $4008.7 is still 0.
- Changing the mode upon writes to $4008 like the doc specifies seems to cause more problems than it solves. When a write to $4008 takes place, don't touch the mode of the linear counter.
- if the channel is disabled via $4015, the linear counter shouldn't be loaded with the load value even if in load mode. This doesn't seem right, but it seems to work o_O
I don't know if those problems are related... but I've had to do them to get the triangle channel working correctly.
For the details on how my counter works... here's snippits from my source:
// --- variables used ---
BYTE nLinearTimer; //'Load' would be a more accurate name. This is the load register BYTE nLinearCount; //the counter BYTE bLinearMode; //the current mode (0 = load, 1 = count) BYTE bLinearStart; //$4008.7 bit BYTE bLinearSignalCount; //signal to enter count on next linear clock
// --- linear clock ---
if( bLinearSignalCount && !bLinearStart ) { bLinearSignalCount = 0; bLinearMode = 1; //enter count mode }
if(bLinearMode && nLinearCount) nLinearCount--;
// --- writes to 4008 --- (val is the written value)
bLengthDisable = bLinearStart = val & 0x80; nLinearTimer = val & 0x7F; if(bChannelEnabled && !bLinearMode) nLinearCount = nLinearTimer;
// --- writes to 400B ---
bLinearMode = 0; if(!bLinearStart) bLinearSignalCount = 1; if(bChannelEnabled) { // [load the length counter here] nLinearCount = nLinearTimer; } // [load MSB of wavelength here]
|