]> git.sur5r.net Git - cc65/blob - libsrc/common/vsprintf.s
Added mouse module from C64
[cc65] / libsrc / common / vsprintf.s
1 ;
2 ; int vsprintf (char* Buf, const char* Format, va_list ap);
3 ;
4 ; Ullrich von Bassewitz, 1.12.2000
5 ;
6
7         .export         _vsprintf
8         .import         pushax, popax
9         .import         _memcpy, __printf
10         .importzp       sp, ptr1
11
12         .macpack        generic
13
14
15 .data
16
17 ; ----------------------------------------------------------------------------
18 ;
19 ; Static data for the _vsprintf routine
20 ;
21
22 outdesc:                        ; Static outdesc structure
23         .word   0               ; ccount
24         .word   out             ; Output function pointer
25         .word   0               ; ptr
26         .word   $7FFF           ; Buffer size (max int)
27
28 .code
29
30 ; ----------------------------------------------------------------------------
31 ; Callback routine used for the actual output.
32 ;
33 ; static void out (struct outdesc* d, const char* buf, unsigned count)
34 ; /* Routine used for writing */
35 ; {
36 ;     /* String - be shure to check the size */
37 ;     while (count-- && d->ccount < d->uns) {
38 ;         ((char*) d->ptr) [d->ccount] = *buf;
39 ;         ++buf;
40 ;         ++d->ccount;
41 ;     }
42 ; }
43 ;
44 ; The assembler version assumes that the buffer is big enough and just copies
45 ; all characters into the buffer. This has to be changed for a vsnprintf like
46 ; function but is ok for now.
47 ; For simplicity, we will use memcpy to copy the stuff and will just rearrange
48 ; the stack to create a matching frame for memcpy.
49
50 out:    ldy     #4                      ; d on stack
51         lda     (sp),y
52         sta     ptr1
53         iny
54         lda     (sp),y
55         sta     ptr1+1                  ; Save d into ptr1
56
57 ; Get a pointer to the target buffer and store it into the stack frame
58 ; currently occupied by d
59
60         dey                             ; d->ptr
61         lda     (ptr1),y                ; Low byte of d->ptr
62         ldy     #0
63         add     (ptr1),y                ; Low byte of d->ccount
64         ldy     #4
65         sta     (sp),y                  ; Store into d stackframe
66         iny
67         lda     (ptr1),y                ; High byte of d->ptr
68         ldy     #1
69         adc     (ptr1),y                ; High byte of d->ccount
70         ldy     #5
71         sta     (sp),y
72
73 ; Increment the total count by the number if bytes in this chunk. While doing
74 ; so, load count into a/x since _memcpy is a fastcall function
75
76         jsr     popax                   ; Get count
77         pha                             ; Save low byte
78         ldy     #0
79         add     (ptr1),y                ; Low byte of d->ccount
80         sta     (ptr1),y
81         iny
82         txa                             ; High byte of count
83         adc     (ptr1),y                ; High byte of d->ccount
84         sta     (ptr1),y
85         pla                             ; Restore low byte of count
86
87 ; We have the correct stackframe for memcpy now, call it
88
89         jmp     _memcpy
90
91
92 ; ----------------------------------------------------------------------------
93 ; vsprintf - formatted output into a buffer
94 ;
95 ; int vsprintf (char* buf, const char* format, va_list ap)
96 ; {
97 ;     struct outdesc d;
98 ;
99 ;     /* Setup descriptor */
100 ;     d.fout = out;
101 ;     d.ptr  = buf;
102 ;     d.uns  = 0x7FFF;
103 ;
104 ;     /* Do formatting and output */
105 ;     _printf (&d, format, ap);
106 ;
107 ;     /* Terminate the result string */
108 ;     buf [d.ccount++] = '\0';
109 ;
110 ;     /* Return bytes written */
111 ;     return d.ccount;
112 ; }
113
114
115 _vsprintf:
116         pha                     ; Save low byte of ap
117
118 ; Setup the outdesc structure
119
120         lda     #0
121         sta     outdesc
122         sta     outdesc+1       ; Clear ccount
123
124 ; Reorder the stack. Replace buf on the stack by &d, so the stack frame is
125 ; exactly as _printf expects it. Parameters will get dropped by _printf.
126
127         ldy     #2              ;
128         lda     (sp),y          ; Low byte of buf
129         sta     outdesc+4       ; Store into outdesc.ptr
130         lda     #<outdesc
131         sta     (sp),y
132         iny
133         lda     (sp),y          ; High byte of buf
134         sta     outdesc+5
135         lda     #>outdesc
136         sta     (sp),y
137
138 ; Restore low byte of ap and call _printf
139
140         pla
141         jsr     __printf
142
143 ; Terminate the string
144
145         lda     outdesc+4       ; buf
146         add     outdesc+0       ; +ccount
147         sta     ptr1
148         lda     outdesc+5
149         adc     outdesc+1
150         sta     ptr1+1
151         ldy     #0
152         tya
153         sta     (ptr1),y
154
155 ; Return the number of bytes written. The carry is clear here because of the
156 ; last addition which will never overflow for sane code.
157
158         lda     outdesc         ; ccount
159         ldx     outdesc+1
160         adc     #1              ; Account for terminator
161         bcc     @L9
162         inx
163 @L9:    rts
164
165