New Project

A place where you can keep others updated about your NES-related projects through screenshots, videos or information in general.

Moderator: Moderators

dsv101
Posts: 36
Joined: Fri Jun 17, 2011 5:16 am
Location: United States
Contact:

Post by dsv101 » Sun Jun 26, 2011 5:49 pm

i read it all, i just have to do some other things to get me familiar with NES Programming which what you told me will come into my code soon.

I never ignore advice, good or bad, it's just how i am :)

Now i feel that im creating a bad vibe with you guys, i'm sorry :/
~Yeah, I Said That

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Sun Jun 26, 2011 6:37 pm

Thank you tokumaru and 3gengames for the positive encouragement here! :D

User avatar
tokumaru
Posts: 11858
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Sun Jun 26, 2011 7:12 pm

dsv101 wrote:Now i feel that im creating a bad vibe with you guys, i'm sorry :/
No bad vibe, don't worry...

You can do as you want now that the advice is given. If you have read what we said and still think that for now you should read the controller your way, then that's your choice. Sometimes we need first hand experience to understand why something is good/bad as opposed to just trusting others.

I assure you that soon you'll feel the need to switch to the other method! 8)

3gengames
Formerly 65024U
Posts: 2277
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Sun Jun 26, 2011 7:50 pm

If you make the routine use Y for the counter and X to loop which controller to read, then you can also read both controllers if you save another byte and on the ROL and LSR use the mode $4016,X and then ControllerButtons,X and read both controllers inside one loop with about 5 extra lines of code. My game read 4 controllers going through only 2 loops and then passes them to my main program. It a huge help to be able to do so much with a simple JSR, you'll learn the significance of using these types of techniques as your programs get bigger and you get more experienced.

dsv101
Posts: 36
Joined: Fri Jun 17, 2011 5:16 am
Location: United States
Contact:

Post by dsv101 » Sun Jun 26, 2011 10:19 pm

thanks or the advice guys :)
~Yeah, I Said That

tepples
Posts: 22052
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Mon Jun 27, 2011 5:20 am

It's possible to use the output byte itself as the counter by prefilling it with $01. The ROL clears the carry until after the eighth read, when it sets the carry to true.

In addition, systems with hardwired controllers (such as the original Family Computer sold in Japan) put the hardwired controller on bit 0 and the plugged-in controller on bit 1. Reading the pad produces $x1 if a button on a hardwired controller is pressed or $x2 if the corresponding button on the plugged-in controller is pressed. So AND with $03 to ignore all other bits and compare with 1 to set carry if one or both of the buttons is pressed.

Here's the code I use, which modifies neither X nor Y (for various reasons related to postprocessing that I'll teach about later):

Code: Select all

JOY1 = $4016
JOY2 = $4017

read_both_pads:
  lda #$01
  sta keys_held_2p  ; set up so that the 8th ROL will SEC
  sta JOY1          ; latch button states into the pads'
  lda #0            ; shift registers
  sta JOY1
  loop:
    lda JOY1
    and #$03   ; on Famicom, 1 means a press on the hardwired
    cmp #1     ; pad and 2 means a press on a plugged-in pad
    rol keys_held_1p
    lda JOY2
    and #$03
    cmp #1
    rol keys_held_2p  ; after eight of these, the 1 bit from
    bcc loop          ; $01 has made its way to carry
  rts

3gengames
Formerly 65024U
Posts: 2277
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Mon Jun 27, 2011 9:16 am

I've never even though of clearing the pads before, that's a great idea! I'm about to do that in my code. :D But even I am confused on the AND #$03 and then CMP #$01. Shouldn't you can the big you want since any unwanted bit read from DB2 will make a true read on the single value since it wasn't cleared from the AND? And in that case, it'd just be better to LDA and then ROL, right?

User avatar
tokumaru
Posts: 11858
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Post by tokumaru » Mon Jun 27, 2011 9:50 am

3gengames wrote:I am confused on the AND #$03 and then CMP #$01
Some Famicom controllers return the button states in bit 1 instead of bit 0, so the AND #$03 is meant to keep the two bits that can possibly contain button states. The CMP #$01 detects whether a button is pressed regardless of the bit. If either bit is set, the button is pressed.

3gengames
Formerly 65024U
Posts: 2277
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Mon Jun 27, 2011 10:44 am

tokumaru wrote:
3gengames wrote:I am confused on the AND #$03 and then CMP #$01
Some Famicom controllers return the button states in bit 1 instead of bit 0, so the AND #$03 is meant to keep the two bits that can possibly contain button states. The CMP #$01 detects whether a button is pressed regardless of the bit. If either bit is set, the button is pressed.
Okay, but the controllers are hardwired on, wouldn't that mean any controller attached to the expansion port would interfere wit hthe hardwired controller and vice versa?

tepples
Posts: 22052
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples » Mon Jun 27, 2011 12:39 pm

Conventionally, the hardwired controllers on an original Famicom (or the ones plugged into the front ports on the AV model) are numbered 1 and 2, and the plug-in controllers 3 and 4. Player 1 may use controller 1 (first hardwired controller) or 3 (first plug-in controller), and player 2 may use controller 2 or 4. As I understand it, only a four-player game treats all four as distinct input sources.

3gengames
Formerly 65024U
Posts: 2277
Joined: Sat Mar 27, 2010 12:57 pm

Post by 3gengames » Mon Jun 27, 2011 12:41 pm

Okay, I guess that makes sense, although on NES I guess the data bits are different, so that's why it was confusing. Okay, cool.

unregistered
Posts: 1075
Joined: Thu Apr 23, 2009 11:21 pm
Location: cypress, texas

Post by unregistered » Mon Jun 27, 2011 1:03 pm

tokumaru wrote:
3gengames wrote:I am confused on the AND #$03 and then CMP #$01
Some Famicom controllers return the button states in bit 1 instead of bit 0, so the AND #$03 is meant to keep the two bits that can possibly contain button states. The CMP #$01 detects whether a button is pressed regardless of the bit. If either bit is set, the button is pressed.
CMP is magical? :? How does CMP #$01 detect whether a button is pressed rehgardless of the bit?

User avatar
Bregalad
Posts: 7951
Joined: Fri Nov 12, 2004 2:49 pm
Location: Chexbres, VD, Switzerland

Post by Bregalad » Mon Jun 27, 2011 1:12 pm

unregistered wrote:CMP is magical? :? How does CMP #$01 detect whether a button is pressed rehgardless of the bit?
The "magic" is that CMP #$01 is basically equivalent to C <- !Z and CMP #$80 is basically equivalent to C <- N

You can quite often make your code smaller/faster using those two tricks.
Useless, lumbering half-wits don't scare us.

User avatar
qbradq
Posts: 951
Joined: Wed Oct 15, 2008 11:50 am

Post by qbradq » Mon Jun 27, 2011 1:22 pm

I haven't looked at the code, but I suspect it is using BCS (Branch if Carry Set). After the CMP (CoMPare) instruction if the value in the A register is greater than or equal to the value in memory (in this case the value 1) the Carry flag will be set.

So basically this lets you say "if the controller data is greater than zero".

There's a faster way though. After your lda instruction, use BEQ (Branch if EQual) or BNE (Branch if Not Equal). After a load instruction the Zero flag will be set if the value loaded is zero, clear otherwise.

Example:

Code: Select all

ldx #8
polling_loop:
  asl controller_state
  lda reg_ctrl_port1
  beq next
  inc controller_state
next:
  dex
  bne polling_loop

User avatar
thefox
Posts: 3141
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Post by thefox » Mon Jun 27, 2011 1:32 pm

qbradq wrote:There's a faster way though. After your lda instruction, use BEQ (Branch if EQual) or BNE (Branch if Not Equal). After a load instruction the Zero flag will be set if the value loaded is zero, clear otherwise.
Nope, that doesn't work, you have to use AND because the top bits are not connected when reading $4016, so they usually (if cart doesn't have resistors on the data bus, like PowerPak) return the top bits of the value that was previously on the data bus (most often $4x). See http://nesdev.com/rom.txt for more details.

Post Reply