snicklin Posted April 12, 2015 Share Posted April 12, 2015 I could probably work this out with enough time, but I guess that enough of you clever people know how to do something like this.... I have an integer stored as a byte which can be a value of between 0 and 99 inclusive. I then want to create a filename, so I need this number as text. If the integer is between 0 and 9 inclusive, I would like to print it as "07" (i.e. a zero at the start). If the integer is greater than 9 and will always be less than 100, I just want the number as the 1st 2 bytes of the filename. I want some compact code to do this, could I use CIOV somehow? Or can I do better with your code? Quote Link to comment Share on other sites More sharing options...
dmsc Posted April 12, 2015 Share Posted April 12, 2015 I could probably work this out with enough time, but I guess that enough of you clever people know how to do something like this.... I have an integer stored as a byte which can be a value of between 0 and 99 inclusive. I then want to create a filename, so I need this number as text. If the integer is between 0 and 9 inclusive, I would like to print it as "07" (i.e. a zero at the start). If the integer is greater than 9 and will always be less than 100, I just want the number as the 1st 2 bytes of the filename. I want some compact code to do this, could I use CIOV somehow? Or can I do better with your code? Untested, should work: example: lda #<outputPtr sta ptr lda #>outputPtr sta ptr++1 lda inputNumber sta number jsr p2dig end: jmp end ; Outputs a decimal three digit number from "000" to "999", ; input is in ZP variable "number" and output is written ; to address in ZP variables "ptr" p3dig: jsr p1dig ; Fall-through ; Outputs a decimal two digit number from "00" to "99", ; input is in ZP variable "number" and output is written ; to address in ZP variables "ptr" p2dig: jsr p1dig ; Fall-through ; Outputs a decimal one digit number from "0" to "9", ; input is in ZP variable "number" and output is written ; to address in ZP variables "ptr" p1dig: ldx #8 ; 8 bit division... lda #0 ; remainder divL: asl number rol a cmp #10 bcc noInc sbc #10 inc number noInc: dex bne divL ora #48 sta (ptr),y iny rts Quote Link to comment Share on other sites More sharing options...
ricortes Posted April 12, 2015 Share Posted April 12, 2015 When I had a similar problem, I ended up using the internal FP routines to do the conversion. Takes a while to learn the use of the routines. Ended up being useful for several programs at the time but haven't used them much if at all since. Quote Link to comment Share on other sites More sharing options...
dmsc Posted April 12, 2015 Share Posted April 12, 2015 Untested, should work: Obviously, didn't work :-( This is a working version, there are entry points for 3 digits (p3dig), 2 digits (p2dig) and one digit (p1dig). example: lda #<outputPtr sta ptr lda #>outputPtr sta ptr+1 lda inputNumber sta number jsr p2dig end: jmp end ; Outputs a decimal three digit number from "000" to "999", ; input is in ZP variable "number" and output is written ; to address in ZP variables "ptr" p3dig: ldy #2 jsr div10 ; Fall-through ; Outputs a decimal two digit number from "00" to "99", ; input is in ZP variable "number" and output is written ; to address in ZP variables "ptr" p2dig: ldy #1 ; Fall-through div10: ldx #8 ; 8 bit division... lda #0 ; remainder divL: asl number rol cmp #10 bcc noInc sbc #10 inc number noInc: dex bne divL ora #48 sta (ptr),y ; Outputs a decimal one digit number from "0" to "9", ; input is in ZP variable "number" and output is written ; to address in ZP variables "ptr" p1dig: ldy #0 lda number putdig: ora #48 sta (ptr),y rts Quote Link to comment Share on other sites More sharing options...
mono Posted April 12, 2015 Share Posted April 12, 2015 (edited) Try to organize your counter as a decimal one and advance it with: sed clc lda #1 adc counter sta counter cld Then conversion to 2-digit string is: lda counter lsr lsr lsr lsr ora #'0' tax lda counter and #$f ora #'0' The result is in XA, where X=dozens, A=units ATASCII characters - put they where you like. Edited April 12, 2015 by mono Quote Link to comment Share on other sites More sharing options...
snicklin Posted April 13, 2015 Author Share Posted April 13, 2015 Thank you all for your input. I will just take a little time to analyse each suggestion and then I'll answer back. If anyone else has any ideas, feel free to continue to suggest ways... Quote Link to comment Share on other sites More sharing options...
kenjennings Posted April 13, 2015 Share Posted April 13, 2015 I'd go with the suggestion above to use BCD mode. That stores value '0' to '9' in each nybble of the byte making it easy to mask/convert to the text equivalent. (Remember to turn off decimal mode if it is not needed for the rest of your program.) 1 Quote Link to comment Share on other sites More sharing options...
snicklin Posted April 13, 2015 Author Share Posted April 13, 2015 Try to organize your counter as a decimal one and advance it with: sed clc lda #1 adc counter sta counter cld Hi Mono, Could you clarify the above code a little more please? (sorry, I'm new to this decimal mode). What is the difference between this and me doing a normal increment? Steve Quote Link to comment Share on other sites More sharing options...
MaPa Posted April 13, 2015 Share Posted April 13, 2015 What is the difference between this and me doing a normal increment? In normal mode 9+1=$a, in decimal mode 9+1=$10. Quote Link to comment Share on other sites More sharing options...
Rybags Posted April 13, 2015 Share Posted April 13, 2015 If the intent is to simply have a printable counter and not do any other operations it's probably easiest to just maintain it as either the ASCII or internal screen codes in seperate bytes. The increment loop gets a bit longer and complex but you remove the need for conversion. Quote Link to comment Share on other sites More sharing options...
mono Posted April 13, 2015 Share Posted April 13, 2015 Hi Mono, Could you clarify the above code a little more please? (sorry, I'm new to this decimal mode). What is the difference between this and me doing a normal increment? Steve BCD mode is described here: http://www.6502.org/tutorials/decimal_mode.html In common words this does as MaPa said. Any disadvantage is that inc/dec opcodes not run with BCD, so you need to use adc/sbc instead. As kenjennings wrote - keep in mind to do CLD after "increment". Quote Link to comment Share on other sites More sharing options...
snicklin Posted April 13, 2015 Author Share Posted April 13, 2015 If the intent is to simply have a printable counter and not do any other operations it's probably easiest to just maintain it as either the ASCII or internal screen codes in seperate bytes. The increment loop gets a bit longer and complex but you remove the need for conversion. I intend to be using the values for more than just printing to a memory location, so I need to keep it as the original values (0-99) and then convert them. And to others, thanks for explaining the difference between the modes. This is all helping my 6502 education, thanks for the assistance. Quote Link to comment Share on other sites More sharing options...
pirx Posted April 13, 2015 Share Posted April 13, 2015 The fast version lda first,x sta out lda second,x sta out+1 ;.... first :10 .byte '0' :10 .byte '1' :10 .byte '2' :10 .byte '3' :10 .byte '4' :10 .byte '5' :10 .byte '6' :10 .byte '7' :10 .byte '8' :10 .byte '9' second :10 .byte '0123456789' 1 Quote Link to comment Share on other sites More sharing options...
pirx Posted April 13, 2015 Share Posted April 13, 2015 You know what, I have exactly a routine doing this stuff: ;-------------------------------------------------- displaybyte ;decimal (byte), displayposition (word) ;-------------------------------------------------- ; displays decimal number as in parameters (in text mode) ; the range is (00..99 - one byte) ldy #1 ; there will be 2 digits NextDigit2 ldx #8 ; 8-bit dividee so Rotate 8 times lda #$00 Rotate001 asl decimal rol ; scroll dividee cmp #10 ; divider bcc TooLittle001 ; if A is smaller than divider ; there is nothing to substract sbc #10 ; divider inc decimal ; because it is 0 and this is the fastest way TooLittle001 dex bne Rotate001 ; and Rotate 8 times, Result will be in decimal tax ; and the rest in A ; (and it goes to X because ; it is our decimal digit) lda digits,x sta decimalresult,y dey bpl NextDigit2 ; Result again /10 and we have next digit decimalend1 ; displaying mwa displayposition modify ldy #1 displayloop1 lda decimalresult,y sta (modify),y dey bpl displayloop1 rts ;-------decimal constans digits dta d"0123456789" decimalresult .word 0 ;-------------------------------------------------------- It is awful but works. Style sucks because it was migrated from MAC65 to mads (through OMC65 in between). This is modified from a routine displaying more than 2 digits. Quote Link to comment Share on other sites More sharing options...
snicklin Posted April 18, 2015 Author Share Posted April 18, 2015 OK, thank you everyone so far for your input. You've all been great and show me just how good that the Atari 8-bit community is. I think that the solution from Pirx and Dmsc are similar. I didn't want to go with the counter option as I am not counting up, I am using the code to refer to tables and databases as numbers within a filename. I got Pirx's code (as it was similar to Dmsc and I had to use one of them) and used that as a basis. I've then customised it to my requirements. I pass in a value in the accumulator and expect the result out in acc and x as 2 digits. Internal_Convert099: STA decimal LDY #1 NextDigit2: LDX #8 LDA #0 Rotate001: ASL decimal ROL CMP #10 BCC TooLittle001 SBC #10 INC decimal TooLittle001: DEX BNE Rotate001 TAX LDA digits,x STA decimalresult,y DEY BPL NextDigit2 storeResults: LDX decimalresult+1 LDA decimalresult+0 RTS ;-------decimal constants digits: dta 48,49,50,51,52,53,54,55,56,57 decimalresult: .word 0 decimal: .byte I could probably refine this a little, but I'll come back to that later, this is working as is. Thanks once more to all. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.