APU behavior (Eliminator Boat Duel)

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
APU behavior (Eliminator Boat Duel)
by on (#231684)
Hi nesdev.

"Eliminator Boat Duel (USA).nes" must have buzz sound on power-on, you can hear it on some emulators
(nintendulator, nestopia, fceux, rocknes for example)
I remember it was present on real hardware but need to re-test it again on famicom some day.

Strange, but most of top-accurate NES emulators (mesen, punes, bizhawk) play silence at startup.
Is it bug?
Re: APU behavior (Eliminator Boat Duel)
by on (#231695)
I think I've figured this one out. The game enables the DMC channel without ever writing to $4012/$4013 to initialize those registers. Then it keeps writing to $4015 (once per frame) with the DMC enabled flag set. According to the Wiki, this restarts the DMC sample if it has stopped playing ("If the DMC bit is set, the DMC sample will be restarted only if its bytes remaining is 0."), which essentially means the game ends up reading random data between $C000-$FFFF and playing it as a DMC sample.

Mesen initializes the sample address and length with a 0 (which is probably impossible, hardware-wise), which means nothing gets played at all, even though $4015 is written to with the DMC flag enabled. If I initialize those values with $C000 and 1 (which are their minimum respective values normally), a buzzing sound can be heard and never stops throughout the game, because the game keeps writing to the $4015 register with the DMC enabled flag set.

I suppose the power on values could potentially be anything (or even random), though given that the CPU powers on with specific values for registers and the like, it's likely that there is a specific value for these. Would be interesting to see if the register values are affected by a reset, too.
Re: APU behavior (Eliminator Boat Duel)
by on (#231696)
Quote:
The game enables the DMC channel without ever writing to $4012/$4013 to initialize those registers. Then it keeps writing to $4015 (once per frame) with the DMC enabled flag set.
If I initialize those values with $C000 and 1 (which are their minimum respective values normally), a buzzing sound can be heard and never stops throughout the game, because the game keeps writing to the $4015 register with the DMC enabled flag set.

It's game abnormal behavior, yes. Anyway i will test it on real hardware.
Re: APU behavior (Eliminator Boat Duel)
by on (#231697)
Looking in Visual2A03...

/RESET clears the DPCM pointer "pcm_a0" through "pcm_a14" ... but...
Restarting DPCM by writing to $4015 with the bit DPCM bit set (i.e. node 11092) reloads pcm_a6 through pcm_a13 from pcm_sa0 through pcm_sa7 (and clears pcm_a0 through pcm_a5 and sets pcm_a14)

The value in pcm_saX is neither set nor cleared on /RESET, and the storage device - two inverters and a transmission gate - looks like it should come out of cold boot usually low.
(Specifically: both pcm_sa0 and pcm_/sa0 have the same geometry of pullup, but pcm_sa0 is larger and so its charge time should be slower, so pcm_/sa0 should reach logic high earlier).

edit: similarly, /RESET also clears the DPCM "bytes remaining" "pcm_lc0" through "pcm_lc11", but it also is reloaded from pcm_l7 through pcm_l0, which is also not explicitly set during reset, and also should tend towards 0 on cold boot

So if I'm reading this correctly:
DPCM halted and address set to $8000 on all resets, but this address can't actually matter
DPCM start address not initialized in hardware, but probably $8000 on cold boot, and definitely unchanged on warm boot.
edit: DPCM length also not initialized in hardware, and probably 0 (meaning "1 byte") on cold boot, and unchanged on warm boot
Re: APU behavior (Eliminator Boat Duel)
by on (#231698)
Running the game on my PowerPak / NES I hear the buzz constantly, at the title screen and during most of the game (except when paused).

Though because it's 60Hz, I probably would have assumed it was just crosstalk from the video signal if playing on hardware... but obviously that doesn't happen in an emulator.

Reminded slightly of the codemasters buzz.
Re: APU behavior (Eliminator Boat Duel)
by on (#231705)
lidnariq wrote:
DPCM start address not initialized in hardware, but probably $8000 on cold boot, and definitely unchanged on warm boot.
edit: DPCM length also not initialized in hardware, and probably 0 (meaning "1 byte") on cold boot, and unchanged on warm boot
I'm assuming you meant $C000 rather than $8000? (Since the DMC can only load from $C000-$FFFF?)

I've attached a very basic test ROM that should buzz on power on (Disclaimer: I still suck at 6502 assembly)
On FCEUX/Nestopia/VirtuaNES it buzzes, on Mesen 0.9.7 and Bizhawk, it doesn't.

Only byte $C000 is set in memory (to a value that sounded relatively loud from my testing), everything else in the $C000-$FFFF range is $00 except the vector bytes. Assuming it buzzes on hardware, it should confirm the power on state to be $C000.

Edit: Also, this may not work properly on a powerpak/etc since they may initialize the registers to something else?
Re: APU behavior (Eliminator Boat Duel)
by on (#231706)
Sour wrote:
I'm assuming you meant $C000 rather than $8000? (Since the DMC can only load from $C000-$FFFF?)
Nope! I definitely do mean $8000.

You may recall that DPCM that starts at $FFC0 and extends past $FFFF will overflow to $8000...

For whatever reason, it's a 15-bit counter – compare Visual2A03 transistor "t16851", which connects "pcm_+a14" to the address bus multiplexer, vs transistor "t16954" which instead just pulls a15 high.

The thing that initialized pcm_a14 is transistor "t16835" which always pulls the signal high.
Re: APU behavior (Eliminator Boat Duel)
by on (#231707)
lidnariq wrote:
Nope! I definitely do mean $8000.

You may recall that DPCM that starts at $FFC0 and extends past $FFFF will overflow to $8000...
I don't think I've ever been aware of this. And actually Mesen's code currently wraps to $0000 after $FFFF, as far as I can tell, whoops.
Re: APU behavior (Eliminator Boat Duel)
by on (#231710)
Alright, with that in mind, let's try this again!

Here are 2 tests, both of them have all their code/data in the $F000-FFFF range.

The $8000 version sets $8000 to $87, and everything else is $00.
The $C000 version sets $C000 to $87, and everything else is $00.

I'd expect the $8000 version to buzz, while the $C000 version should be silent. None of the emulators I tested buzz on the $8000 version at the moment.

Eliminator Boat Duel seems to have the value $4C at both $8000 and $C000, so it would sound the exact same in both scenarios (which means emulators that currently emulate the buzz properly might only be getting it right by luck)
Re: APU behavior (Eliminator Boat Duel)
by on (#231729)
FCAV test record is here

Eliminator Boat Duel is buzzing
$C000 is buzzing
$8000 is silent (sometimes after restart it have graphical garbage)

Nintendulator, nestopia, fceux, and even old nnnesterj and virtuanes
pass this test same way as hardware,
but rocknes have silence on both (but buzzing on boat duel)

Mesen, puNES, BizHawk(NESHawk) and MyNES have silence on tests and on Boat Duel too.
Re: APU behavior (Eliminator Boat Duel)
by on (#231730)
... <facepalm> Right, made a mistake. I even explained why but didn't finish thinking it through ... it's specifically the pcm_sa0 through pcm_sa7 latches that're uninitialized, and when DPCM is restarted by writing to $4015, pcm_a14 is initialized high there.
Re: APU behavior (Eliminator Boat Duel)
by on (#231731)
So, i guess this title will confusing other emu developers
Re: APU behavior (Eliminator Boat Duel)
by on (#231732)
I did some testing with my own test ROMs on Everdrive and suspect that its firmware writes to these registers (unless I was doing something wrong, setting the address in one ROM and switching to another did not seem to preserve it), so I can't say much about the power-on values, but it does appear that registers are indeed unchanged by reset. My tests modify the length because they play actual samples; sour's tests are probably more useful because they leave length alone, so I don't intend to post mine unless someone wants them.
Re: APU behavior (Eliminator Boat Duel)
by on (#231738)
So, what's the correct setting for DMC powerup/reset? Address is set to $8000... or would it be $C000?
In my emulator (current beta), I could "fix" the buzzing by doing the following:

1. There's a frequency table.
Code:
static const int freq_table[0x10] = {
  0x1AC, 0x17C, 0x154, 0x140, 0x11E, 0x0FE, 0x0E2, 0x0D6,
  0x0BE, 0x0A0, 0x08E, 0x080, 0x06A, 0x054, 0x048, 0x036
};

2. Once DMC frequency_counter expires, frequency_counter = freq_table[$4010 AND 15];

3. So... the buzzing sound is hearded if I do frequency_counter = freq_table[0] on reset/powerup, plus setting dmc_length = 1.

4. DMC address at $8000 on powerup/reset does NOT output the buzzing sound.
Re: APU behavior (Eliminator Boat Duel)
by on (#231739)
Eugene.S wrote:
So, i guess this title will confusing other emu developers
I'll post a final "v3" with updated text to say which test should be silent or playing a sound when I get a chance (e.g after work). Thanks for running the tests, by the way!
Zepper wrote:
So, what's the correct setting for DMC powerup/reset? Address is set to $8000... or would it be $C000?
Based on Eugene's results, the sample address should be initialized to $C000 and length to 1 byte, which should cause a buzzing on the C000 test.
Re: APU behavior (Eliminator Boat Duel)
by on (#231773)
Zepper wrote:
So, what's the correct setting for DMC powerup/reset?
The registers at $4010, $4012, and $4013 have the same geometry as the registers from $4000-$400F, so it appears that they should come out of cold boot holding 0.

The register at $4011 is a different shape, but previous evidence (krzysiobal's switchable 60Hz/50Hz famiclone) implies that it also comes out of cold boot holding 0.


On warm boot, $4010, $4012, $4013 are unchanged. The upper six bits of $4011 are cleared and the least significant bit is known to not be changed. (i.e. &= 1)
Re: APU behavior (Eliminator Boat Duel)
by on (#231776)
Sour wrote:
Based on Eugene's results, the sample address should be initialized to $C000 and length to 1 byte, which should cause a buzzing on the C000 test.

Since he tested on Everdrive, like me, I'm not sure we can trust those results. I'll do additional testing on this tonight. The test for this should be setting the register with one ROM, resetting to the menu while maintaining power, and testing the value with another ROM to see if it persists (though this isn't a perfect test because the Everdrive could modify registers on reset that aren't touched on power-on).

Unless PowerPak is any different, testing this properly may require a dev cart.
Re: APU behavior (Eliminator Boat Duel)
by on (#231778)
Ah, hadn't looked at the video so I had assumed it was tested on a regular cart.

Like you said, without a regular cart, there is no 100% safe way to test this - any write to $4012/4013 will make the test unreliable, and there is no way to know for sure that the PowerPak/Everdrive do not write to those registers. So the only thing that can be tested is reset behavior (which is arguably less important than the power on behavior)
Re: APU behavior (Eliminator Boat Duel)
by on (#231796)
Here's what should be a set of pretty thorough tests.

DmcPowerOnSilent sets virtually everything other than $C000 to $87 ($C000 is $00). If this test is silent on hardware, this should prove that the power on address & length are $C000 and $01 respectively.

DmcPowerOnBuzz keeps every byte at $00 (except the bare minimum for the code/data) and sets $C000 to $87. This should buzz on hardware at power on. Pressing a button should stop the sound (by setting the sample address to $FFC0). Pressing a button and then resetting should NOT cause a buzz (if the sample address is unchanged by a soft reset). Resetting without pressing a button should keep the buzz going.
Re: APU behavior (Eliminator Boat Duel)
by on (#231809)
Tried out your test on Everdrive. DmcPowerOnBuzz starts up with buzzing, pressing a button silences the buzzing, and it remains silent after a reset, so seems to confirm that address is preserved across resets.

I did further testing with my sample-based test and it plays the full sample normally after reset, so it appears length and flags/rate are also preserved. I've also verified that the Everdrive menu (at least through reset) modifies these registers, by first playing a sample in one ROM, resetting to the menu, and starting another ROM containing those same samples that just writes to $4015 without setting any DMC registers (the sample is not played).


@lidnariq: Maybe drifting off-topic a tiny bit, but I was looking at the wiki page on DMC and saw this note on writing to $4011: "If the timer is outputting a clock at the same time, the output level is occasionally not changed properly.[1]". The referenced post by rainwarrior notes the issue, but he isn't sure how this works just from testing. Is this something you can take a stab at from Visual2A03?
Re: APU behavior (Eliminator Boat Duel)
by on (#231833)
That's "just" a bus conflict.

The DPCM DACs have the exact same "basic cell" as I saw in the 2C02's up-counters for $2006 and $2003... only this has a little extra support circuitry to allow it count up or down.

If "pcm_doadjust" is true at the same time that "w4011" is true, even though _db1 through _db6 are larger and would usually win, there's nothing to stop pcm_doadjust from pulling the storage node down.

"w4011" is true during φ2 (actually φ2, not M2), but I'm having the worst time tracking down the exact timing of pcm_doadjust.
Re: APU behavior (Eliminator Boat Duel)
by on (#232801)
gauauu tested a CHR-RAM version of the tests I wrote on a GTROM board and confirmed that one test is silent, while the other behaves as expected (buzzing at power on, and if silenced before resetting, stays silent after resetting).

So, looks like the results match what we were expecting:
-The DMC DMA will read from $C000 after a power on, if not initialized
-The default sample length is 1
-Resetting does not alter the address
Re: APU behavior (Eliminator Boat Duel)
by on (#232837)
"Druid", an FDS game from Jaleco, suffers from the same problem on real hardware.