Discussion:
Apple Monitor: Print Integer?
(too old to reply)
Harry Potter
2017-07-01 18:39:25 UTC
Permalink
Hi! I remember seeing recently an entry in the Apple 2 Monitor to print an integer to the screen but forgot where the routine is located and its name. What are the name and address of the routine, and does it print signed or unsigned integers?
r***@gmail.com
2017-07-03 01:47:02 UTC
Permalink
Hi! I remember seeing recently an entry in the Apple 2 Monitor to print an integer ...
The Apple II monitor can print hexadecimal. Printing a decimal value would require a divide routine which was only in the original monitor.

The routine at $F941 prints A in hex then X in hex.
Michael J. Mahon
2017-07-03 03:42:56 UTC
Permalink
Post by r***@gmail.com
Hi! I remember seeing recently an entry in the Apple 2 Monitor to print an integer ...
The Apple II monitor can print hexadecimal. Printing a decimal value
would require a divide routine which was only in the original monitor.
The routine at $F941 prints A in hex then X in hex.
There's an Applesoft ROM routine that prints a 16-bit unsigned
integer--it's called to print line numbers.
--
-michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com
Denis Molony
2017-07-03 03:52:29 UTC
Permalink
Does this help?

http://apple.rscott.org/tools/view.htm?crc=5d17ffe8385031e&n=14

Is LINPRNT (ED24) what you were thinking of?
Michael J. Mahon
2017-07-03 05:58:03 UTC
Permalink
Post by Denis Molony
Does this help?
http://apple.rscott.org/tools/view.htm?crc=5d17ffe8385031e&n=14
Is LINPRNT (ED24) what you were thinking of?
It looks like it. ;-)
--
-michael - NadaNet 3.1 and AppleCrate II: http://michaeljmahon.com
Harry Potter
2017-07-03 10:55:49 UTC
Permalink
Post by Denis Molony
Does this help?
http://apple.rscott.org/tools/view.htm?crc=5d17ffe8385031e&n=14
Is LINPRNT (ED24) what you were thinking of?
Looks like it to me, also. Thank you! :)
Harry Potter
2017-07-04 22:43:56 UTC
Permalink
Post by Harry Potter
Post by Denis Molony
Does this help?
http://apple.rscott.org/tools/view.htm?crc=5d17ffe8385031e&n=14
Is LINPRNT (ED24) what you were thinking of?
Looks like it to me, also. Thank you! :)
The LINPRNT entry didn't work. :( Nothing was displayed when I tried it. I need this for my Apple2SimpleIO library for cc65: if I can get the ROM to print numbers for me, then I would need a lot less code to perform the function. :)
Michael 'AppleWin Debugger Dev'
2017-07-05 03:50:33 UTC
Permalink
Do you need 2 digit, 3 digit, or 5 digit output?
Why not use the code from my printm() library?
https://github.com/Michaelangel007/apple2_printm

Here is the integer portion ripped along with a demo.
I only tested it assembles with Merlin32.
The original printm() code assembles with cc65.

- - - 8< - - -

_temp = $FE

COUT = $FDED

ORG $800

LDY #$12
LDX #$34
JSR PrintDec5
RTS

; # Dec 1 Byte (max 2 digits)
; d Dec 2 Byte (max 3 digits)
; u Dec 2 Byte (max 5 digits)
; ======================================================================

PrintDec5
LDA #5/2 ; offset into _bcd buffer
db $2C ; BIT $abs skip next instruction

PrintDec3
LDA #3/2 ; offset into bcd buffer
db $2C ; BIT $abs skip next instruction

PrintDec2
LDA #0 ; special: print 2 digits

_PrintDec
STA DecWidth+1

STX _temp+0
STY _temp+1

PrintDecYX
STZ _bcd+0
STZ _bcd+1
STZ _bcd+2

Dec2BCD
LDX #16 ; 16 bits
SED ; "Double Dabble"
_Dec2BCD ; https://en.wikipedia.org/wiki/Double_dabble
ASL _temp+0
ROL _temp+1

LDY #$FD ; $00-$FD=-3 bcd[0] bcd[1] bcd[2] bcd[3]
_DoubleDabble ; Y=FD Y=FE Y=FF Y=00
LDA _bcd-$FD,Y
ADC _bcd-$FD,Y
STA _bcd-$FD,Y
INY
BNE _DoubleDabble

DEX
BNE _Dec2BCD
CLD

DecWidth
LDY #3 ; default to 6 digits
BEQ _EvenBCD ; special case 0 -> only 2 digits
; otherwise have odd digits,
; Print low nibble, skip high nibble
_OddBCD ; Y = num digits/2 to print
LDA _bcd,Y ; __c??? _b_?XX a_YYXX
JSR HexA
JSR PutChar
DEY
_EvenBCD
LDA _bcd,Y ; __c??? _b_?XX a_YYXX
JSR PrintHexByte
DEY
BPL _EvenBCD
RTS

PrintHexByte
JSR HexA
LDA _temp+0
JSR PutChar
PrintHexBotNib
LDA _temp+1
JMP PutChar

; Converts A to Hex digits, stores two chars in _temp+0, _temp+1
; @return: A will be bottom nibble in ASCII
HexA
PHA
LSR
LSR
LSR
LSR
JSR _HexNib
STA _temp+0
PLA
_HexNib
AND #$F
CMP #$A ; n < 10 ?
BCC _Hex2Asc
ADC #6 ; n += 6 $A -> +6 + (C=1) = $11
_Hex2Asc
ADC #'0' + $80 ; inverse=remove #$80
STA _temp+1
RTS

PutChar
; STA $C0DE ; _pScreen NOTE: self-modifying!
; INC PutChar+1 ; inc lo
; RTS
JMP COUT

_bcd ds 6 ; 6 chars for printing dec
Michael 'AppleWin Debugger Dev'
2017-07-05 13:59:11 UTC
Permalink
Print Unsigned 16-bit Integer in 162 bytes.
Skips leading zero(s), always prints at least 1 digit.
Self-contained, no zero-page usage.
Uses no ROM calls except for COUT.
Includes demo -- total size is 169 bytes.

Usage:
A,X = 16-bit integer
A=high, X=low, same calling convention as Applesoft's LINPRT

0800:A9 12 A2 34 4C 07 08 8E
0808:A7 08 8D A8 08 A9 00 8D
0810:93 08 8D 9B 08 8D 9C 08
0818:8D 9D 08 A2 10 F8 0E A7
0820:08 2E A8 08 A0 FD B9 9E
0828:07 79 9E 07 99 9E 07 C8
0830:D0 F4 CA D0 E9 D8 A0 03
0838:B9 9B 08 20 78 08 20 92
0840:08 88 B9 9B 08 20 69 08
0848:88 10 F7 A0 FF C8 CC 93
0850:08 F0 07 B9 A1 08 C9 B0
0858:F0 F3 B9 A1 08 20 ED FD
0860:C8 CC 93 08 F0 02 90 F2
0868:60 20 78 08 AD A7 08 20
0870:92 08 AD A8 08 4C 92 08
0878:48 4A 4A 4A 4A 20 84 08
0880:8D A7 08 68 29 0F C9 0A
0888:90 02 69 06 69 B0 8D A8
0890:08 60 A2 00 9D A1 08 EE
0898:93 08 60 00 00 00 00 00
08A0:00 00 00 00 00 00 00 00
08A8:00


- - - 8< print_int.s - - -

COUT = $FDED

ORG $800

LDA #$12
LDX #$34
JMP PrintUint

; Print unsigned 16-bit integer
; ======================================================================
PrintUint
STX _temp+0
STA _temp+1

PrintDecYX
LDA #0
STA _len ; output buffer len = num digits to print
STA _bcd+0
STA _bcd+1
STA _bcd+2

Dec2BCD
LDX #16 ; 16 bits
SED ; "Double Dabble"
_Dec2BCD ; https://en.wikipedia.org/wiki/Double_dabble
ASL _temp+0
ROL _temp+1

LDY #$FD ; $00-$FD=-3 bcd[0] bcd[1] bcd[2] bcd[3]
_DoubleDabble ; Y=FD Y=FE Y=FF Y=00
LDA _bcd-$FD,Y
ADC _bcd-$FD,Y
STA _bcd-$FD,Y
INY
BNE _DoubleDabble

DEX
BNE _Dec2BCD
CLD

DecWidth
LDY #3 ; 3*2 = 6 digit output
_OddBCD ; Y = num digits/2 to print
LDA _bcd,Y ; __c??? _b_?XX a_YYXX
JSR HexA
JSR PutChar
DEY
_EvenBCD
LDA _bcd,Y ; __c??? _b_?XX a_YYXX
JSR PrintHexByte
DEY
BPL _EvenBCD

PrintOutput
LDY #$FF
SkipLeadZero
INY
CPY _len
BEQ OutDigits
LDA _output,Y
CMP #'0' + $80 ; skip all leading zero's
BEQ SkipLeadZero

OutDigits
LDA _output,Y ; always print digit in "ones" place
JSR COUT
INY
CPY _len
BEQ _PrintDone
BCC OutDigits
_PrintDone
RTS

PrintHexByte
JSR HexA
LDA _temp+0
JSR PutChar
PrintHexBotNib
LDA _temp+1
JMP PutChar

; Converts A to Hex digits, stores two chars in _temp+0, _temp+1
; @return: A will be bottom nibble in ASCII
HexA
PHA
LSR
LSR
LSR
LSR
JSR _HexNib
STA _temp+0
PLA
_HexNib
AND #$F
CMP #$A ; n < 10 ?
BCC _Hex2Asc
ADC #6 ; n += 6 $A -> +6 + (C=1) = $11
_Hex2Asc
ADC #'0' + $80 ; inverse=remove #$80
STA _temp+1
RTS

PutChar
LDX #0
STA _output,X
INC _len
RTS

_bcd ds 6 ; 6 chars for printing dec
_len = PutChar+1
_output ds 6 ; 16-bit uint -> 5 chars
_temp db 0,0
qkumba
2017-07-05 17:31:59 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
JMP PutChar
...
PutChar
LDX #0
STA _output,X
INC _len
RTS
I suggest moving PutChar up, so that the JMP goes away.
Michael 'AppleWin Debugger Dev'
2017-07-05 17:50:28 UTC
Permalink
Hey Peter -- I was wondering when you were going to show up. :-)
Thanks for the optimization trick!
Smaller and faster is always appreciated -- even if it only 3 bytes.
Down to 159 bytes ($9F) now.

0800:A9 12 A2 34 4C 07 08 8E
0808:A4 08 8D A5 08 A9 00 8D
0810:76 08 8D 98 08 8D 99 08
0818:8D 9A 08 A2 10 F8 0E A4
0820:08 2E A5 08 A0 FD B9 9B
0828:07 79 9B 07 99 9B 07 C8
0830:D0 F4 CA D0 E9 D8 A0 03
0838:B9 98 08 20 7E 08 20 75
0840:08 88 B9 98 08 20 69 08
0848:88 10 F7 A0 FF C8 CC 76
0850:08 F0 07 B9 9E 08 C9 B0
0858:F0 F3 B9 9E 08 20 ED FD
0860:C8 CC 76 08 F0 02 90 F2
0868:60 20 7E 08 AD A4 08 20
0870:75 08 AD A5 08 A2 00 9D
0878:9E 08 EE 76 08 60 48 4A
0880:4A 4A 4A 20 8A 08 8D A4
0888:08 68 29 0F C9 0A 90 02
0890:69 06 69 B0 8D A5 08 60
0898:00 00 00 00 00 00 00 00
08A0:00 00 00 00 00 00

--- print_uint.s ---

COUT = $FDED

ORG $800

LDA #$12
LDX #$34
JMP PrintUint

; Print unsigned 16-bit integer
; ======================================================================
PrintUint
STX _temp+0
STA _temp+1

PrintDecYX
LDA #0
STA _len ; output buffer len = num digits to print
STA _bcd+0
STA _bcd+1
STA _bcd+2

Dec2BCD
LDX #16 ; 16 bits
SED ; "Double Dabble"
_Dec2BCD ; https://en.wikipedia.org/wiki/Double_dabble
ASL _temp+0
ROL _temp+1

LDY #$FD ; $00-$FD=-3 bcd[0] bcd[1] bcd[2] bcd[3]
_DoubleDabble ; Y=FD Y=FE Y=FF Y=00
LDA _bcd-$FD,Y
ADC _bcd-$FD,Y
STA _bcd-$FD,Y
INY
BNE _DoubleDabble

DEX
BNE _Dec2BCD
CLD

DecWidth
LDY #3 ; 3*2 = 6 digit output
_OddBCD ; Y = num digits/2 to print
LDA _bcd,Y ; __c??? _b_?XX a_YYXX
JSR HexA
JSR PutChar
DEY
_EvenBCD
LDA _bcd,Y ; __c??? _b_?XX a_YYXX
JSR PrintHexByte
DEY
BPL _EvenBCD

PrintOutput
LDY #$FF
SkipLeadZero
INY
CPY _len
BEQ OutDigits
LDA _output,Y
CMP #'0' + $80 ; skip all leading zero's
BEQ SkipLeadZero

OutDigits
LDA _output,Y ; always print digit in "ones" place
JSR COUT
INY
CPY _len
BEQ _PrintDone
BCC OutDigits
_PrintDone
RTS

PrintHexByte
JSR HexA
LDA _temp+0
JSR PutChar
PrintHexBotNib
LDA _temp+1
PutChar
LDX #0
STA _output,X
INC _len
RTS

; Converts A to Hex digits, stores two chars in _temp+0, _temp+1
; @return: A will be bottom nibble in ASCII
HexA
PHA
LSR
LSR
LSR
LSR
JSR _HexNib
STA _temp+0
PLA
_HexNib
AND #$F
CMP #$A ; n < 10 ?
BCC _Hex2Asc
ADC #6 ; n += 6 $A -> +6 + (C=1) = $11
_Hex2Asc
ADC #'0' + $80 ; inverse=remove #$80
STA _temp+1
RTS

_bcd ds 6 ; 6 chars for printing dec
_len = PutChar+1
_output ds 6 ; 16-bit uint -> 5 chars
_temp db 0,0
qkumba
2017-07-05 20:31:21 UTC
Permalink
Hi Michael,
Post by Michael 'AppleWin Debugger Dev'
Hey Peter -- I was wondering when you were going to show up. :-)
:-)
Post by Michael 'AppleWin Debugger Dev'
Thanks for the optimization trick!
Smaller and faster is always appreciated -- even if it only 3 bytes.
Then perhaps a bit smaller.
Post by Michael 'AppleWin Debugger Dev'
PrintOutput
LDY #$FF
can be removed - Y is already #$FF at this time.
Post by Michael 'AppleWin Debugger Dev'
BEQ _PrintDone
BCC OutDigits
I think that the BEQ can be removed. Carry set covers >=.

It's not clear to me why the _oddBCD block exists. The code seems to behave properly without it. If it were removed, then HexA could fall into PutChar since they are paired, and then you wouldn't need to store anything at _temp. That's a big saving.
Post by Michael 'AppleWin Debugger Dev'
HexA
...
LSR
LSR
LSR
LSR
can "JSR SCRN2+2" here, if you like.

To be a bit faster, the PHA/PLA in HexA could be TAX/TXA.
Michael 'AppleWin Debugger Dev'
2017-07-05 23:48:12 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
PrintOutput
LDY #$FF
can be removed - Y is already #$FF at this time.
Indeed. Good eye!
Post by Michael 'AppleWin Debugger Dev'
It's not clear to me why the _oddBCD block exists.
That is left-over code from printm() where variable width printing of 2-digit, 3-digit, or 5-digit output. That code always printed leading zeroes; the new code skips leading zeros. However, it is still needed for when the input is $0000. :-/ Rethinking this though, if we take your suggestion ...
Post by Michael 'AppleWin Debugger Dev'
If it were removed, then HexA could fall into PutChar since they are paired, and then you wouldn't need to store anything at _temp. That's a big saving.
... then yes, _oddBCD can now be removed! As you point out PutChar can be merged into HexA since _temp isn't used at this point.
Post by Michael 'AppleWin Debugger Dev'
To be a bit faster, the PHA/PLA in HexA could be TAX/TXA.
Excellent suggestion -- but with PutChar merged into HexA we need X for the output string length. :-( Pity.
Post by Michael 'AppleWin Debugger Dev'
JSR SCRN2+2
I had actually debated that entry point @ $F879 last year.
Since COUT is being used I guess we can use it.
However, we need to double check that exists on all the Apple 2 and clones ...

[x] Apple ][
[x] Apple //e
[x] Apple //c
[-] Laser 128 --- ARGH! WTF! For some reason the AND #$0F is missing. Well that's a bummer. Would have been a nice savings too.

Also _bcd over-allocates space, we don't need all 6 bytes, only 4.

With your suggestions and more optimizations this brings the size down to ... $883 - $807 = $7C.
Not bad for 124 bytes!

0800:A9 12 A2 34 4C 07 08 8E
0808:81 08 8D 82 08 A9 00 8D
0810:6F 08 8D 77 08 8D 78 08
0818:8D 79 08 A2 10 F8 0E 81
0820:08 2E 82 08 A0 FD B9 7A
0828:07 79 7A 07 99 7A 07 C8
0830:D0 F4 CA D0 E9 D8 A0 03
0838:B9 77 08 20 5B 08 88 10
0840:F7 C8 CC 6F 08 F0 07 B9
0848:7B 08 C9 B0 F0 F3 B9 7B
0850:08 20 ED FD C8 CC 6F 08
0858:90 F4 60 48 4A 4A 4A 4A
0860:20 64 08 68 29 0F C9 0A
0868:90 02 69 06 69 B0 A2 00
0870:9D 7B 08 EE 6F 08 60 00
0878:00 00 00 00 00 00 00 00
0880:00 00 00

Source is up on GitHub
https://github.com/Michaelangel007/apple2_print_uint16
qkumba
2017-07-06 01:19:08 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
Post by qkumba
JSR SCRN2+2
Since COUT is being used I guess we can use it.
However, we need to double check that exists on all the Apple 2 and clones ...
[x] Apple ][
[x] Apple //e
[x] Apple //c
[-] Laser 128 --- ARGH! WTF! For some reason the AND #$0F is missing. Well that's a bummer. Would have been a nice savings too.
After four LSRs, you don't need the AND. It can't be anything but #$00-#$0F.
The existing AND #$0F in your code can move next to the PLA where it belongs.
qkumba
2017-07-06 01:32:04 UTC
Permalink
You also don't need the self-modifying _len thing. Remove the LDX #0 (it's already zero on exit from DoubleDabble), and then just INX after storing A. After the BCD2Chars loop, STX to either of the places where _len is still referenced so that you have an immediate compare instead.
qkumba
2017-07-06 01:35:53 UTC
Permalink
Aaand it looks like your leading-zero check could go away if HexA detected the leading zero case and just didn't store anything at all...
i.e. if _HexNib detected A=0 and X=0 and then just returned.
Michael 'AppleWin Debugger Dev'
2017-07-06 02:38:32 UTC
Permalink
First attempt didn't save any bytes. :-/
Second attempt -- just barely able to save 2 bytes. :-)
Down to 117 bytes now.

i.e.
0800:A9 12 A2 34 4C 07 08 8E
0808:7A 08 8D 7B 08 A9 00 8D
0810:70 08 8D 71 08 8D 72 08
0818:A2 10 F8 0E 7A 08 2E 7B
0820:08 A0 FD B9 73 07 79 73
0828:07 99 73 07 C8 D0 F4 CA
0830:D0 E9 D8 A0 04 A9 B0 8D
0838:74 08 B9 6F 08 20 53 08
0840:88 D0 F7 8E 70 08 B9 74
0848:08 20 ED FD C8 CC 70 08
0850:90 F4 60 48 20 7B F8 20
0858:5D 08 68 29 0F D0 04 E0
0860:00 F0 0C C9 0A 90 02 69
0868:06 69 B0 9D 74 08 E8 60
0870:00 00 00 00 00 00 00 00
0878:00 00 00 00
Michael 'AppleWin Debugger Dev'
2017-07-06 03:29:18 UTC
Permalink
Mwahahaha, optimized down to 96 ($60) bytes!

_output is completely redundant since we can print the digits as they become available.

0800:A9 12 A2 34 4C 07 08 8E
0808:65 08 8D 66 08 A9 00 8D
0810:61 08 8D 62 08 8D 63 08
0818:A2 10 F8 0E 65 08 2E 66
0820:08 A0 FD B9 64 07 79 64
0828:07 99 64 07 C8 D0 F4 CA
0830:D0 E9 D8 A0 03 B9 60 08
0838:20 44 08 88 D0 F7 8A E0
0840:00 F0 11 60 48 20 7B F8
0848:20 4E 08 68 29 0F D0 04
0850:E0 00 F0 0C C9 0A 90 02
0858:69 06 69 B0 20 ED FD E8
0860:60 00 00 00 00 00 00

Source & Binary updated on GitHub.
qkumba
2017-07-06 04:25:22 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
Mwahahaha, optimized down to 96 ($60) bytes!
Wow, but not done yet!
CPX #$00 goes away, the TXA takes care of it, and the branch should be to _Hex2Asc instead.
qkumba
2017-07-06 04:29:47 UTC
Permalink
And preincrement X, to enable JMP COUT (the BEQ _HexAsciiDone becomes BEQ _PrintDone).
qkumba
2017-07-06 04:37:47 UTC
Permalink
And finally(?), rol/pha/pla instead of sta _temp+1/rol _temp+1 (after switching the init from LDA #0/STA to LDX #0/STX).
Michael 'AppleWin Debugger Dev'
2017-07-06 06:14:35 UTC
Permalink
Ah, took me a minute or two to see what you were getting at, but yes, we can cache the high-byte in A. Nice!

Down to 91 bytes!

0800:A9 12 A2 34 4C 07 08 8E
0808:61 08 48 A2 00 8E 5D 08
0810:8E 5E 08 8E 5F 08 A2 10
0818:F8 0E 61 08 68 2A 48 A0
0820:FD B9 60 07 79 60 07 99
0828:60 07 C8 D0 F4 CA D0 E9
0830:68 D8 A0 03 B9 5C 08 20
0838:41 08 88 D0 F7 8A F0 11
0840:60 48 20 7B F8 20 4B 08
0848:68 29 0F D0 04 E0 00 F0
0850:EF C9 0A 90 02 69 06 69
0858:B0 E8 4C ED FD 00 00 00
0860:00 00

Considering the original version I posted was 162 bytes that's a WHOPPING 71 bytes saved. That is 56% of the original size!

Thanks for all the great ideas! I'm not sure if we're going to be able to squeeze any more bytes out.

If we wanted to make this 65C02 only we could obviously replace

LDX #0
STX _bcd+0
STX _bcd+1
STX _bcd+2

With STZ _bcd+0, etc. to save 2 more bytes, but I'm gonna keep it generic 6502 for portability.

There is probably a quote by Michael Abrash or someone along these lines:

"Most optimizations is an exercise in caching"

This has been a total blast optimizing this. Thanks for all the feedback!
g***@sasktel.net
2017-07-06 11:31:37 UTC
Permalink
Michael, Are you into using zero page at all? Does this work for you.

CHANGE:

PrintUint
STX _temp+0
STA _temp+1

PrintDecYX
LDA #0
STA _len ; output buffer len = num digits to print
STA _bcd+0
STA _bcd+1
STA _bcd+2

Dec2BCD
LDX #16 ; 16 bits
SED ; "Double Dabble"
_Dec2BCD ; https://en.wikipedia.org/wiki/Double_dabble
ASL _temp+0
ROL _temp+1

LDY #$FD ; $00-$FD=-3 bcd[0] bcd[1] bcd[2] bcd[3]
_DoubleDabble ; Y=FD Y=FE Y=FF Y=00
LDA _bcd-$FD,Y
ADC _bcd-$FD,Y
STA _bcd-$FD,Y
INY
BNE _DoubleDabble

DEX
BNE _Dec2BCD


TO:

PrintUint
STX $FE
STA $FF

PrintDecYX
LDA #0
STA _len ; output buffer len = num digits to print
STA $FB
STA $FC
STA $FD

Dec2BCD
LDY #16 ; 16 bits
SED ; "Double Dabble"
_Dec2BCD ; https://en.wikipedia.org/wiki/Double_dabble
ASL $FE
ROL $FF

LDX #$FD ; $00-$FD=-3 bcd[0] bcd[1] bcd[2] bcd[3]
_DoubleDabble ; Y=FD Y=FE Y=FF Y=00
LDA $FE,X ; USES $FB, FC, FD
ADC $FE,X
STA $FE,X
INX
BNE _DoubleDabble

DEY
BNE _Dec2BCD


Saves 12 bytes and the X&Y registers are still zero when used with the Print Output.
Michael 'AppleWin Debugger Dev'
2017-07-06 15:03:04 UTC
Permalink
Hey Rob

Last nigh after having implemented all of Peter's optimizations I was considering what else for optimizations that could be done. The low hanging fruit would be to move all the vars to the zero page. But given how precious / over-used / etc. the zero page is I was trying to keep the program 100% "self contained" so I decided against that. BUT you bring up a really good point! Queue /Oblg. "Why not both!" meme --> Loading Image...

GitHub has been updated -- TWO versions are now available!

- one without any zero page usage (90 bytes)
- one with zero page vars (78 bytes)

Thanks for the suggestion of swapping X and Y around for the DoubleDabble. I see there is no ZP,Y addressing mode -- only ZP,X -- nice call there!


Sans Zero-Page
0800:A9 12 A2 34 4C 07 08 8E
0808:60 08 48 A2 00 8E 5D 08
0810:8E 5E 08 8E 5F 08 A2 10
0818:F8 0E 60 08 68 2A 48 A0
0820:FD B9 60 07 79 60 07 99
0828:60 07 C8 D0 F4 CA D0 E9
0830:68 D8 A0 03 B9 5C 08 20
0838:41 08 88 D0 F7 8A F0 11
0840:60 48 20 7B F8 20 4B 08
0848:68 29 0F D0 04 E0 00 F0
0850:EF C9 0A 90 02 69 06 69
0858:B0 E8 4C ED FD 00 00 00
0860:00

With Zero-Page
0900:A9 12 A2 34 4C 07 09 86
0908:FC 48 A0 00 84 FD 84 FE
0910:84 FF A0 10 F8 06 FC 68
0918:2A 48 A2 FD B5 00 75 00
0920:95 00 E8 D0 F7 88 D0 ED
0928:68 D8 A0 03 B9 FC 00 20
0930:39 09 88 D0 F7 8A F0 11
0938:60 48 20 7B F8 20 43 09
0940:68 29 0F D0 04 E0 00 F0
0948:EF C9 0A 90 02 69 06 69
0950:B0 E8 4C ED FD

That way people can decide which one is more appropriate for their needs instead of me since they _know_ whereas I can only presume.

How would you like to be credited? With Rob or with gid? I've used gid but let me know if you want that changed.

Thanks again for everyone's "code golf" ideas!

Michael
g***@sasktel.net
2017-07-06 17:55:19 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
How would you like to be credited? With Rob or with gid? I've used gid but let me know if you want that changed.
Michael
You don't have to mention my name. Just call me that hick boy from Saskatchewan. But if you want, use Gids, which is short for my last name Giddings.
Michael 'AppleWin Debugger Dev'
2017-07-06 19:46:46 UTC
Permalink
Post by g***@sasktel.net
Post by Michael 'AppleWin Debugger Dev'
How would you like to be credited? With Rob or with gid? I've used gid but let me know if you want that changed.
Michael
You don't have to mention my name. Just call me that hick boy from Saskatchewan. But if you want, use Gids, which is short for my last name Giddings.
Readme and code updated.

Canadian, eh? :-)

Fellow prairie boy here as well. Asquith FTW :-) Well, last millennium.
qkumba
2017-07-06 17:01:03 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
Thanks for all the great ideas! I'm not sure if we're going to be able to squeeze any more bytes out.
Then let me suggest one more - the PHA/PLA is required only around the 'Y' part of the _DoubleDabble loop.

I wonder if pushing to the stack and using X as index would help at all? Then you wouldn't need the _bcd array...
Michael 'AppleWin Debugger Dev'
2017-07-06 17:25:50 UTC
Permalink
Post by qkumba
Then let me suggest one more - the PHA/PLA is required only around the 'Y' part of the _DoubleDabble loop.
I wonder if pushing to the stack and using X as index would help at all? Then you wouldn't need the _bcd array...
Interesting idea! Are you thinking something along these 65C02 lines ... ?

PrintUint16
STX _temp
PHA ; Optimized: STA _temp+1

LDX #0
PHX
PHX
PHX

:

TSX
_DoubleDabble ; Y=FD Y=FE Y=FF Y=00

LDA $FF,X ; ZP,X
ADC $FF,X
STA $FF,X
qkumba
2017-07-06 18:40:55 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
Interesting idea! Are you thinking something along these 65C02 lines ... ?
PrintUint16
STX _temp
PHA ; Optimized: STA _temp+1
LDX #0
PHX
PHX
PHX
TSX
_DoubleDabble ; Y=FD Y=FE Y=FF Y=00
LDA $FF,X ; ZP,X
ADC $FF,X
STA $FF,X
Yes, something like that, but you can't use the "ZP,X" access because it won't extend into the stack page, so it might not save anything.
Michael 'AppleWin Debugger Dev'
2017-07-06 19:34:54 UTC
Permalink
Post by qkumba
Yes, something like that, but you can't use the "ZP,X" access because it won't extend into the stack page, so it might not save anything.
Yeah, we lose the ZP,X and are forced to use a 16-bit,X addressing mode. :-/
Plus the over-head of having to manage the stack means we don't win here.
Maybe you can edge out a few more bytes? :-)

0900:A9 12 A2 34 4C 07 09 A0
0908:00 48 DA 5A 5A 5A A0 10
0910:F8 BA 8E 30 09 1E 04 01
0918:3E 05 01 20 3C 09 20 3C
0920:09 20 3C 09 88 D0 EA D8
0928:BD 00 01 20 47 09 CA E0
0930:00 D0 F5 8A 69 04 AA 9A
0938:98 F0 1C 60 BD 01 01 7D
0940:01 01 9D 01 01 E8 60 48
0948:20 7B F8 20 51 09 68 29
0950:0F D0 04 C0 00 F0 E4 C9
0958:0A 90 02 69 06 69 B0 C8
0960:4C ED FD

- - - 8< print_uint16_sp.s - - -

; Michael Pohoreski
; https://github.com/Michaelangel007/apple2_print_uint16
; Optimized from printm
; Thanks to qkumba for optimizations
; Thanks to gid for nudging a zero-page version

; F8 ROM Entry Points
COUT = $FDED
SCRN2 = $F879

; Zero-Page Version - 4 locations used
;_temp = $fc
;bcd = $fd ; NOTE: MUST be at $FD for ZP,X addressing in _DoubleDabble

ORG $900 ; Intentionally different from sans-zero-page version for testing both

LDA #$12
LDX #$34
JMP PrintUint16

; Print unsigned 16-bit integer
; A=High byte
; X=Low byte
; Also see: Applesoft LINPRT @ ED24
; ======================================================================
PrintUint16
LDY #0 ; S=F3
PHA ; S+5 = _temp+1 = $105,X S=F1
PHX ; S+4 = _temp+0 = $104,X S=F2
PHY ; S+3 = _bcd[2] = $103,X S=F0
PHY ; S+2 = _bcd[1] = $102,X S=EF
PHY ; S+1 = _bcd[0] = $101,X S=EE

Dec2BCD
LDY #16 ; 16 bits
SED ; "Double Dabble"
_Dec2BCD ; https://en.wikipedia.org/wiki/Double_dabble
TSX ; X=EE
STX _BCDbegin+1 ; *** SELF-MODIFYING

; ASL _temp+0 ; abcd efgh | ijkl mnop |
; ROL _temp+1 ; C=a bcde fghi | jklm nop0 |
; ; Bit 7654_3210 | 7654_3210 |
ASL $104,X ; _temp+0
ROL $105,X ; _temp+1

; LDX #$FD ; $00-$FD=-3 bcd[0] bcd[1] bcd[2] bcd[3]
_DoubleDabble ; Y=FD Y=FE Y=FF Y=00
JSR Dabble ; X=EF
JSR Dabble ; X=F0
JSR Dabble ; X=F1
DEY
BNE _Dec2BCD

CLD ; Y=0 = output length

BCD2Chars
LDA $100,X ; X=F1, 1F1 -> bcd[2]
JSR HexA ; print 0, 1, or 2 hex digits
DEX
_BCDbegin
CPX #00 ; *** SELF-MODIFIED X == EE ?
BNE BCD2Chars

; Safe to restore stack now since we are done with vars
TXA
ADC #$04 ; C=1 from CPX #EE
TAX
TXS

TYA ; Handle special case input = $0000 of no output
BEQ _HaveLeadingDigit
_PrintDone
RTS
Dabble
LDA $101,X ; bcd,X
ADC $101,X
STA $101,X
INX
RTS

; Converts A to high ASCII digits, prints as they become available
; @return: A will be bottom nibble in high ASCII
HexA
PHA
JSR SCRN2+2 ; LSR x4 == 0>> 4
JSR _HexNib
PLA
AND #$F
_HexNib
BNE _HaveLeadingDigit ; If have leading zero and no output yet ...
CPY #0 ; ... then skip storing it
BEQ _PrintDone

_HaveLeadingDigit
CMP #$A ; n < 10 ?
BCC _Hex2Asc
ADC #6 ; n += 6 $A -> +6 + (C=1) = $11
_Hex2Asc
ADC #'0' + $80 ; inverse=remove #$80
PutChar
INY ; Y = output string length
JMP COUT
qkumba
2017-07-06 21:11:18 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
Yeah, we lose the ZP,X and are forced to use a 16-bit,X addressing mode. :-/
Plus the over-head of having to manage the stack means we don't win here.
Maybe you can edge out a few more bytes? :-)
I'll think about it.
In the meantime, the pha/pla in the non-zp version can be fixed for -2 bytes.
qkumba
2017-07-06 21:37:34 UTC
Permalink
and how about this:

_HexNib
BNE _HaveLeadingDigit ; If have leading zero and no output yet ...
DEX ; ... then skip storing it

_HaveLeadingDigit
INX ; X = flag to specify non-zero was seen
BEQ _PrintDone
Michael 'AppleWin Debugger Dev'
2017-07-06 22:10:09 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
_HexNib
BNE _HaveLeadingDigit ; If have leading zero and no output yet ...
DEX ; ... then skip storing it
_HaveLeadingDigit
INX ; X = flag to specify non-zero was seen
BEQ _PrintDone
Nice trick of removing the Compare == Zero by piggy-backing onto the INX. :-)
Updated all 3 versions on GitHub.

Current stats:
* sans-zero-page 89 bytes
* with-zero-page 77 bytes
* with stack page 91 bytes
qkumba
2017-07-06 22:26:52 UTC
Permalink
The pha/pla thing, from this:

STX _temp
PHA ; Optimized: STA _temp+1
...
_Dec2BCD
...
PLA
ROL
PHA

LDY #$FD ; $00-$FD=-3 bcd[0] bcd[1] bcd[2] bcd[3]
_DoubleDabble ; Y=FD Y=FE Y=FF Y=00
...
DEX
BNE _Dec2BCD

PLA ; keep stack

to this:

STX _temp
...
_Dec2BCD
ROL

LDY #$FD ; $00-$FD=-3 bcd[0] bcd[1] bcd[2] bcd[3]
PHA
_DoubleDabble ; Y=FD Y=FE Y=FF Y=00
...
PLA ; keep stack
DEX
BNE _Dec2BCD
qkumba
2017-07-06 22:31:55 UTC
Permalink
zpage version can do this:

LDX #0
LDY #$FD
_InitBCD
STX _bcd-$FD,Y
INY
BNE _InitBCD
Michael 'AppleWin Debugger Dev'
2017-07-06 23:06:52 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
LDX #0
LDY #$FD
_InitBCD
STX _bcd-$FD,Y
INY
BNE _InitBCD
Am I missing something? Not sure how those 9 bytes are better then these 8?

LDY #0
STY _bcd+0
STY _bcd+1
STY _bcd+2

We need X=-3, and Y=16 for the start of the DoubleDabble loop ...
Harry Potter
2017-07-06 23:22:20 UTC
Permalink
Uhh...Michael: I was wrong about the last message: I wasn't taking into account the optimizations the people here have made to your code. You said your code is online? Where can I find it? :)
Michael 'AppleWin Debugger Dev'
2017-07-06 23:26:06 UTC
Permalink
Post by Harry Potter
Uhh...Michael: I was wrong about the last message: I wasn't taking into account the optimizations the people here have made to your code. You said your code is online? Where can I find it? :)
https://github.com/Michaelangel007/apple2_print_uint16
Harry Potter
2017-07-07 12:10:14 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
Post by Harry Potter
Uhh...Michael: I was wrong about the last message: I wasn't taking into account the optimizations the people here have made to your code. You said your code is online? Where can I find it? :)
https://github.com/Michaelangel007/apple2_print_uint16
The reason I was doing so poorly is that I *kept* the cc65 divide routine in the code. I did this just in case I need the divide routine for a target program. I removed the reference, and I am getting great results. :)
Harry Potter
2017-07-07 12:18:58 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
https://github.com/Michaelangel007/apple2_print_uint16
I tried your code and got the Apple monitor at $FE14. :(
Michael 'AppleWin Debugger Dev'
2017-07-07 14:18:27 UTC
Permalink
Considering there are three versions _which_ one isn't working for you?
Have you tried the built in demo?
Which hardware, if any, are you on?
Which emulator, if any, are you using?

I've uploaded a demo.dsk -- does this work?

I've tested with AppleWin, Jace, and Virtual ][ without any issues.
Harry Potter
2017-07-07 14:34:32 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
Considering there are three versions _which_ one isn't working for you?
Have you tried the built in demo?
Which hardware, if any, are you on?
Which emulator, if any, are you using?
I'm using the top version of print_uint16_sans_zp.s.
Post by Michael 'AppleWin Debugger Dev'
I've uploaded a demo.dsk -- does this work?
I've tested with AppleWin, Jace, and Virtual ][ without any issues.
I'm using AppleWin and am compiling the program--the test program is in C--using cc65. The following is my version of your code:
---------------------------------
.include "zeropage.inc"
.import negax
;.import _printu

.export _printi

.import pushax, popax
.import tosudiva0
.import _prints, _printc
.export _printu

COUT = $FDED
;.bss
;_output: .res 6

_temp=tmp1
;_bcd=ptr1
.code
_printi:
cpx #0
bpl _printu
;pha
tay
lda #'-'
;jsr $ffd2
jsr _printc
;pla
tya
jsr negax
_printu:
; Michael Pohoreski
; https://github.com/Michaelangel007/apple2_print_uint16
; Optimized from printm
; Thanks to qkumba for optimizations
; Thanks to Gids for nudging a zero-page version

; F8 ROM Entry Points
PRHEXZ = $FDE5
SCRN2 = $F879

;ORG $800

;LDA #$12
;LDX #$34
;JMP PrintUint16

; Print unsigned 16-bit integer
; A=High byte
; X=Low byte
; Also see: Applesoft LINPRT @ ED24
; ======================================================================
PrintUint16:
STX _temp

LDX #0 ; Optional 65C02 version
STX _bcd+0 ; STZ _bcd+0
STX _bcd+1 ; STZ _bcd+1
STX _bcd+2 ; STZ _bcd+2

Dec2BCD:
LDX #16 ; 16 bits
SED ; "Double Dabble"
_Dec2BCD: ; https://en.wikipedia.org/wiki/Double_dabble
ASL _temp+0 ; abcd efgh | ijkl mnop |
ROL _temp+1 ; C=a bcde fghi | jklm nop0 |
; ; Bit 7654_3210 | 7654_3210 |
ROL
PHA ; Optimized: STA _temp+1

LDY #$FD ; $00-$FD=-3 bcd[0] bcd[1] bcd[2] bcd[3]
_DoubleDabble: ; Y=FD Y=FE Y=FF Y=00
LDA _bcd-$FD,Y
ADC _bcd-$FD,Y
STA _bcd-$FD,Y
INY
BNE _DoubleDabble
PLA
DEX
BNE _Dec2BCD

CLD ; X=0 = output length

DecWidth:
LDY #3 ; maximum 6 digits output
BCD2Chars:
LDA _bcd-1,Y
JSR HexA ; print 0, 1, or 2 hex digits
DEY
BNE BCD2Chars

TXA ; Handle special case input = $0000 of no output
BEQ _HaveLeadingDigit

_PrintDone:
RTS


; Converts A to high ASCII digits, prints as they become available
; @return: A will be bottom nibble in high ASCII
HexA:
PHA
JSR SCRN2+2 ; LSR x4 == 0>> 4
;jsr _printc
JSR _HexNib
PLA
AND #$F
_HexNib:
BNE _HaveLeadingDigit ; If have leading zero and no output yet ...
DEX ; ... then skip storing it

_HaveLeadingDigit:
INX ; X = flag to specify non-zero leading digit was seen
BEQ _PrintDone
JMP PRHEXZ

.bss

_bcd: .res 3 ; 6 chars for printing dec
;_temp: .res 0

.code
;jmp tosudiva0
---------------------------
Am I at fault here?
qkumba
2017-07-07 16:11:32 UTC
Permalink
Post by Harry Potter
_Dec2BCD: ; https://en.wikipedia.org/wiki/Double_dabble
ASL _temp+0 ; abcd efgh | ijkl mnop |
ROL _temp+1 ; C=a bcde fghi | jklm nop0 |
; ; Bit 7654_3210 | 7654_3210 |
ROL
PHA ; Optimized: STA _temp+1
This is a combination of a previous version and the current version.
Please fetch the current version from Git and replace what you have.
Post by Harry Potter
I've uploaded a demo.dsk -- does this work?
Michael 'AppleWin Debugger Dev'
2017-07-07 16:28:53 UTC
Permalink
Post by Harry Potter
I'm using AppleWin and am compiling the program--the test program is in C--using cc65.
Am I at fault here?
Yes, you have an integration bug considering the program works across multiple emulators.

Do you have a binary and/or hexdump of your program so I can debug it?


Also, you don't need to manually include my source. I would simplify your cc65 assembly source to:

.feature labels_without_colons
.include "print_uint16_sans_zp.s"

That way you don't have to keep adding colons to the labels in print_uint16_sans_zp.s.

Of course you will need to comment out the corresponding ORG and TEST code in your local copy of print_uint16_sans_zp.s
Harry Potter
2017-07-07 22:46:06 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
Yes, you have an integration bug considering the program works across multiple emulators.
Sorry, but what _exactly_ am I doing wrong?
Post by Michael 'AppleWin Debugger Dev'
Do you have a binary and/or hexdump of your program so I can debug it?
I can give you the binary file and/or the full source. It is my Apple2SimpleIO library. My e-mail is rose(dot)joseph12(at)yahoo(dot)com.
E-mail me for a copy. :)
Post by Michael 'AppleWin Debugger Dev'
.feature labels_without_colons
.include "print_uint16_sans_zp.s"
That way you don't have to keep adding colons to the labels in print_uint16_sans_zp.s.
Of course you will need to comment out the corresponding ORG and TEST code in your local copy of print_uint16_sans_zp.s
I have it my way because I am developing a *library*; others need to use it, and I need a certain name for the function.
Michael 'AppleWin Debugger Dev'
2017-07-08 00:05:21 UTC
Permalink
Post by Harry Potter
Post by Michael 'AppleWin Debugger Dev'
Yes, you have an integration bug considering the program works across multiple emulators.
Sorry, but what _exactly_ am I doing wrong?
That's what _you_ need to spend time debugging.

FIRST, are you able to run the demo.dsk provided on GitHub ?

ONCE you have verified that works that we can proceed to troubleshoot the next step.
Post by Harry Potter
Post by Michael 'AppleWin Debugger Dev'
Do you have a binary and/or hexdump of your program so I can debug it?
I can give you the binary file and/or the full source. It is my Apple2SimpleIO library. My e-mail is rose(dot)joseph12(at)yahoo(dot)com.
E-mail me for a copy. :)
Email sent.
Post by Harry Potter
Post by Michael 'AppleWin Debugger Dev'
.feature labels_without_colons
.include "print_uint16_sans_zp.s"
That way you don't have to keep adding colons to the labels in print_uint16_sans_zp.s.
Of course you will need to comment out the corresponding ORG and TEST code in your local copy of print_uint16_sans_zp.s
I have it my way because I am developing a *library*; others need to use it, and I need a certain name for the function.
You are making it WAY harder then it needs to be. Export the name THEN include the source.

Just for your convenience I've split the demo functionality from the PrintUint16 code so that:

1) It assembles with either Merlin32 or cc65, and
2) You can include it into other projects. You shouldn't have to change a thing now in "print_uint16_sans_zp.s".

Please fetch the latest versions from GitHub.

SECOND, are you able to build `demo_cc65.s` with cc65?

- - - 8< file: demo_cc65.s - - -

.feature labels_without_colons
.export _printu

.org $800

LDA #$12
LDX #$34
JMP _printu

_printu
.include "print_uint16_sans_zp.s"
James Davis
2017-07-08 07:49:50 UTC
Permalink
... My e-mail is rose(dot)joseph12(at)yahoo(dot)com. ...
Hi Rose (AKA: Harry Potter),

Are you 12?! You should not reveal your email address to the universe as you just did. You are now vulnerable to junk mail, spam, and identity theft! You should throw that one away immediately. In future, communicate your email address (write) privately to the one person you are attempting to contact.

Sincerely,

James Davis
Harry Potter
2017-07-08 11:34:57 UTC
Permalink
Post by James Davis
Are you 12?! You should not reveal your email address to the universe as you just did. You are now vulnerable to junk mail, spam, and identity theft! You should throw that one away immediately. In future, communicate your email address (write) privately to the one person you are attempting to contact.
Sincerely,
James Davis
You're right. I'm sorry. :(
Michael 'AppleWin Debugger Dev'
2017-07-09 03:30:01 UTC
Permalink
Post by Harry Potter
Post by Michael 'AppleWin Debugger Dev'
Yes, you have an integration bug considering the program works across multiple emulators.
Sorry, but what _exactly_ am I doing wrong?
What YOU are doing wrong is:

[x] not running the provided demo.dsk and letting us know if it works,
[x] not writing a SMALL test case and VERIFYING that it works,
[x] not using a debugger and TRACING this YOURSELF,
[x] not telling us WHICH version of ProDOS you are using,
[x] not providing a DSK which we can boot to 100% replicate your environment,
[x] expecting other people to debug your program while not providing relevant information,
[x] keep asking trivial questions without doing any of the "groundwork" yourself, and finally
[x] In your simple.system leaving the Language Card Bank 2 active and trying to call ROM routines. Namely:

a) @ $21DF calling SCRN2+2 = $F87B

Which, on ProDOS 2.4.1 has

LC02/F87B:40 RTI

instead of the ROM expected code of LSR x4. This then causes a crash into never-never land. Depending on which version of ProDOS you have loaded will crash to different location(s),

b) @ $21EE calling PRHEXZ = $FDE5

Which would ALSO crash but it never gets here due to crashing at $21DF first.


If you want to fix this then you need to insert 3 instructions into your source:

i) 2x, BEFORE you call PrintU16 to disable LC Bank2 and re-enable ROM
STA $C081
STA $C081

ii) 2x, AFTER you call PrintU16 to re-enable LC Bank2 and disable ROM
STA $C080
STA $C080

Harry, we have been MORE then patient with you but if you refuse to help yourself you will eventually come to find that no one wants to help you.

Stop expecting other people to do your work for you.

If you don't know HOW to start to Troubleshoot then ASK.
barrym95838
2017-07-09 04:58:40 UTC
Permalink
https://tenor.com/view/neil-degrasse-tyson-mic-drop-gif-5236150
Michael 'AppleWin Debugger Dev'
2017-07-09 05:23:33 UTC
Permalink
LOL Mike. :-)

Wait till you see my next post where I provide a binary patch. :-)

/oblg. SNL's Nick Burns "Uh, You're Welcome"
Loading Image...


Harry Potter
2017-07-09 13:00:20 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
[x] not running the provided demo.dsk and letting us know if it works,
I just did. It didn't work: it's only 32k long. :(
Post by Michael 'AppleWin Debugger Dev'
[x] not writing a SMALL test case and VERIFYING that it works,
Well...it worked when I was using cc65's divide routine but not with your approach. :(
Post by Michael 'AppleWin Debugger Dev'
[x] not using a debugger and TRACING this YOURSELF,
You got me there. :)
Post by Michael 'AppleWin Debugger Dev'
[x] not telling us WHICH version of ProDOS you are using,
V. 2.0.3.
Post by Michael 'AppleWin Debugger Dev'
[x] not providing a DSK which we can boot to 100% replicate your environment,
I'll e-mail it to you now. :0
Post by Michael 'AppleWin Debugger Dev'
[x] expecting other people to debug your program while not providing relevant information,
I tried. What information do you need?
Post by Michael 'AppleWin Debugger Dev'
[x] keep asking trivial questions without doing any of the "groundwork" yourself, and finally
You're right. :(
Post by Michael 'AppleWin Debugger Dev'
[x] In your simple.system leaving the Language Card Bank 2 active and trying to call ROM routines.
I did elsewhere. (?)

BTW, I just got it to work. I removed the JMP PRHEXZ with a call to _printc, which prints a character to the screen and replaced the JSR SCRN2+2 with 4 lsr's. Then I had to switch .A and .X. Now it works! :) Thank you for your patience. :)
Michael 'AppleWin Debugger Dev'
2017-07-09 13:17:42 UTC
Permalink
Post by Harry Potter
Post by Michael 'AppleWin Debugger Dev'
[x] not running the provided demo.dsk and letting us know if it works,
I just did. It didn't work: it's only 32k long. :(
Then you downloaded it wrong.

1. Notice how it says ** 140KB **
https://github.com/Michaelangel007/apple2_print_uint16/blob/master/demo.dsk
2. Click on "View Raw" to download it.

Here is a direct download URL
https://github.com/Michaelangel007/apple2_print_uint16/blob/master/demo.dsk?raw=true
Michael 'AppleWin Debugger Dev'
2017-07-09 05:21:09 UTC
Permalink
And just to PROVE what you are doing wrong is accessing the LC instead of ROM:

CALL-151
BLOAD SIMPLE.SYSTEM
23EC:8d 81 c0 8d 81 c0 86 90 A2 00 20 aa 21 8d 80 c0 8d 80 c0 60
21A6:4C EC 23
BSAVE FIXED.SYSTEM,A$2000,L$400
BE00G
-FIXED.SYSTEM

And your program will now work.
qkumba
2017-07-07 00:01:59 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
Am I missing something? Not sure how those 9 bytes are better then these 8?
LDY #0
STY _bcd+0
STY _bcd+1
STY _bcd+2
We need X=-3, and Y=16 for the start of the DoubleDabble loop ...
Err, because clearly I can't count.
I was using non-zp sizes, where there would be a saving if only there were a sty,x.
qkumba
2017-07-07 00:10:17 UTC
Permalink
For zp version, temp doesn't have to be at $FD. A zp,x access will wrap around within the zpage if zp+x > $FF, so you can be anywhere in zpage.
Michael 'AppleWin Debugger Dev'
2017-07-07 00:15:07 UTC
Permalink
Post by qkumba
Post by Michael 'AppleWin Debugger Dev'
Am I missing something? Not sure how those 9 bytes are better then these 8?
LDY #0
STY _bcd+0
STY _bcd+1
STY _bcd+2
We need X=-3, and Y=16 for the start of the DoubleDabble loop ...
Err, because clearly I can't count.
I was using non-zp sizes, where there would be a saving if only there were a sty,x.
Whew! :-)
Michael 'AppleWin Debugger Dev'
2017-07-06 22:43:05 UTC
Permalink
AH, that makes perfect sense, now.
Non-zp version down to 79 bytes. :-)
Michael 'AppleWin Debugger Dev'
2017-07-06 22:29:51 UTC
Permalink
Post by qkumba
In the meantime, the pha/pla in the non-zp version can be fixed for -2 bytes.
I'm not sure how you are removing the pha/pla ...

but with your last DEX / INX / BNE relocation optimization I'll CALL you and RAISE you -8 bytes!

Down to 81 bytes now for non-zp, 69 bytes for zp, and 83 bytes for stack versions. :-)
Michael 'AppleWin Debugger Dev'
2017-07-06 05:30:07 UTC
Permalink
Ha! Just finished talking with a friend and taking another look at the code thought of that one too. :-)

Great minds think alike. :-)
Michael 'AppleWin Debugger Dev'
2017-07-06 05:33:22 UTC
Permalink
Post by qkumba
CPX #$00 goes away, the TXA takes care of it,
Right, that make sense. Another 2 bytes saved. :-)
Post by qkumba
and the branch should be to _Hex2Asc instead.
Hmm, I'm branching to _HaveLeadingDigit to force CMP -> C=0.
How do you reck'n we can guarantee C=0 by branching to _Hex2Asc ?

_HaveLeadingDigit
CMP #$A ; n < 10 ?
BCC _Hex2Asc
ADC #6 ; n += 6 $A -> +6 + (C=1) = $11
_Hex2Asc
ADC #'0' + $80 ; inverse=remove #$80
Michael 'AppleWin Debugger Dev'
2017-07-06 01:50:17 UTC
Permalink
Post by qkumba
You also don't need the self-modifying _len thing.
Remove the LDX #0 (it's already zero on exit from DoubleDabble),
Excellent find.
Post by qkumba
and then just INX after storing A. After the BCD2Chars loop, STX to either of the places where _len is still referenced so that you have an immediate compare instead.
That's a real nice saving. Can even reuse _bcd since it is no longer needed at this point.

Down to 119 ($77) bytes!
Michael 'AppleWin Debugger Dev'
2017-07-06 01:45:38 UTC
Permalink
Post by qkumba
After four LSRs, you don't need the AND. It can't be anything but #$00-#$0F.
Right, LSR is unsigned shift right. Good catch.
Post by qkumba
The existing AND #$0F in your code can move next to the PLA where it belongs.
Saves 2 cycles. Nice!
Harry Potter
2017-07-06 23:12:06 UTC
Permalink
Michael, I tried your code, and it *increased* the size of my code, which uses cc65's divide function to get each digit. :(
Michael 'AppleWin Debugger Dev'
2017-07-06 23:25:24 UTC
Permalink
Post by Harry Potter
Michael, I tried your code, and it *increased* the size of my code, which uses cc65's divide function to get each digit. :(
You are using it wrong then. You _don't_ need any DIGIT = MOD % BASE that is normally used in itoa().


i.e. For example, this 1-liner in Javascript:

var n = 0x1234, txt = ""; for( var i = 0; i < 5; i++ ) { txt += (n % 10); n /= 10; n = n|0; }; console.log( txt.split("").reverse().join("") );

Or in C

#include <stdio.h>
#include <stdint.h>

char* itoa( uint32_t n, int base )
{
const char set[] = "0123456789ABCDEF";
/* */ int length = 0;

#define MAX_DIGITS 32
static char output[ MAX_DIGITS+1 ]; // base 2 = max 32 binary digits + null

if (base < 2) base = 2;
if (base > 16) base = 16;

do
{
output[ length++ ] = set[ n % base ];
n /= base;
} while( n > 0 );

// String Reverse
output[ length ] = 0;
for( int i = 0; i < length/2; i++ )
{
char temp = output[ i ]; // t <- D
output[ i ] = output[length-i-1]; // D <- S
output[length-i-1] = temp; // t ------> S
}

return output;
}

int main()
{
return printf( "%s\n", itoa( 0x1234, 10 ) );
}


What's the context of the problem you are trying to solve ?
r***@gmail.com
2017-07-05 03:58:01 UTC
Permalink
Post by Harry Potter
The LINPRNT entry didn't work.
Worked fine for me. Is Applesoft working and the COUT vector set correctly?
Post by Harry Potter
if I can get the ROM to print numbers for me, then I would need a lot less code to perform the function.
Welcome to the world of 6502 hurt. I wrote a ProDOS name input routine and it's over a page (256 bytes) of code.
Delfs
2017-07-05 09:30:22 UTC
Permalink
Hello I recall this monitor entry point but I can't put my finger on it. It is used by the list command to display line numbers. Displays a 16 bit number as integer... maybe this mention will jog someone else's memory for the parameters and location of this rom routine.
Steve Nickolas
2017-07-05 10:00:01 UTC
Permalink
Post by Delfs
Hello I recall this monitor entry point but I can't put my finger on it.
It is used by the list command to display line numbers. Displays a 16
bit number as integer... maybe this mention will jog someone else's
memory for the parameters and location of this rom routine.
It's not a monitor call, but a function in FPBASIC: $ED24 LINPRT, "print
line number from XA"

-uso.
Harry Potter
2017-07-05 12:47:35 UTC
Permalink
Post by Steve Nickolas
It's not a monitor call, but a function in FPBASIC: $ED24 LINPRT, "print
line number from XA"
That's the address I have, but it doesn't work. Again, I'm using the default cc65 setups and am working on a substitute for the cc65 standard/console I/O functions, Apple2SimpleIO.
Michael 'AppleWin Debugger Dev'
2017-07-05 12:59:48 UTC
Permalink
This post might be inappropriate. Click to display it.
Joshua Bell
2020-12-23 20:06:05 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
LINPRT ... that's helluva lot of code just to print an unsigned 16-bit int.
The only good news is that it is built-into ROM.
LDA #$12
LDX #$34
JMP $ED24
4660
NOTE: Stack $100 .. $1104 is used as output buffer.
* $E000 Basic Cold Start or
* $E003 Basic Warm Start
must be called first.
To document for posterity:

I wanted to use LINPRNT without fully initializing Basic. Assuming at least ProDOS has started (i.e. you're in a SYS file), it appears you can get away with just the following:

SHIFT.SIGN.EXT set to 0; required by FP routines
TEMPPT set to TEMPST; it's a string descriptor pointer
SPEEDZ set to 1, for no output delay
FLASH.BIT set to 0, to get normal characters

Equates per http://www.txbobsc.com/scsc/scdocumentor/definitions.html
Harry Potter
2017-07-05 14:49:02 UTC
Permalink
Post by Harry Potter
Hi! I remember seeing recently an entry in the Apple 2 Monitor to print an integer to the screen but forgot where the routine is located and its name. What are the name and address of the routine, and does it print signed or unsigned integers?
Your code seems to be slightly smaller than mine and also much faster--no long division. Two questions:

1. May I use your code in my SimpleIO libraries?
2. Who should I say donated the code? ;)
Michael 'AppleWin Debugger Dev'
2017-07-05 14:57:40 UTC
Permalink
Post by Harry Potter
1. May I use your code in my SimpleIO libraries?
Sure.

The license is WTFPL.
http://www.wtfpl.net/
Post by Harry Potter
2. Who should I say donated the code? ;)
Michael Pohoreski

I _don't_ need public attribution but a comment in the code with a link to the original version, printm(), would be greatly appreciated.

i.e.
; Print unsigned 16-bit integer by Michael Pohoreski aka Michaelangel007 freely donated from his printm library
; https://github.com/Michaelangel007/apple2_printm


This maybe a dumb question but doesn't cc65 already provide a printf() ?
Why are you re-inventing the wheel?
Harry Potter
2017-07-05 15:19:49 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
This maybe a dumb question but doesn't cc65 already provide a printf() ?
Why are you re-inventing the wheel?
I *am* reinventing the wheel, but this wheel is designed to streamline code if only simple I/O, i.e. print text and numbers, is necessary. It could save about 2k if the full printf()/puts() functionality is not needed.

BTW, I already have a version of A2SimpleIO on-line at https://sourceforge.net/projects/cc65extra/files/ui/ . I am currently working on optimizing it now. Try it out! :)
David Schmenk
2017-07-05 16:44:36 UTC
Permalink
Post by Michael 'AppleWin Debugger Dev'
Post by Harry Potter
1. May I use your code in my SimpleIO libraries?
Sure.
The license is WTFPL.
http://www.wtfpl.net/
I've got a few projects for this licensing term. Thanks!
Denis Molony
2017-07-07 02:56:20 UTC
Permalink
I can't wait till you guys get it down to a single byte.
Michael 'AppleWin Debugger Dev'
2017-07-07 04:58:25 UTC
Permalink
Post by Denis Molony
I can't wait till you guys get it down to a single byte.
We're trying. =P

Joking aside, Peter has done an outstanding job of optimizing.

I'm very happy with the way it has turned out. I'm probably not going to focus on any more optimizations since I have other projects I need to work on but I'll be keeping an eye on them if any more crop up.
barrym95838
2017-07-08 05:11:21 UTC
Permalink
Post by Denis Molony
I can't wait till you guys get it down to a single byte.
Only 41 bytes to go, and I'm down to one byte! :-)

300:86 A0 85 A1 A9 00 48 A9 00 A2 10 C9 05 90 02 E9
310:05 26 A0 26 A1 2A CA D0 F2 09 B0 48 A5 A0 05 A1
320:D0 E5 68 20 ED FD 68 D0 FA 60

I decided to blaze my own trail. Source available on request.

Mike B.
awanderin
2017-07-08 06:39:26 UTC
Permalink
Post by barrym95838
Post by Denis Molony
I can't wait till you guys get it down to a single byte.
Only 41 bytes to go, and I'm down to one byte! :-)
300:86 A0 85 A1 A9 00 48 A9 00 A2 10 C9 05 90 02 E9
310:05 26 A0 26 A1 2A CA D0 F2 09 B0 48 A5 A0 05 A1
320:D0 E5 68 20 ED FD 68 D0 FA 60
I decided to blaze my own trail. Source available on request.
Mike B.
Very nice! Clever way to get rid of leading zeros: don't even generate
them. :)

--
Jerry awanderin at gmail dot com
Loading...