Jump to content
Sign in to follow this  
Cafeman

need help - hex numbers to on-screen decimals

Recommended Posts

I am going in circles trying to do this, and I'm hoping it'll be quicker to just ask somebody for help.

 

What is the best way (simplest) to convert a variable named DragonKills from its hex value (say it is $25) into 2 bytes on-screen (antic 2) which would read "37", the decimal value?

 

I know how to strip the HI and LO bytes and change (for example) a value of $01 to $11 which is the printable ASCII version of "1". I'm asking for the math or loop which takes a hex value and creates 2 bytes in memory called HI and LO which will have values of "$3" and "$7" to represent the decimal value of "37".

 

thanks,

 

A'rgh!

 

(_)3

Share this post


Link to post
Share on other sites

For numbers in the decimal range 00 to 99 you can use the following :-

 

Convert2Bcd:
   lda #0
   sta BcdValue
   ldx #8
   sed
Convert2BcdLoop:
   asl Temp      ; Contains DragonKills (or what ever you need to convert)
   lda BcdValue
   adc BcdValue
   sta BcdValue
   dex
   bne Convert2BcdLoop
   cld

; Convert to displayable characters.
   lda BcdValue
   lsr
   lsr
   lsr
   lsr
   clc
   adc #Offset_To_Convert_To_ASCII    ; Convert to ASCII or a font (whatever you need to do).
   sta .... ; Write to video character memory.

   lda BcdValue
   and #$0F
   adc #Offset_To_Convert_To_ASCII
   sta ... ; Write to video character memory

 

If you need the range 0 to 255 you need to add this line of code "sta BcdValue+1" before the loop and add the following :-

 

   lda BcdValue+1
   adc BcdValue+1
   sta BcdValue+1

 

after the first set of lda/adc/sta operations in the loop. Obviously you can unroll the loop or optimise as required.

 

Hope that helps.

  • Like 1

Share this post


Link to post
Share on other sites

I am using a lookup table...

 

 

digit_lo: 012345678901234567890...

digit_hi: 000000000011111111112...

Share this post


Link to post
Share on other sites

That'd get a bit pricey if the value can range to 255.

 

Lots of games just keep the score/lives as screen codes, ie directly in display RAM.

 

Of course that's fine in most cases but not so great when you want to use them in calculations. If there's only the one variable for display/calculation then it might be easy to just keep a binary and screen code copy.

 

But IMO the BCD is the best allrounder - it's easy to convert to screen code and not too much effort to get to binary if needed, but BCD can be used easily enough in general calculations anyway.

 

If you dig around 6502.org there should be routines there to do stuff like converting 8-bit binary / BCD / ASCII.

 

Also, if you can stand the kinda slow speed and losing all the RAM it uses, the inbuilt FP-ROM routines are there. Wouldn't use them during a game though (aside from text adventure or turn-based game).

Edited by Rybags

Share this post


Link to post
Share on other sites

I modified GroovyBee's approach and it works fine. Here is the exact code for future reference.

 

LoadStatsToScreen2   
lda DragonKillsRank     
sta $383 		; work variable / memory location
jsr Convert2Bcd	
lda $381		; HI number
sta $13ca		; screen memory
lda $382		; LO number
sta $13cb		; screen memory
... other bcd convert jsr's here ...


; *** AdvII XE addition 7/7/2011 ***************************************************************************** XE
; *** 380 = work variable which will result in the converted bcd value - Ex: "$37" 
; *** 381 = HI digit - Ex: "$3"
; *** 382 = LO digit - Ex: "$7"
; *** 383 = put the hexadecimal number you want converted to bcd in 4383. Ex: "$25" (which is decimal 37)
Convert2Bcd: 
   lda #0 
   sta $380	;BcdValue 
   ldx #8 
   sed 
Convert2BcdLoop: 
   asl $383	;input variable 
   lda $380 	;BcdValue 
   adc $380 	;BcdValue 
   sta $380 	;BcdValue 
   dex 
   bne Convert2BcdLoop 
   cld 
; Convert to displayable characters. 
   lda $380 	;BcdValue 
   lsr a
   lsr a
   lsr a
   lsr a
   clc 
   AND #%00001111		;strip off left nibble
   ORA #%00010000		;Convert to ASCII or a font (whatever you need to do). 
   sta $381			;store HI digit
;
   lda $380			;BcdValue 
   and #$0F 
   ORA #%00010000		;modify to ascii value for screen
   sta $382			;store LO digit

Covert2BcdExit
rts
; *** AdvII XE END *************************************************************************************** XE END

Share this post


Link to post
Share on other sites

 

Lots of games just keep the score/lives as screen codes, ie directly in display RAM.

 

Of course that's fine in most cases but not so great when you want to use them in calculations. If there's only the one variable for display/calculation then it might be easy to just keep a binary and screen code copy.

 

But IMO the BCD is the best allrounder - it's easy to convert to screen code and not too much effort to get to binary if needed, but BCD can be used easily enough in general calculations anyway.

 

If you dig around 6502.org there should be routines there to do stuff like converting 8-bit binary / BCD / ASCII.

 

 

yeah, that's what I did for an earlier game of mine, Koffi: Yellow Kopter -- I just stored the score and lives as bcd right on-screen. But for this game I am checking the values of DragonKills and TimesEaten, etc, to derive a ranking (text), and then at the end of the game I need to convert them to displayable bcd. This worked.

Share this post


Link to post
Share on other sites

You could use the dec mode of the 6502 for the scores. Then you have the number always as dec, so no changing is needed. forget this comment.

 

In one of my projects I have up to 65535 Points. They are stored in a word. So for displaying them I splited this into 5 digits from 0 to 9. Below you can find the code.

 

ps1 to ps5 are the digits, points is the word

 

The code is old and not optimized yet, but it works for me.

;---------------------------------------------

;-- Punkte

punkte
lda #0
sta ps1
sta ps2
sta ps3
sta ps4
sta ps5

;-- Highbyte zuerst

lda points+1
sta pu
clc
lsr pu
lda #0
adc #0
cmp #1
bne p512

;-- 256
clc
lda #6
adc ps5
sta ps5
clc
lda #5
adc ps4
sta ps4
clc
lda #2
adc ps3
sta ps3

;-- 512

p512
clc
lsr pu
lda #0
adc #0
cmp #1
bne p1024
clc
lda #2
adc ps5
sta ps5
clc
lda #1
adc ps4
sta ps4
clc
lda #5
adc ps3
sta ps3

p1024
clc
lsr pu
lda #0
adc #0
cmp #1
bne p2048
clc
lda #4
adc ps5
sta ps5
clc
lda #2
adc ps4
sta ps4
clc
lda #0
adc ps3
sta ps3
clc
lda #1
adc ps2
sta ps2

p2048
clc
lsr pu
lda #0
adc #0
cmp #1
bne p4096
clc
lda #8
adc ps5
sta ps5
clc
lda #4
adc ps4
sta ps4
clc
lda #0
adc ps3
sta ps3
clc
lda #2
adc ps2
sta ps2

p4096
clc
lsr pu
lda #0
adc #0
cmp #1
bne p8192
clc
lda #6
adc ps5
sta ps5
clc
lda #9
adc ps4
sta ps4
clc
lda #0
adc ps3
sta ps3
clc
lda #4
adc ps2
sta ps2

P8192
clc
lsr pu
lda #0
adc #0
cmp #1
bne p16384
clc
lda #2
adc ps5
sta ps5
clc
lda #9
adc ps4
sta ps4
clc
lda #1
adc ps3
sta ps3
clc
lda #8
adc ps2
sta ps2

p16384
clc
lsr pu
lda #0
adc #0
cmp #1
bne p32768
clc
lda #4
adc ps5
sta ps5
clc
lda #8
adc ps4
sta ps4
clc
lda #3
adc ps3
sta ps3
clc
lda #6
adc ps2
sta ps2
clc
lda #1
adc ps1
sta ps1

p32768
clc
lsr pu
lda #0
adc #0
cmp #1
bne p1
clc
lda #8
adc ps5
sta ps5
clc
lda #6
adc ps4
sta ps4
clc
lda #7
adc ps3
sta ps3
clc
lda #2
adc ps2
sta ps2
clc
lda #3
adc ps1
sta ps1

;-- Lowbyte

p1
lda points
sta pu
clc
lsr pu
lda #0
adc #0
cmp #1
bne p2

;-- 1
clc
lda #1
adc ps5
sta ps5

;-- 2

p2
clc
lsr pu
lda #0
adc #0
cmp #1
bne p4
clc
lda #2
adc ps5
sta ps5

p4
clc
lsr pu
lda #0
adc #0
cmp #1
bne p8
clc
lda #4
adc ps5
sta ps5

p8
clc
lsr pu
lda #0
adc #0
cmp #1
bne p16
clc
lda #8
adc ps5
sta ps5

p16
clc
lsr pu
lda #0
adc #0
cmp #1
bne p32
clc
lda #6
adc ps5
sta ps5
clc
lda #1
adc ps4
sta ps4

P32
clc
lsr pu
lda #0
adc #0
cmp #1
bne p64
clc
lda #2
adc ps5
sta ps5
clc
lda #3
adc ps4
sta ps4

p64
clc
lsr pu
lda #0
adc #0
cmp #1
bne p128
clc
lda #4
adc ps5
sta ps5
clc
lda #6
adc ps4
sta ps4

p128
clc
lsr pu
lda #0
adc #0
cmp #1
bne punktemalen
clc
lda #8
adc ps5
sta ps5
clc
lda #2
adc ps4
sta ps4
clc
lda #1
adc ps3
sta ps3

punktemalen

;-- da sind noch überläufe...
lda ps5
cmp #10
beq p5st
bmi p4sta
p5st
clc
lda ps5
sbc #9
sta ps5
cmp #10
beq p5st2
bmi p5zehn
inc ps4
jmp p5st
p5st2
inc ps4
inc ps4
lda #0
sta ps5
jmp p4sta
p5zehn
inc ps4
;------------
p4sta
lda ps4
cmp #10
beq p4st
bmi p3sta
p4st
clc
lda ps4
sbc #9
sta ps4
cmp #10
beq p4st2
bmi p4zehn
inc ps3
jmp p4st
p4st2
inc ps3
inc ps3
lda #0
sta ps4
jmp p3sta
p4zehn
inc ps3
;--------------
p3sta
lda ps3
cmp #10
beq p3st
bmi p2sta
p3st
clc
lda ps3
sbc #9
sta ps3
cmp #10
beq p3st2
bmi p3zehn
inc ps2
jmp p3st
p3st2
inc ps2
inc ps2
lda #0
sta ps3
jmp p2sta
p3zehn
inc ps2
;--------------
p2sta
lda ps2
cmp #10
beq p2st
bmi p1sta
p2st
clc
lda ps2
sbc #9
sta ps2
cmp #10
beq p2st2
bmi p2zehn
inc ps1
jmp p2st
p2st2
inc ps1
inc ps1
lda #0
sta ps2
jmp p1sta
p2zehn
inc ps1
p1sta
;---------------------------
ldx #0
pl16
clc
lda ps1,x
adc #16
sta ps1,x
inx
cpx #5
bne pl16
ldx #0
ploop
lda pkt,x
sta text2,x
inx
cpx #4
bne ploop
ldx #0
ploop2
lda ps1,x
sta text2+4,x
inx
cpx #5
bne ploop2
rts

pkt
dta d'Pts:'

;---------------------------------------------

Edited by pps

Share this post


Link to post
Share on other sites

   clc 
   AND #%00001111		;strip off left nibble

 

You can remove the above lines in your implementation. The 4 LSR's already leave the top nybble zeroed out.

Share this post


Link to post
Share on other sites

   clc 
   AND #%00001111		;strip off left nibble

 

You can remove the above lines in your implementation. The 4 LSR's already leave the top nybble zeroed out.

 

It wasn't working for me. I compile with TASM. Could the LSR act differently across assemblers?

Share this post


Link to post
Share on other sites
It wasn't working for me. I compile with TASM. Could the LSR act differently across assemblers?

 

LSR should shift a 0 into bit7 as bit0 is shifted into carry. What hex value is the opcode for the instruction in your assembler? It should be 0x4A.

Share this post


Link to post
Share on other sites

I don't know. I stepped thru the code as you gave me to see where it wasn't working - I could have not entered something correctly, I don't know. But I made the additions based on what I observed happening, and the additional statements fixed it. I'm moving on. Thanks for the help very much! I have forgotten a lot.

Share this post


Link to post
Share on other sites

Here's a lovely little routine from codebase64:

 

; Converts .A to 3 ASCII/PETSCII digits: .Y = hundreds, .X = tens, .A = ones
; modify for Atari by subtracting $20 from the constants?

 ldy #$2f ; this should be '0'-1
 ldx #$3a ; this should be '0'+1
 sec
- iny
 sbc #100
 bcs -
- dex
 adc #10
 bmi -
 adc #$2f ; this should be '0'-1
 rts

 

http://www.codebase64.org/doku.php?id=base:tiny_.a_to_ascii_routine

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...