News: 11 March 2016 - Forum Rules
Current Moderators - DarkSol, KingMike, MathOnNapkins, Azkadellia, Danke

Author Topic: A couple of ASM things I don't understand  (Read 2240 times)

RetroRain

  • Sr. Member
  • ****
  • Posts: 287
    • View Profile
A couple of ASM things I don't understand
« on: October 03, 2015, 04:35:56 pm »
Despite doing ASM all of these years, there are still some things I don't understand.

Code: [Select]
; Strobe D-pad.  I get this.
 05:A0E1:A9 01     LDA #$01
 05:A0E3:8D 16 40  STA $4016 = #$FF
 05:A0E6:A9 00     LDA #$00
 05:A0E8:8D 16 40  STA $4016 = #$FF


 05:A0EB:A2 04     LDX #$04
 05:A0ED:AD 16 40  LDA $4016 = #$FF
 05:A0F0:29 03     AND #$03
 05:A0F2:C9 01     CMP #$01
 05:A0F4:26 40     ROL $0040 = #$00
 05:A0F6:CA        DEX
 05:A0F7:D0 F4     BNE $A0ED
 05:A0F9:A5 40     LDA $0040 = #$00
 05:A0FB:29 07     AND #$07
 05:A0FD:60        RTS

Why is there a CMP #$01 after AND #$03 if there is no branch immediately after it?  Wouldn't that make the CMP #$01 pointless?

And the ROL $0040... ROL shifts the bits right, and one of them goes into Carry.  So am I correct that Carry is not simply a flag?  It is capable of holding a bit?  When carry is Clear, it is 0 (not set), and when Carry is Set, it is 1 (set)?

Bregalad

  • Hero Member
  • *****
  • Posts: 2755
    • View Profile
Re: A couple of ASM things I don't understand
« Reply #1 on: October 03, 2015, 04:49:44 pm »
CMP sets the carry flag on a comparison result, and ROL uses that carry flag to be inserted in the LSB of the accumulator. This controller reading routines want to acknowledge that a button has been pressed if either bit 0 or bit 1 or $4016 is set, because on famicom consoles, bit 0 correspond to the hardwired controller while bit 1 correspond to an attachable controller. Almost all games have something like that in their controller code.

Quote
So am I correct that Carry is not simply a flag?  It is capable of holding a bit?
That makes absolutely no difference - a "flag" or a "bit" are just two ways to call the same thing.

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: A couple of ASM things I don't understand
« Reply #2 on: October 03, 2015, 04:54:04 pm »
+1 @ Bregalad

Also:

So am I correct that Carry is not simply a flag?  It is capable of holding a bit?  When carry is Clear, it is 0 (not set), and when Carry is Set, it is 1 (set)?

Flags ARE a single bit.  set=1 and clear=0

Carry isn't anything special in that regard -- that's just what a flag is.

RetroRain

  • Sr. Member
  • ****
  • Posts: 287
    • View Profile
Re: A couple of ASM things I don't understand
« Reply #3 on: October 03, 2015, 04:58:40 pm »
Okay.  So, that code is always making the rightmost bit of $40 1 by using the CMP and then the ROL?

dougeff

  • Sr. Member
  • ****
  • Posts: 358
    • View Profile
Re: A couple of ASM things I don't understand
« Reply #4 on: October 03, 2015, 05:08:21 pm »
So, this is a button reading routine...and apparently the most accepted version of it. It's testing each button, one at a time, to see it's being pressed. That information will be in the lowest bit (for US controller 1, and the next bit over for Famicom expansion port controller 1) of Register 4016.

AND #03 is isolating just those 2 bits.
CMP #01 is seeing if either version of controller 1 is pushing a certain button. If neither is, the Carry flag will be 0, if either is, the Carry flag will be 1.
ROL $40 is shifting the bits of RAM address 0x40 left, and its shifting the Carry flag value into the least bit of address 0x40.

This is repeated 8 times, one for each button. Thus storing button presses at Ram 0x40
« Last Edit: October 03, 2015, 05:15:40 pm by dougeff »
nesdoug.com -- blog/tutorial on programming for the NES

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: A couple of ASM things I don't understand
« Reply #5 on: October 03, 2015, 05:11:59 pm »
Not quite

Usually a routine like this would read the entire joypad state into $40... but here it's only looping 4 times instead of the usual 8, so it's actually only taking the A,B,Select,Start buttons

The end result is:

$40.3 = set if A button pressed, clear if A released
$40.2 = B button
$40.1 = Select button
$40.0 = Start button

Code: [Select]
05:A0ED:AD 16 40  LDA $4016 = #$FF      ; get one button's state (in either bit 0 or bit 1)

05:A0F0:29 03     AND #$03              ; isolate bits 0,1

05:A0F2:C9 01     CMP #$01              ; see if A >= 1 (either bit set)
                                        ;   if either bit is set, C=1
                                        ;   if both bits clear, C=0
                                        ; so effectively, C=button state
                                       
05:A0F4:26 40     ROL $0040 = #$00      ; rotate button state into $40

05:A0F6:CA        DEX                   ; repeat 4 times total (A,B,Select,Start)
05:A0F7:D0 F4     BNE $A0ED

It works out like so:
Code: [Select]
$40 = the below
_____________________
%00000000   ; <- at startup
%0000000A   ; <- first loop
%000000AB   ; <- second
%00000ABs   ; <- third (s=select)
%0000ABsT   ; <- final (T=start)


I was ninja'd by dougeff, but I think my example might still help, so posting anyway

RetroRain

  • Sr. Member
  • ****
  • Posts: 287
    • View Profile
Re: A couple of ASM things I don't understand
« Reply #6 on: October 03, 2015, 05:17:53 pm »
I hate bit math.  I really do.  I honestly never had to deal with it all of these years, and I was glad that I didn't have to.

I'm not going to lie and say I understand this when I don't.

But I'm going to try a different work-around for the hack I'm working on.  I didn't want to use a different button, but it will still produce the same result.  I'll keep this thread for a reference, but I'm sure one of these days I'm going to have to "get" this.

Thanks for your help guys.  I'll keep this information for reference.

Disch

  • Hero Member
  • *****
  • Posts: 2814
  • NES Junkie
    • View Profile
Re: A couple of ASM things I don't understand
« Reply #7 on: October 03, 2015, 05:44:53 pm »
Binary logic isn't that hard to follow -- it just isn't arithmetic so you might not be as used to it.  But in a way, it's actually simpler.

The trickiest part with the logic is the CMP, but that's only tricky if you think of CMP only in terms of bundling with a branch -- and not in terms of what CMP is actually designed to do (set flags):

CMP takes 2 values, A and the value given ('V').
Its primary function is to set C and Z flags according to the result of comparing those 2 values:

Code: [Select]
if  A > V   :   C=1   Z=0
if  A = V   :   C=1   Z=1
if  A < V   :   C=0   Z=0

With that in mind... one more example to try and show the logic flow a bit more clearly:

Code: [Select]
; 'A' = accumulator
; 'B' = button state
; 'C' = carry flag

LDA $4016       ; A = %??????BB

AND #%00000011  ; A = %000000BB

CMP #$01        ; C = B

ROL $40         ; $40 = %???????B