Discussion:
Apple Monitor: Print Integer?
(too old to reply)
Harry Potter
2017-07-01 18:39:25 UTC
Permalink
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
And preincrement X, to enable JMP COUT (the BEQ _HexAsciiDone becomes BEQ _PrintDone).
qkumba
2017-07-06 04:37:47 UTC
Permalink
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
... 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
Raw Message
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
Raw Message
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
Raw Message
https://tenor.com/view/neil-degrasse-tyson-mic-drop-gif-5236150
Michael 'AppleWin Debugger Dev'
2017-07-09 05:23:33 UTC
Permalink
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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.

Usage:

LDA #$12
LDX #$34
JMP $ED24

Output:
4660

NOTE: Stack $100 .. $1104 is used as output buffer.

Requires:

* $E000 Basic Cold Start or
* $E003 Basic Warm Start

must be called first.


Call Tree:
LINPRT
FLOAT.2
NORMALIZE.FAC.1
FOUT
STROUT
STRLIT
FREFAC
OUTDO

Partial disassembly ...
http://www.txbobsc.com/scsc/scdocumentor/ED0A.html
http://jamtronix.com/files/applesoft.html

1130 *--------------------------------
1140 * PRINT A,X AS DECIMAL INTEGER
1150 *--------------------------------
ED24- 85 9E 1160 LINPRT STA FAC+1 PRINT A,X IN DECIMAL
ED26- 86 9F 1170 STX FAC+2
ED28- A2 90 1180 LDX #$90 EXPONENT = 2^16
ED2A- 38 1190 SEC CONVERT UNSIGNED
ED2B- 20 A0 EB 1200 JSR FLOAT.2 CONVERT LINE # TO FP
1210 *--------------------------------
1220 * CONVERT (FAC) TO STRING, AND PRINT IT
1230 *--------------------------------
1240 PRINT.FAC
ED2E- 20 34 ED 1250 JSR FOUT CONVERT (FAC) TO STRING AT STACK
1260 *--------------------------------
1270 * PRINT STRING STARTING AT Y,A
1280 *--------------------------------
1290 GO.STROUT
ED31- 4C 3A DB 1300 JMP STROUT PRINT STRING AT A,Y

1310 *--------------------------------
1320 * CONVERT (FAC) TO STRING STARTING AT STACK
1330 * RETURN WITH (Y,A) POINTING AT STRING
1340 *--------------------------------
ED34- A0 01 1350 FOUT LDY #1 NORMAL ENTRY PUTS STRING AT STACK...
1360 *--------------------------------
1370 * "STR$" FUNCTION ENTERS HERE, WITH (Y)=0
1380 * SO THAT RESULT STRING STARTS AT STACK-1
1390 * (THIS IS USED AS A FLAG)
1400 *--------------------------------
ED36- A9 2D 1410 FOUT.1 LDA #'-' IN CASE VALUE NEGATIVE
ED38- 88 1420 DEY BACK UP PNTR
ED39- 24 A2 1430 BIT FAC.SIGN
ED3B- 10 04 1440 BPL .1 VALUE IS +
ED3D- C8 1450 INY VALUE IS -
ED3E- 99 FF 00 1460 STA STACK-1,Y EMIT "-"
ED41- 85 A2 1470 .1 STA FAC.SIGN MAKE FAC.SIGN POSITIVE ($2D)
ED43- 84 AD 1480 STY STRNG2 SAVE STRING PNTR
ED45- C8 1490 INY
ED46- A9 30 1500 LDA #'0' IN CASE (FAC)=0
ED48- A6 9D 1510 LDX FAC NUMBER=0?
ED4A- D0 03 1520 BNE .2 NO, (FAC) NOT ZERO
ED4C- 4C 57 EE 1530 JMP FOUT.4 YES, FINISHED
1540 *--------------------------------
ED4F- A9 00 1550 .2 LDA #0 STARTING VALUE FOR TMPEXP
ED51- E0 80 1560 CPX #$80 ANY INTEGER PART?
ED53- F0 02 1570 BEQ .3 NO, BTWN .5 AND .999999999
ED55- B0 09 1580 BCS .4 YES
1590 *--------------------------------
ED57- A9 14 1600 .3 LDA #CON.BILLION MULTIPLY BY 1E9
ED59- A0 ED 1610 LDY /CON.BILLION TO GIVE ADJUSTMENT A HEAD START
ED5B- 20 7F E9 1620 JSR FMULT
ED5E- A9 F7 1630 LDA #-9 EXPONENT ADJUSTMENT
ED60- 85 99 1640 .4 STA TMPEXP 0 OR -9
1650 *--------------------------------
1660 * ADJUST UNTIL 1E8 <= (FAC) <1E9
1670 *--------------------------------
ED62- A9 0F 1680 .5 LDA #CON.999999999
ED64- A0 ED 1690 LDY /CON.999999999
ED66- 20 B2 EB 1700 JSR FCOMP COMPARE TO 1E9-1
ED69- F0 1E 1710 BEQ .10 (FAC) = 1E9-1
ED6B- 10 12 1720 BPL .8 TOO LARGE, DIVIDE BY TEN
ED6D- A9 0A 1730 .6 LDA #CON.99999999.9 COMPARE TO 1E8-.1
ED6F- A0 ED 1740 LDY /CON.99999999.9
ED71- 20 B2 EB 1750 JSR FCOMP COMPARE TO 1E8-.1
ED74- F0 02 1760 BEQ .7 (FAC) = 1E8-.1
ED76- 10 0E 1770 BPL .9 IN RANGE, ADJUSTMENT FINISHED
ED78- 20 39 EA 1780 .7 JSR MUL10 TOO SMALL, MULTIPLY BY TEN
ED7B- C6 99 1790 DEC TMPEXP KEEP TRACK OF MULTIPLIES
ED7D- D0 EE 1800 BNE .6 ...ALWAYS
ED7F- 20 55 EA 1810 .8 JSR DIV10 TOO LARGE, DIVIDE BY TEN
ED82- E6 99 1820 INC TMPEXP KEEP TRACK OF DIVISIONS
ED84- D0 DC 1830 BNE .5 ...ALWAYS
1840 *--------------------------------
ED86- 20 A0 E7 1850 .9 JSR FADDH ROUND ADJUSTED RESULT
ED89- 20 F2 EB 1860 .10 JSR QINT CONVERT ADJUSTED VALUE TO 32-BIT INTEGER
1870 *--------------------------------
1880 * FAC+1...FAC+4 IS NOW IN INTEGER FORM
1890 * WITH POWER OF TEN ADJUSTMENT IN TMPEXP
1900 *
1910 * IF -10 < TMPEXP > 1, PRINT IN DECIMAL FORM
1920 * OTHERWISE, PRINT IN EXPONENTIAL FORM
1930 *--------------------------------
ED8C- A2 01 1940 FOUT.2 LDX #1 ASSUME 1 DIGIT BEFORE "."
ED8E- A5 99 1950 LDA TMPEXP CHECK RANGE
ED90- 18 1960 CLC
ED91- 69 0A 1970 ADC #10
ED93- 30 09 1980 BMI .1 < .01, USE EXPONENTIAL FORM
ED95- C9 0B 1990 CMP #11
ED97- B0 06 2000 BCS .2 >= 1E10, USE EXPONENTIAL FORM
ED99- 69 FF 2010 ADC #$FF LESS 1 GIVES INDEX FOR "."
ED9B- AA 2020 TAX
ED9C- A9 02 2030 LDA #2 SET REMAINING EXPONENT = 0
ED9E- 38 2040 .1 SEC COMPUTE REMAINING EXPONENT
ED9F- E9 02 2050 .2 SBC #2
EDA1- 85 9A 2060 STA EXPON VALUE FOR "E+XX" OR "E-XX"
EDA3- 86 99 2070 STX TMPEXP INDEX FOR DECIMAL POINT
EDA5- 8A 2080 TXA SEE IF "." COMES FIRST
EDA6- F0 02 2090 BEQ .3 YES
EDA8- 10 13 2100 BPL .5 NO, LATER
EDAA- A4 AD 2110 .3 LDY STRNG2 GET INDEX INTO STRING BEING BUILT
EDAC- A9 2E 2120 LDA #'.' STORE A DECIMAL POINT
EDAE- C8 2130 INY
EDAF- 99 FF 00 2140 STA STACK-1,Y
EDB2- 8A 2150 TXA SEE IF NEED ".0"
EDB3- F0 06 2160 BEQ .4 NO
EDB5- A9 30 2170 LDA #'0' YES, STORE "0"
EDB7- C8 2180 INY
EDB8- 99 FF 00 2190 STA STACK-1,Y
EDBB- 84 AD 2200 .4 STY STRNG2 SAVE OUTPUT INDEX AGAIN
2210 *--------------------------------
2220 * NOW DIVIDE BY POWERS OF TEN TO GET SUCCESSIVE DIGITS
2230 *--------------------------------
EDBD- A0 00 2240 .5 LDY #0 INDEX TO TABLE OF POWERS OF TEN
EDBF- A2 80 2250 LDX #$80 STARTING VALUE FOR DIGIT WITH DIRECTION
EDC1- A5 A1 2260 .6 LDA FAC+4 START BY ADDING -100000000 UNTIL
EDC3- 18 2270 CLC OVERSHOOT. THEN ADD +10000000,
EDC4- 79 6C EE 2280 ADC DECTBL+3,Y THEN ADD -1000000, THEN ADD
EDC7- 85 A1 2290 STA FAC+4 +100000, AND SO ON.
EDC9- A5 A0 2300 LDA FAC+3 THE # OF TIMES EACH POWER IS ADDED
EDCB- 79 6B EE 2310 ADC DECTBL+2,Y IS 1 MORE THAN CORRESPONDING DIGIT
EDCE- 85 A0 2320 STA FAC+3
EDD0- A5 9F 2330 LDA FAC+2
EDD2- 79 6A EE 2340 ADC DECTBL+1,Y
EDD5- 85 9F 2350 STA FAC+2
EDD7- A5 9E 2360 LDA FAC+1
EDD9- 79 69 EE 2370 ADC DECTBL,Y
EDDC- 85 9E 2380 STA FAC+1
EDDE- E8 2390 INX COUNT THE ADD
EDDF- B0 04 2400 BCS .7 IF C=1 AND X NEGATIVE, KEEP ADDING
EDE1- 10 DE 2410 BPL .6 IF C=0 AND X POSITIVE, KEEP ADDING
EDE3- 30 02 2420 BMI .8 IF C=0 AND X NEGATIVE, WE OVERSHOT
EDE5- 30 DA 2430 .7 BMI .6 IF C=1 AND X POSITIVE, WE OVERSHOT
EDE7- 8A 2440 .8 TXA OVERSHOT, SO MAKE X INTO A DIGIT
EDE8- 90 04 2450 BCC .9 HOW DEPENDS ON DIRECTION WE WERE GOING
EDEA- 49 FF 2460 EOR #$FF DIGIT = 9-X
EDEC- 69 0A 2470 ADC #10
EDEE- 69 2F 2480 .9 ADC #'0'-1 MAKE DIGIT INTO ASCII
EDF0- C8 2490 INY ADVANCE TO NEXT SMALLER POWER OF TEN
EDF1- C8 2500 INY
EDF2- C8 2510 INY
EDF3- C8 2520 INY
EDF4- 84 83 2530 STY VARPNT SAVE PNTR TO POWERS
EDF6- A4 AD 2540 LDY STRNG2 GET OUTPUT PNTR
EDF8- C8 2550 INY STORE THE DIGIT
EDF9- AA 2560 TAX SAVE DIGIT, HI-BIT IS DIRECTION
EDFA- 29 7F 2570 AND #$7F MAKE SURE $30...$39 FOR STRING
EDFC- 99 FF 00 2580 STA STACK-1,Y
EDFF- C6 99 2590 DEC TMPEXP COUNT THE DIGIT
EE01- D0 06 2600 BNE .10 NOT TIME FOR "." YET
EE03- A9 2E 2610 LDA #'.' TIME, SO STORE THE DECIMAL POINT
EE05- C8 2620 INY
EE06- 99 FF 00 2630 STA STACK-1,Y
EE09- 84 AD 2640 .10 STY STRNG2 SAVE OUTPUT PNTR AGAIN
EE0B- A4 83 2650 LDY VARPNT GET PNTR TO POWERS
EE0D- 8A 2660 TXA GET DIGIT WITH HI-BIT = DIRECTION
EE0E- 49 FF 2670 EOR #$FF CHANGE DIRECTION
EE10- 29 80 2680 AND #$80 $00 IF ADDING, $80 IF SUBTRACTING
EE12- AA 2690 TAX
EE13- C0 24 2700 CPY #DECTBL.END-DECTBL
EE15- D0 AA 2710 BNE .6 NOT FINISHED YET
2720 *--------------------------------
2730 * NINE DIGITS HAVE BEEN STORED IN STRING. NOW LOOK
2740 * BACK AND LOP OFF TRAILING ZEROES AND A TRAILING
2750 * DECIMAL POINT.
2760 *--------------------------------
EE17- A4 AD 2770 FOUT.3 LDY STRNG2 POINTS AT LAST STORED CHAR
EE19- B9 FF 00 2780 .1 LDA STACK-1,Y SEE IF LOPPABLE
EE1C- 88 2790 DEY
EE1D- C9 30 2800 CMP #'0' SUPPRESS TRAILING ZEROES
EE1F- F0 F8 2810 BEQ .1 YES, KEEP LOOPING
EE21- C9 2E 2820 CMP #'.' SUPPRESS TRAILING DECIMAL POINT
EE23- F0 01 2830 BEQ .2 ".", SO WRITE OVER IT
EE25- C8 2840 INY NOT ".", SO INCLUDE IN STRING AGAIN
EE26- A9 2B 2850 .2 LDA #'+' PREPARE FOR POSITIVE EXPONENT "E+XX"
EE28- A6 9A 2860 LDX EXPON SEE IF ANY E-VALUE
EE2A- F0 2E 2870 BEQ FOUT.5 NO, JUST MARK END OF STRING
EE2C- 10 08 2880 BPL .3 YES, AND IT IS POSITIVE
EE2E- A9 00 2890 LDA #0 YES, AND IT IS NEGATIVE
EE30- 38 2900 SEC COMPLEMENT THE VALUE
EE31- E5 9A 2910 SBC EXPON
EE33- AA 2920 TAX GET MAGNITUDE IN X
EE34- A9 2D 2930 LDA #'-' E SIGN
EE36- 99 01 01 2940 .3 STA STACK+1,Y STORE SIGN IN STRING
EE39- A9 45 2950 LDA #'E' STORE "E" IN STRING BEFORE SIGN
EE3B- 99 00 01 2960 STA STACK,Y
EE3E- 8A 2970 TXA EXPONENT MAGNITUDE IN A-REG
EE3F- A2 2F 2980 LDX #'0'-1 SEED FOR EXPONENT DIGIT
EE41- 38 2990 SEC CONVERT TO DECIMAL
EE42- E8 3000 .4 INX COUNT THE SUBTRACTION
EE43- E9 0A 3010 SBC #10 TEN'S DIGIT
EE45- B0 FB 3020 BCS .4 MORE TENS TO SUBTRACT
EE47- 69 3A 3030 ADC #'0'+10 CONVERT REMAINDER TO ONE'S DIGIT
EE49- 99 03 01 3040 STA STACK+3,Y STORE ONE'S DIGIT
EE4C- 8A 3050 TXA
EE4D- 99 02 01 3060 STA STACK+2,Y STORE TEN'S DIGIT
EE50- A9 00 3070 LDA #0 MARK END OF STRING WITH $00
EE52- 99 04 01 3080 STA STACK+4,Y
EE55- F0 08 3090 BEQ FOUT.6 ...ALWAYS
EE57- 99 FF 00 3100 FOUT.4 STA STACK-1,Y STORE "0" IN ASCII
EE5A- A9 00 3110 FOUT.5 LDA #0 STORE $00 ON END OF STRING
EE5C- 99 00 01 3120 STA STACK,Y
EE5F- A9 00 3130 FOUT.6 LDA #STACK POINT Y,A AT BEGINNING OF STRING
EE61- A0 01 3140 LDY /STACK (STR$ STARTED STRING AT STACK-1, BUT
EE63- 60 3150 RTS STR$ DOESN'T USE Y,A ANYWAY.)
3160 *--------------------------------
EE64- 80 00 00
EE67- 00 00 3170 CON.HALF .HS 8000000000 FP CONSTANT 0.5
3180 *--------------------------------
3190 * POWERS OF 10 FROM 1E8 DOWN TO 1,
3200 * AS 32-BIT INTEGERS, WITH ALTERNATING SIGNS
3210 *--------------------------------
EE69- FA 0A 1F
EE6C- 00 3220 DECTBL .HS FA0A1F00 -100000000
EE6D- 00 98 96
EE70- 80 3230 .HS 00989680 10000000
EE71- FF F0 BD
EE74- C0 3240 .HS FFF0BDC0 -1000000
EE75- 00 01 86
EE78- A0 3250 .HS 000186A0 100000
EE79- FF FF D8
EE7C- F0 3260 .HS FFFFD8F0 -10000
EE7D- 00 00 03
EE80- E8 3270 .HS 000003E8 1000
EE81- FF FF FF
EE84- 9C 3280 .HS FFFFFF9C -100
EE85- 00 00 00
EE88- 0A 3290 .HS 0000000A 10
EE89- FF FF FF
EE8C- FF 3300 .HS FFFFFFFF -1
3310 DECTBL.END
3320 *--------------------------------

... and STROUT ...

DB02- 60 1310 RTS.8 RTS

1690 *--------------------------------
1700 * PRINT STRING AT (Y,A)
DB3A- 20 E7 E3 1710 STROUT JSR STRLIT MAKE (Y,A) PRINTABLE
1720 *--------------------------------
1730 * PRINT STRING AT (FACMO,FACLO)
1740 *--------------------------------
DB3D- 20 00 E6 1750 STRPRT JSR FREFAC GET ADDRESS INTO INDEX, (A)=LENGTH
DB40- AA 1760 TAX USE X-REG FOR COUNTER
DB41- A0 00 1770 LDY #0 USE Y-REG FOR SCANNER
DB43- E8 1780 INX
DB44- CA 1790 .1 DEX
DB45- F0 BB 1800 BEQ RTS.8 FINISHED
DB47- B1 5E 1810 LDA (INDEX),Y NEXT CHAR FROM STRING
DB49- 20 5C DB 1820 JSR OUTDO PRINT THE CHAR
DB4C- C8 1830 INY
1840 * <<< NEXT THREE LINES ARE USELESS >>>
DB4D- C9 0D 1850 CMP #$0D WAS IT <RETURN>?
DB4F- D0 F3 1860 BNE .1 NO
DB51- 20 00 DB 1870 JSR NEGATE EOR #$FF WOULD DO IT, BUT WHY?
1880 * <<< ABOVE THREE LINES ARE USELESS >>>
DB54- 4C 44 DB 1890 JMP .1
1900 *--------------------------------
DB57- A9 20 1910 OUTSP LDA #' ' PRINT A SPACE
DB59- 2C 1920 .HS 2C SKIP OVER NEXT LINE
DB5A- A9 3F 1930 OUTQUES LDA #'?' PRINT QUESTION MARK
1940 *--------------------------------
1950 * PRINT CHAR FROM (A)
1960 *
1970 * NOTE: POKE 243,32 ($20 IN $F3) WILL CONVERT
1980 * OUTPUT TO LOWER CASE. THIS CAN BE CANCELLED
1990 * BY NORMAL, INVERSE, OR FLASH OR POKE 243,0.
2000 *--------------------------------
DB5C- 09 80 2010 OUTDO ORA #$80 PRINT (A)
DB5E- C9 A0 2020 CMP #$A0 CONTROL CHR?
DB60- 90 02 2030 BCC .1 SKIP IF SO
DB62- 05 F3 2040 ORA FLASH.BIT =$40 FOR FLASH, ELSE $00
DB64- 20 ED FD 2050 .1 JSR MON.COUT "AND"S WITH $3F (INVERSE), $7F (FLASH)
DB67- 29 7F 2060 AND #$7F
DB69- 48 2070 PHA
DB6A- A5 F1 2080 LDA SPEEDZ COMPLEMENT OF SPEED #
DB6C- 20 A8 FC 2090 JSR MON.WAIT SO SPEED=255 BECOMES (A)=1
DB6F- 68 2100 PLA
DB70- 60 2110 RTS


... and STRLIT ...

1300 *--------------------------------
1310 * BUILD A DESCRIPTOR FOR STRING STARTING AT Y,A
1320 * AND TERMINATED BY $00 OR QUOTATION MARK
1330 * RETURN WITH DESCRIPTOR IN A TEMPORARY
1340 * AND ADDRESS OF DESCRIPTOR IN FAC+3,4
1350 *--------------------------------
E3E7- A2 22 1360 STRLIT LDX #'"' SET UP LITERAL SCAN TO STOP ON
E3E9- 86 0D 1370 STX CHARAC QUOTATION MARK OR $00
E3EB- 86 0E 1380 STX ENDCHR
1390 *--------------------------------
1400 * BUILD A DESCRIPTOR FOR STRING STARTING AT Y,A
1410 * AND TERMINATED BY $00, (CHARAC), OR (ENDCHR)
1420 *
1430 * RETURN WITH DESCRIPTOR IN A TEMPORARY
1440 * AND ADDRESS OF DESCRIPTOR IN FAC+3,4
1450 *--------------------------------
E3ED- 85 AB 1460 STRLT2 STA STRNG1 SAVE ADDRESS OF STRING
E3EF- 84 AC 1470 STY STRNG1+1
E3F1- 85 9E 1480 STA FAC+1 ...AGAIN
E3F3- 84 9F 1490 STY FAC+2
E3F5- A0 FF 1500 LDY #$FF
E3F7- C8 1510 .1 INY FIND END OF STRING
E3F8- B1 AB 1520 LDA (STRNG1),Y NEXT STRING CHAR
E3FA- F0 0C 1530 BEQ .3 END OF STRING
E3FC- C5 0D 1540 CMP CHARAC ALTERNATE TERMINATOR # 1?
E3FE- F0 04 1550 BEQ .2 YES
E400- C5 0E 1560 CMP ENDCHR ALTERNATE TERMINATOR # 2?
E402- D0 F3 1570 BNE .1 NO, KEEP SCANNING
E404- C9 22 1580 .2 CMP #'"' IS STRING ENDED WITH QUOTE MARK?
E406- F0 01 1590 BEQ .4 YES, C=1 TO INCLUDE " IN STRING
E408- 18 1600 .3 CLC
E409- 84 9D 1610 .4 STY FAC SAVE LENGTH
E40B- 98 1620 TYA
E40C- 65 AB 1630 ADC STRNG1 COMPUTE ADDRESS OF END OF STRING
E40E- 85 AD 1640 STA STRNG2 (OF 00 BYTE, OR JUST AFTER ")
E410- A6 AC 1650 LDX STRNG1+1
E412- 90 01 1660 BCC .5
E414- E8 1670 INX
E415- 86 AE 1680 .5 STX STRNG2+1
E417- A5 AC 1690 LDA STRNG1+1 WHERE DOES THE STRING START?
E419- F0 04 1700 BEQ .6 PAGE 0, MUST BE FROM STR$ FUNCTION
E41B- C9 02 1710 CMP #2 PAGE 2?
E41D- D0 0B 1720 BNE PUTNEW NO, NOT PAGE 0 OR 2
E41F- 98 1730 .6 TYA LENGTH OF STRING
E420- 20 D5 E3 1740 JSR STRINI MAKE SPACE FOR STRING
E423- A6 AB 1750 LDX STRNG1
E425- A4 AC 1760 LDY STRNG1+1
E427- 20 E2 E5 1770 JSR MOVSTR MOVE IT IN
1780 *--------------------------------
1790 * STORE DESCRIPTOR IN TEMPORARY DESCRIPTOR STACK
1800 *
1810 * THE DESCRIPTOR IS NOW IN FAC, FAC+1, FAC+2
1820 * PUT ADDRESS OF TEMP DESCRIPTOR IN FAC+3,4
1830 *--------------------------------
E42A- A6 52 1840 PUTNEW LDX TEMPPT POINTER TO NEXT TEMP STRING SLOT
E42C- E0 5E 1850 CPX #TEMPST+9 MAX OF 3 TEMP STRINGS
E42E- D0 05 1860 BNE PUTEMP ROOM FOR ANOTHER ONE
E430- A2 BF 1870 LDX #ERR.FRMCPX TOO MANY, FORMULA TOO COMPLEX
E432- 4C 12 D4 1880 JERR JMP ERROR
1890 *--------------------------------
E435- A5 9D 1900 PUTEMP LDA FAC COPY TEMP DESCRIPTOR INTO TEMP STACK
E437- 95 00 1910 STA 0,X
E439- A5 9E 1920 LDA FAC+1
E43B- 95 01 1930 STA 1,X
E43D- A5 9F 1940 LDA FAC+2
E43F- 95 02 1950 STA 2,X
E441- A0 00 1960 LDY #0
E443- 86 A0 1970 STX FAC+3 ADDRESS OF TEMP DESCRIPTOR
E445- 84 A1 1980 STY FAC+4 IN Y,X AND FAC+3,4
E447- 88 1990 DEY Y=$FF
E448- 84 11 2000 STY VALTYP FLAG (FAC ) AS STRING
E44A- 86 53 2010 STX LASTPT INDEX OF LAST POINTER
E44C- E8 2020 INX UPDATE FOR NEXT TEMP ENTRY
E44D- E8 2030 INX
E44E- E8 2040 INX
E44F- 86 52 2050 STX TEMPPT
E451- 60 2060 RTS

... and FREFAC ...

1720 *--------------------------------
1730 * IF STRING DESCRIPTOR POINTED TO BY FAC+3,4 IS
1740 * A TEMPORARY STRING, RELEASE IT.
1750 *--------------------------------
E600- A5 A0 1760 FREFAC LDA FAC+3 GET DESCRIPTOR POINTER
E602- A4 A1 1770 LDY FAC+4
1780 *--------------------------------
1790 * IF STRING DESCRIPTOR WHOSE ADDRESS IS IN Y,A IS
1800 * A TEMPORARY STRING, RELEASE IT.
1810 *--------------------------------
E604- 85 5E 1820 FRETMP STA INDEX SAVE THE ADDRESS OF THE DESCRIPTOR
E606- 84 5F 1830 STY INDEX+1
E608- 20 35 E6 1840 JSR FRETMS FREE DESCRIPTOR IF IT IS TEMPORARY
E60B- 08 1850 PHP REMEMBER IF TEMP
E60C- A0 00 1860 LDY #0 POINT AT LENGTH OF STRING
E60E- B1 5E 1870 LDA (INDEX),Y
E610- 48 1880 PHA SAVE LENGTH ON STACK
E611- C8 1890 INY
E612- B1 5E 1900 LDA (INDEX),Y
E614- AA 1910 TAX GET ADDRESS OF STRING IN Y,X
E615- C8 1920 INY
E616- B1 5E 1930 LDA (INDEX),Y
E618- A8 1940 TAY
E619- 68 1950 PLA LENGTH IN A
E61A- 28 1960 PLP RETRIEVE STATUS, Z=1 IF TEMP
E61B- D0 13 1970 BNE .2 NOT A TEMPORARY STRING
E61D- C4 70 1980 CPY FRETOP+1 IS IT THE LOWEST STRING?
E61F- D0 0F 1990 BNE .2 NO
E621- E4 6F 2000 CPX FRETOP
E623- D0 0B 2010 BNE .2 NO
E625- 48 2020 PHA YES, PUSH LENGTH AGAIN
E626- 18 2030 CLC RECOVER THE SPACE USED BY
E627- 65 6F 2040 ADC FRETOP THE STRING
E629- 85 6F 2050 STA FRETOP
E62B- 90 02 2060 BCC .1
E62D- E6 70 2070 INC FRETOP+1
E62F- 68 2080 .1 PLA RETRIEVE LENGTH AGAIN
E630- 86 5E 2090 .2 STX INDEX ADDRESS OF STRING IN Y,X
E632- 84 5F 2100 STY INDEX+1 LENGTH OF STRING IN A-REG
E634- 60 2110 RTS

... and NORMALIZE.FAC.1 ...

1850 *--------------------------------
1860 * NORMALIZE VALUE IN FAC
1870 *--------------------------------
1880 NORMALIZE.FAC.1
E829- B0 03 1890 BCS NORMALIZE.FAC.2
E82B- 20 9E E8 1900 JSR COMPLEMENT.FAC
1910 *--------------------------------
1920 NORMALIZE.FAC.2
E82E- A0 00 1930 LDY #0 SHIFT UP SIGNIF DIGIT
E830- 98 1940 TYA START A=0, COUNT SHIFTS IN A-REG
E831- 18 1950 CLC
E832- A6 9E 1960 .1 LDX FAC+1 LOOK AT MOST SIGNIFICANT BYTE
E834- D0 4A 1970 BNE NORMALIZE.FAC.4 SOME 1-BITS HERE
E836- A6 9F 1980 LDX FAC+2 HI-BYTE OF MANTISSA STILL ZERO,
E838- 86 9E 1990 STX FAC+1 SO DO A FAST 8-BIT SHUFFLE
E83A- A6 A0 2000 LDX FAC+3
E83C- 86 9F 2010 STX FAC+2
E83E- A6 A1 2020 LDX FAC+4
E840- 86 A0 2030 STX FAC+3
E842- A6 AC 2040 LDX FAC.EXTENSION
E844- 86 A1 2050 STX FAC+4
E846- 84 AC 2060 STY FAC.EXTENSION ZERO EXTENSION BYTE
E848- 69 08 2070 ADC #8 BUMP SHIFT COUNT
E84A- C9 20 2080 CMP #32 DONE 4 TIMES YET?
E84C- D0 E4 2090 BNE .1 NO, STILL MIGHT BE SOME 1'S
2100 * YES, VALUE OF FAC IS ZERO
2110 *--------------------------------
2120 * SET FAC = 0
2130 * (ONLY NECESSARY TO ZERO EXPONENT AND SIGN CELLS)
2140 *--------------------------------
2150 ZERO.FAC
E84E- A9 00 2160 LDA #0
2170 *--------------------------------
2180 STA.IN.FAC.SIGN.AND.EXP
E850- 85 9D 2190 STA FAC
2200 *--------------------------------
2210 STA.IN.FAC.SIGN
E852- 85 A2 2220 STA FAC.SIGN
E854- 60 2230 RTS


... and FLOAT.2 ...

1520 *--------------------------------
1530 * FLOAT UNSIGNED VALUE IN FAC+1,2
1540 * (X) = EXPONENT
1550 * C=0 TO MAKE VALUE NEGATIVE
1560 * C=1 TO MAKE VALUE POSITIVE
1570 *--------------------------------
1580 FLOAT.2
EBA0- A9 00 1590 LDA #0 CLEAR LOWER 16-BITS OF MANTISSA
EBA2- 85 A1 1600 STA FAC+4
EBA4- 85 A0 1610 STA FAC+3
EBA6- 86 9D 1620 STX FAC STORE EXPONENT
EBA8- 85 AC 1630 STA FAC.EXTENSION CLEAR EXTENSION
EBAA- 85 A2 1640 STA FAC.SIGN MAKE SIGN POSITIVE
EBAC- 4C 29 E8 1650 JMP NORMALIZE.FAC.1 IF C=0, WILL NEGATE FAC
Harry Potter
2017-07-05 14:49:02 UTC
Permalink
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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
Raw Message
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...