BCD increment without SED?

Programming the 6502 microprocessor and its relatives in assembly and other languages.
Post Reply
User avatar
mvk
Posts: 81
Joined: 21 Mar 2017

BCD increment without SED?

Post by mvk »

I'm looking to replace the following snippet with something that doesn't use decimal mode. It should increment TRIES if its lower nibble is under 9, or add 7 if that nibble equals 9. All other cases are "don't care".

Code: Select all

; Precondition: A = 0
                SEC
                SED
                ADC        TRIES         ; ADD 1 TO TRIES IN DECIMAL MODE
                STA        TRIES
                CLD
The replacement doesn't have to be in situ (that would surely be impossible). Speed is not important. Of course I know how to write something straightforward that works. But I'm hoping there's an amazingly clever bit trick out there that is just begging to be used.

Context: I'm trying to achieve a slightly more faithful execution of this number guessing game on a certain system without decimal mode. https://www.applefritter.com/files/Appl ... ermind.pdf
User avatar
mvk
Posts: 81
Joined: 21 Mar 2017

Re: BCD increment without SED?

Post by mvk »

This is my best shot. First put an escape in place with this JSR:

Code: Select all

                JSR        NXTBCD
                ADC        TRIES         ; ADD 1 TO TRIES IN DECIMAL MODE
                STA        TRIES
Then do the work in these 13 extra bytes:

Code: Select all

NXTBCD:         LDA        TRIES
                AND        #$F           ; Low nibble
                CMP        #9            ; Is it 9?
                BEQ        LOW9          ; If yes, add 7
                LDA        #4            ; Otherwise add 1
LOW9:           SBC        #3
                RTS
Testing works. The game's try counter wraps from $09 to $10:
Mastermind.png
Martin A
Posts: 197
Joined: 02 Jan 2016

Re: BCD increment without SED?

Post by Martin A »

I came up with this 15 byte routine using an ADC designed to roll over if 9+ is input, with a BBC basic wrapper for testing. If the target byte were in zero page it would shave off a couple of bytes, but it's still too big.

Code: Select all

REM BCD increment test
DIM code 30
FOR X%=0 TO 3 STEP 3
P%=code
[OPT X%
.byte
EQUB 0
EQUB 0
.start
LDA #&F7
CLC
ADC byte
BCS ten
SBC #5
.ten
SBC #&F0
STA byte
RTS
]
NEXT
FOR X%=0 TO 9
?byte=X%
CALL start
PRINT;~X%," ";~?byte
NEXT
The output is as expected for 0 to 9 (the ~ forces BBC basic to output numbers in hex)

Code: Select all

0941                    OPT X%
0941          .byte     
0941 00                 EQUB 0
0942 00                 EQUB 0
0943          .start    
0943 A9 F7              LDA #&F7
0945 18                 CLC
0946 6D 41 09           ADC byte
0949 B0 02              BCS ten
094B E9 05              SBC #5
094D          .ten      
094D E9 F0              SBC #&F0
094F 8D 41 09           STA byte
0952 60                 RTS
0          1
1          2
2          3
3          4
4          5
5          6
6          7
7          8
8          9
9          10
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Re: BCD increment without SED?

Post by 8BIT »

Sorry, I missed this part:
Quote:
Of course I know how to write something straightforward that works. But I'm hoping there's an amazingly clever bit trick out there that is just begging to be used.
I am not aware of much beyond masking the nibbles and testing for overflow method for generic BCD math.

If the goal is to count to 10, then this will work.

Code: Select all

	INC  TRIES
	LDA  TRIES
	CMP  #$0A
	BNE  DONE
	LDA  #$10
	STA  TRIES
DONE
Actually, this will count to 19 correctly.

Hope that helps!

Daryl
Please visit my website -> https://sbc.rictor.org/
User avatar
barrym95838
Posts: 2056
Joined: 30 Jun 2013
Location: Sacramento, CA, USA

Re: BCD increment without SED?

Post by barrym95838 »

Kind of slow, but smaller than the other patches and works through [edit: up to] 99 (allegedly):

Code: Select all

plus1:
   inc   tries
   lda   tries
   and   #$0f
   cmp   #$0a
   bcs   plus1
You can turn the middle three instructions into a subroutine if you don't want to affect your original labels.
Last edited by barrym95838 on Mon Feb 24, 2020 6:14 am, edited 1 time in total.
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)
User avatar
mvk
Posts: 81
Joined: 21 Mar 2017

Re: BCD increment without SED?

Post by mvk »

barrym95838 wrote:
Kind of slow, but smaller than the other patches and works through 99 (allegedly):
That is 10 bytes. The original has 7, so you need 3 bytes to avoid SED. That passes as amazingly clever with me.

[Edited out some of my earlier confusion]
User avatar
GARTHWILSON
Forum Moderator
Posts: 8775
Joined: 30 Aug 2002
Location: Southern California
Contact:

Re: BCD increment without SED?

Post by GARTHWILSON »

How far up does it need to count? Is 0-19 ok, or does it need to go further?
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
User avatar
mvk
Posts: 81
Joined: 21 Mar 2017

Re: BCD increment without SED?

Post by mvk »

GARTHWILSON wrote:
How far up does it need to count? Is 0-19 ok, or does it need to go further?
Certainly past 19. A bad guesser needs many tries. But it doesn't really matter what happens after 99...
User avatar
8BIT
Posts: 1787
Joined: 30 Aug 2002
Location: Sacramento, CA
Contact:

Re: BCD increment without SED?

Post by 8BIT »

barrym95838 wrote:
Kind of slow, but smaller than the other patches and works up to 99 (allegedly):

Code: Select all

plus1:
   inc   tries
   lda   tries
   and   #$0f
   cmp   #$0a
   bcs   plus1
You can turn the middle three instructions into a subroutine if you don't want to affect your original labels.
Nice work Mike! Since speed was not an issue, this is a tidy solution.

Daryl
Please visit my website -> https://sbc.rictor.org/
Chromatix
Posts: 1462
Joined: 21 May 2018

Re: BCD increment without SED?

Post by Chromatix »

This seems like a straightforward way to do it, testing the lower nybble directly and conditionally forcing it to carry through:

Code: Select all

Plus1:
  LDA tries
  AND #$F
  CMP #9
  BNE :+
  LDA #$F
: ORA tries
  STA tries
  INC tries
  RTS
This is 16 bytes, 22 cycles (without the RTS since you can inline this), and avoids the looping. It could be 15 bytes, 19 cycles if specialised for a CMOS 6502, which I'm pretty sure got used in the Tamagotchi toys:

Code: Select all

Plus1C:
  LDA tries
  AND #$F
  CMP #9
  BNE :+
  LDA #$F
: ORA tries
  INC A
  STA tries
  RTS
User avatar
mvk
Posts: 81
Joined: 21 Mar 2017

Re: BCD increment without SED?

Post by mvk »

barrym95838 wrote:
Kind of slow, but smaller than the other patches
I replaced my solution with yours. By keeping it inline, the original program grows with just 2 bytes to a grand total of 172. Bravo!

https://github.com/kervinck/gigatron-ro ... ae0d1307f6
Post Reply