Zapper Implementation

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems.

Moderator: Moderators

Post Reply
Roth
Posts: 400
Joined: Wed Aug 03, 2005 3:15 pm
Contact:

Zapper Implementation

Post by Roth »

Right now, I'm trying to figure out how to get the zapper to fire one shot at a time. As it stands, when I hold the right-click button down on the mouse, it repeats over and over and over again. I can't quite figure out what to do to make it single shot, such as in every other zapper game : P

Here is the code I have presently running in NMI:

Code: Select all

battling:
	lda check_shot
	beq :+
		jsr object1_tile_switch
		lda reg2001_save
		ora #%00001000
		sta $2001
		sta reg2001_save
		lda #$00
		sta check_shot
	jmp @not_pulled

:	lda $4017
	and #test_trigger
	beq @not_pulled
		lda #$01
		sta check_shot
		lda reg2001_save
		and #%11110111
		sta $2001
		sta reg2001_save
@not_pulled:

The jsr object1_tile_switch is actually a badly named routine right now, as it's actually a palette switch for the testing (filling all white). I'm guessing this would be the way to do it, anyway.

But yeah, any ideas on how to make the zapper fire only once per frame when pulled? Thanks for any input; pun intended! ; )
User avatar
Memblers
Site Admin
Posts: 3901
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers »

I'd try treating it the same as a controller - save the zapper state from the previous frame, then branch if it was previously triggered. The zapper demo I made didn't even try to use the trigger.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru »

Wouldn't this be the same as detecting only buttons that were just pressed on the joypad (as opposed to the ones that remain pressed since last time)? That is, invert the old state (EOR $FF) and AND with the current state.

That way, assuming the button/trigger was not pressed last frame, the old state is 0. The old state inverted becomes 1, AND'ed to the new state 1 (button/trigger is pressed) will result in 1, so the button/trigger has *just* been pressed. On the next frame, the old state is 1, and the new is also 1 (button/trigger remains pressed). 1 (old state) inverted is 0, AND'ed with 1 (new state) results in 0, so the button/trigger is either not pressed or remains pressed since last time, but you are not interested in either of those cases.
Celius
Posts: 2159
Joined: Sun Jun 05, 2005 2:04 pm
Location: Minneapolis, Minnesota, United States
Contact:

Post by Celius »

Didn't I hear something about how you have to read it every scanline? Or is that just when you are checking to see if there was a hit?

I'm assuming actually that's just during the reading phase that you have to check every scanline. But what I do in my game is I have three variables:

ControlPrevious
ControlCurrent
ControlTrigger

And this is how my controller code looks:

Code: Select all


	lda ControlCurrent
	sta ControlPrevious

	ldx #1
	stx $4016
	dex
	stx $4016

	ldy #8
-
	lda $4016
	lsr a
	rol ControlCurrent
	dey
	bne -

	lda ControlCurrent
	and ControlPrevious
	eor ControlCurrent
	sta ControlTrigger
For ControlCurrent and ControlPrevious, it's obvious what those hold. Current holds the current button press bits for this frame. Previous holds the previous frame's button press status. And of course, each bit in the byte holds the status for the corresponding button:

Bit 7 - A button status
Bit 6 - B button status
Bit 5 - Select button Status (or is it start?)
Bit 4 - Start button Status (or is it select? I get these two confused all the time)
Bit 3 - Up button status
Bit 2 - Down button status
Bit 1 - Left button status
Bit 0 - Right button status

However, ControlTrigger holds which buttons have been NEWLY pressed. If you press A this frame, and it hasn't been pressed last frame, it will return a 1 in bit 7. However, if you have pressed A last frame, it will not return a 1 in bit 7. I call it "ControlTrigger" because it kind of reminds me of a trigger of a pistol being pulled or something where it only has effect the instant it's pulled. I didn't know what else to call it. It's really nice to have this byte because I can do things like:

lda ControlTrigger
and #BButton
bne Shoot
.... blah blah code for not shooting

Shoot:
.... blah blah code for shooting

I would absolutely stay away from reading hardware registers in game logic code as much as possible. It is kind of a bug waiting to happen in my opinion. So I would put all the information for button presses and trigger status into bytes in RAM.
Post Reply