Page 1 of 1

BCD increment without SED?

Posted: Sat Feb 22, 2020 8:26 pm
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

Re: BCD increment without SED?

Posted: Sun Feb 23, 2020 10:10 am
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

Re: BCD increment without SED?

Posted: Sun Feb 23, 2020 1:32 pm
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

Re: BCD increment without SED?

Posted: Sun Feb 23, 2020 4:32 pm
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

Re: BCD increment without SED?

Posted: Sun Feb 23, 2020 10:01 pm
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.

Re: BCD increment without SED?

Posted: Sun Feb 23, 2020 10:44 pm
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]

Re: BCD increment without SED?

Posted: Mon Feb 24, 2020 12:18 am
by GARTHWILSON
How far up does it need to count? Is 0-19 ok, or does it need to go further?

Re: BCD increment without SED?

Posted: Mon Feb 24, 2020 7:05 am
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...

Re: BCD increment without SED?

Posted: Mon Feb 24, 2020 2:28 pm
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

Re: BCD increment without SED?

Posted: Tue Feb 25, 2020 1:48 am
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

Re: BCD increment without SED?

Posted: Sat Feb 29, 2020 3:58 pm
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