Question about coding for NES zapper

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Question about coding for NES zapper
by on (#63690)
Hello, everyone. This is kalzone, that complete noob from 2 years ago who was trying to mess with NES emulators without any idea what he was doing. Just want to thank everyone here that helped me with that, again, since I really didn't know what I was getting into.

That said, I've now had a year or two of x86 and MIPS assembly under my belt and I'm looking into starting with 6502 assembly for a project I had in mind. The problem is--I'm looking into using the NES zapper. I'm guessing this involves a pretty huge level of complexity, and I also imagine it'd be pretty hard to test in an emulator.

So, I guess my question is this: should I just go ahead and give up now, or is there a fair bit of documentation on coding for the zapper?

Also, what I need to do at least SOUNDS fairly basic...basically, just producing a sound depending on where the light gun hits. So I need code to map the zapper, code for the instruments, code to actually produce the pitches, and very basic white sprites on a black background just so there are white areas for the zapper to hit. Are there any roms floating around that already do something similar?

Thanks.
In Soviet Russia, roulette plays YOU
by on (#63691)
It won't work so well on a modern TV.

The Zapper and similar light guns have the photodiode connected to a 15.7 kHz resonator to detect whether light is actually coming from adjacent scanlines of a CRT's raster scan and not a light bulb. The trouble is that LCD TVs don't have that 15.7 kHz flicker. The only sort of Zapper game that works on an NES connected to a modern TV is one that uses the trigger ($4017.D4 active high) and not the photodiode ($4017.D3 active low). And I know of only one game that uses a firearm without aiming: Russian roulette. In fact, I made a Russian roulette game for NES today; I plan to have source and binary available tonight.

But if you can be certain that your players will be using a CRT SDTV, here's how to do it:

When the player pulls the trigger ($4017.D4 goes from 0 to 1)...
  1. Make the next frame's background color white (PPU $3F00 = $30) and arrange for a sprite 0 hit to happen at the top of the next frame.
  2. Wait for sprite 0 hit ($2002.D6 to become 0 then 1), then turn off rendering so that the background color fills the screen.
  3. Poll $4017 once every 113.667 cycles, waiting for bit 3 to go from 1 to 0. Record how many polls it took it took before the hit.
  4. Find all "candidates", or sprites within a couple scanlines of that hit line.
  5. Make the next frame's background color black and draw all candidates in white. See if a candidate was hit; $4017.D3 should go from 1 to 0 (and then back to 1 after a couple scanlines) sometime during the frame if so.
  6. If a candidate was hit, narrow down the candidates with a binary search.

How many targets do you plan to have on the screen at once?

by on (#63693)
Would it work on a plasma?

by on (#63694)
I'm not very familiar with how plasmas work. But plasmas upscale to 480p or 720p or 1080p, so even if they did scan the picture sequentially like a CRT, I don't think the screen would activate the 15.7 kHz resonator for the same reason that a VGA monitor doesn't.

by on (#63695)
Wow, quick and useful replies again...gotta love these forums. Shouldn't be surprised, coming from you, tepples--without you, I never would've made that emulator work.

Anyway, luckily, my target audience is me and I have old CRT's lying around. I just want to make my Zapper/NES into a musical instrument...and I absolutely do need the aiming part, as that will determine the pitch (and possibly the channel/instrument...I want both squares and the triangle available, but I don't need the noise channel).

OK, so, I guess I'm a bit of a noob regarding how the NES handles IO, but by the sound of things, IO is memory-mapped, and those memory locations are the ones to poll when the zapper is plugged in. Okay. This is beginning to sound easier than I was thinking it would be...in fact, I assume the A502 is going to be the source of bigger problems...

As far as targets, I was thinking of having maybe 3-4 octaves worth of notes, so either 36 or 48, and I was thinking that shooting away from the screen (not hitting any targets) would result in a change of instrument, or something. Is that a bit too high-resolution for the zapper?

by on (#63700)
Do note that while checking for a hit horizontally requires you to brighten a specific area and darken the rest, obtaining the vertical position is much simpler as long as you're pointing at a non-black area. You can take advantage of this, by for example letting the volume be continuously controlled by the height of the zapper while the notes would be played by shooting at targets at discrete horizontal points.

by on (#63702)
kalzone wrote:
Wow, quick and useful replies again...gotta love these forums. Shouldn't be surprised, coming from you, tepples--without you, I never would've made that emulator work.

Thanks. But sometimes, I worry about giving too much information. Give a fellow enough rope and he could hang himself; give him a gun and he could shoot himself in the foot or, worse, in the head like in Russian Roulette for NES :P

Quote:
I just want to make my Zapper/NES into a musical instrument

Would you be doing something like Electroplankton or perhaps my own AXE: The Poor Man's Electroplankton (video)?

Quote:
OK, so, I guess I'm a bit of a noob regarding how the NES handles IO, but by the sound of things, IO is memory-mapped, and those memory locations are the ones to poll when the zapper is plugged in.

Correct. Make a demo using the standard controller, and then you might start finding the Zapper easier.

Quote:
As far as targets, I was thinking of having maybe 3-4 octaves worth of notes, so either 36 or 48, and I was thinking that shooting away from the screen (not hitting any targets) would result in a change of instrument, or something.

Or you could have the standard controller held Wii Nunchuk-style in the other hand do half the work of selecting sounds.

Quote:
Is that a bit too high-resolution for the zapper?

You aren't going to easily discern more than about four targets on a given scanline.

by on (#63706)
Here is a really small zapper test I did a while back:
http://www.parodius.com/~memblers/nes/zappa.zip

It read the zapper about once per scanline (if even that, I don't know what the timing was in this) and changes the pitch of a sound channel based on that.

by on (#63709)
Hmm, you know, this might actually make a lot more sense as a DS app. I have a DS app and I can either churn this out in a few days or modify your demo or another demo in the span of a few hours, to do what I'm looking for. I'd want to find authentic-sounding 8-bit instruments though...

At the end of the day, it might make more sense to just do this with an NES->USB adapter, a MIDI controller, and some VST instruments designed to sound 8-bit.

Oh well...let's say I continued with the original plan. Memblers--what emulator do you recommend to try your zapper test? As far as I can tell using FCEUltra, the sound doesn't change according to zapper position.

by on (#63715)
kalzone wrote:
Oh well...let's say I continued with the original plan. Memblers--what emulator do you recommend to try your zapper test? As far as I can tell using FCEUltra, the sound doesn't change according to zapper position.


Is the zapper on the right port? Looks like the 2nd port, from the code. I seem to remember it working OK on emulators, but I did all of the code testing on my NES when I wrote it, so it definitely should work.

BTW maybe you could use a powerpad to hit the notes and the zapper to control the volume (good luck coordinating that though, heheh). :D

by on (#63716)
I guess that means you have a flash cart that works with the zapper? That's good news, no point in going through all this work just to emulate it on the PC.

Anyway, I was using controller port 1...using 2 seems to have solved the problem. Wow, seems like your code, with some minor adjustments, will actually do the trick.

I guess that leaves an easier question...what's the best place to get a flash cart? Or do you recommend just buying parts and constructing one?

Edit: I'm looking through your code and working through some 6502 references, and I'm not sure I understand the addressing mode here:
lda #%10011100

It's one byte, so I'm assuming that's immediate addressing, but for some reason that doesn't match the syntax of any of the reference materials I'm using.

by on (#63720)
The NES PowerPak is still the only easy option for a flash cart. I have an EPROM emulator device that I got maybe 8 years ago, that has been greatly useful but was about $200 at the time. It's great since I can use it everywhere an 8-bit EPROM can be used. I've designed my own flash cart but I've kept on redesigning and improving it (and sitting on it) rather than produce it yet (for a time, MIDINES was distributed on the 2nd revision of it though).

The PowerPak though is pretty decent, but the programs go onto flash cards. I would go nuts having to swap that out during testing. It would be same deal with EPROMS and Flash chips, which is why I got the ROM emulator.

If you already have a ROM burner, then it's pretty cheap to build a cart (just a matter of desoldering the old ROMs).

I use a toploading system mostly for this reason, for building your own you can't fit a socketed EPROM inside the cart shell (or past that metal bar in the cart holder). So you have take the top off the system off, at least (and use a bare board or cut out case).

kalzone wrote:
Edit: I'm looking through your code and working through some 6502 references, and I'm not sure I understand the addressing mode here:
lda #%10011100


That is immediate addressing like you thought, what may be unusual is that it's specifying the value in binary by using % instead of $ for hex (or lack of a symbol for decimal).

by on (#63868)
Memblers wrote:
Here is a really small zapper test I did a while back:
http://www.parodius.com/~memblers/nes/zappa.zip

It read the zapper about once per scanline (if even that, I don't know what the timing was in this) and changes the pitch of a sound channel based on that.


I remember reading about this. I ended up doing something myself as I was trying to figure out zapper behavio.
I used a light colored background, and continuously read from each zapper (it only plays the noise when you depress the trigger). Since many emulators do not allow a partial trigger, its more interesting on a real NES.

I assume this link works (src and rom)
http://www.4shared.com/account/file/3tU ... ounds.html

Al

by on (#63872)
Both of these samples come really close to what I had in mind. The only difference is that I want to limit (or at least be able to limit) the pitches that are played to the normal chromatic scale. As far as I can tell, that just means making a bunch of constants representing those pitches, and writing a quick procedure to basically round down to the nearest pitch in that array.

I think I at least understand enough of the assembly that I could write the constants and the floor function, but to save me a little bit of time, can you point out the lines that determine the pitches of the sound?

If I'm looking at this correctly, it looks like it's these lines in updateAudioLG1 and updateAudioLG2:

LDA LG1_SENSOR_STEP_1 ; timer low for Pulse 1
STA $4002
CLC
LDA #%01000000
ADC LG1_SENSOR_STEP_2 ; timer high for Pulse 1
STA $4003

LDA LG2_SENSOR_STEP_1 ; timer low for Pulse 1
STA $4006
CLC
LDA #%00100000
ADC LG2_SENSOR_STEP_2 ; timer high for Pulse 1
STA $4007

Am I correct in thinking the LG_SENSOR_STEP identifiers are coordinates of some sort?

by on (#63876)
In mine I have 2 separate 16-bit counters. one for each zapper. Those values are the upper and lower bytes of those counters.

You can see the values at the bottom of the screen.

I didnt really devote a lot of energy into making it sound good, I just wanted the 2 zappers to sound differently. I'm no expert on the square wave registers (and most of my attempts at NES music are terrible).

Al