1 
2 #define STDIO_ASM
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 
7 #asm
8 	SECTION code_clib
9 	PUBLIC	funopen
10 	PUBLIC	_funopen
11 
12 ; FILE  *funopen(const void	*cookie, int (*readfn)(void *, char *, int),
13 ;	 int (*writefn)(void *,	const char *, int),
14 ;	 fpos_t	(*seekfn)(void *, fpos_t, int),	int (*closefn)(void *));
15 
16 DEFVARS 0 {
17 	fu_readfn		ds.w	1
18 	fu_writefn		ds.w	1
19 	fu_seekfn		ds.w	1
20 	fu_closefn		ds.w	1
21 }
22 
23 
24 funopen:
25 _funopen:
26 IF __CPU_INTEL__ | __CPU_GBZ80__
27 	ld	hl,0
28 	ret
29 ELSE
30 	; Allocate some memory first of all
31 	push	ix		;save callers ix
32 
33 	ld	ix,4
34 	add	ix,sp		;points to closefn
35 
36 	ld	hl, +(fp_extra + 2) + ( fu_closefn + 2)
37 	push	hl
38 	call	malloc
39 	pop	bc
40 	push	hl		;Keep for later
41 	ld	e,(ix+8)	;cookie
42 	ld	d,(ix+9)
43 	ld	(hl),e		;fp_desc
44 	inc	hl
45 	ld	(hl),d
46 	inc	hl
47 	ld	(hl),_IOUSE|_IOEXTRA|_IOREAD|_IOWRITE
48 	inc	hl
49 	ld	(hl),0		;ungetc
50 	inc	hl
51 	ld	de,funopen_trampoline
52 	ld	(hl),e
53 	inc	hl
54 	ld	(hl),d
55 	inc	hl
56 	ld	e,(ix + 6)	;readfn
57 	ld	d,(ix + 7)
58 	call	noop_becomes_dummy
59 	ld	(hl),e
60 	inc	hl
61 	ld	(hl),d
62 	inc	hl
63 	ld	e,(ix + 4)	;writefn
64 	ld	d,(ix + 5)
65 	call	noop_becomes_dummy
66 	ld	(hl),e
67 	inc	hl
68 	ld	(hl),d
69 	inc	hl
70 	ld	e,(ix + 2)	;seekfn
71 	ld	d,(ix + 3)
72 	call	noop_becomes_dummy
73 	ld	(hl),e
74 	inc	hl
75 	ld	(hl),d
76 	inc	hl
77 	ld	e,(ix + 0)	;closefn
78 	ld	d,(ix + 1)
79 	call	noop_becomes_dummy
80 	ld	(hl),e
81 	inc	hl
82 	ld	(hl),d
83 	pop	hl		;get fp back
84 	pop	ix		;restore callers
85 	ret
86 
87 noop_becomes_dummy:
88 	ld	a,d
89 	or	e
90 	ret	nz
91 	ld	de,dummy_func
92 	ret
93 
94 dummy_func:
95 	ld	hl,-1
96 	ld	d,h
97 	ld	e,l
98 	scf
99 	ret
100 
101 funopen_trampoline:
102         cp      __STDIO_MSG_GETC
103         jr      z,handle_getc
104         cp      __STDIO_MSG_PUTC
105         jr      z,handle_putc
106         cp      __STDIO_MSG_READ
107         jr      z,handle_read
108         cp      __STDIO_MSG_WRITE
109         jr      z,handle_write
110         cp      __STDIO_MSG_SEEK
111         jr      z,handle_seek
112         cp      __STDIO_MSG_CLOSE
113         jr      z,handle_close
114 	ld	hl,-1
115 	ld	d,h
116 	ld	e,l
117 	ret
118 
119 
120 
121 handle_getc:
122 	push	hl	; storage space
123 	ld	hl,0
124 	add	hl,sp
125 	ex	de,hl	;de = buf
126 	ld	bc,1
127 	call	handle_read
128 handle_returncodes:
129 	pop	bc	; c = byte read (if any)
130 	ld	a,h
131 	or	l
132 	jr	z,eof
133 	inc	hl
134 	ld	a,h
135 	or	l
136 	jr	z,error
137 	; Successful return, return new character
138 	ld	l,c
139 	ld	h,0
140 	ret
141 eof:
142 error:
143 	scf
144 	ld	hl,EOF
145 	ret
146 
147 ; Entry: ix = fp
148 ;        bc = character
149 ; Exit: hl = result
150 handle_putc:
151 	push	bc
152 	ld	hl,0
153 	add	hl,sp
154 	ex	de,hl
155 	ld	bc,1
156 	call	handle_write
157 	pop	bc	; byte we wrote
158 	inc	hl
159 	ld	a,h
160 	or	l
161 	jr	z,eof
162 	; Successful return, return character written
163 	ld	l,c
164 	ld	h,0
165 	ret
166 
167 ; ix = fp
168 ; de = buf,
169 ; bc = length
170 handle_read:
171 	ld	l,(ix+fp_desc)
172 	ld	h,(ix+fp_desc+1)
173 	push	hl
174 	push	de
175 	push	bc
176 	ld	l,(ix + fp_extra + 2 + fu_readfn)
177 	ld	h,(ix + fp_extra + 2 + fu_readfn + 1)
178 exec_3args:
179 	call	l_jphl
180 	pop	bc
181 	pop	bc
182 	pop	bc
183 	ret
184 
185 ; ix = fp
186 ; de = buf,
187 ; bc = length
188 handle_write:
189 	ld	l,(ix+fp_desc)
190 	ld	h,(ix+fp_desc+1)
191 	push	hl
192 	push	de
193 	push	bc
194 	ld	l,(ix + fp_extra + 2 + fu_writefn)
195 	ld	h,(ix + fp_extra + 2 + fu_writefn + 1)
196 	jr	exec_3args
197 
198 handle_close:
199 	ld	l,(ix + fp_extra + 2 + fu_closefn)
200 	ld	h,(ix + fp_extra + 2 + fu_closefn + 1)
201 	ld	c,(ix + fp_desc)
202 	ld	b,(ix + fp_desc + 1)
203 	push	bc
204 	call	l_jphl		; call users close function
205 	pop	bc
206 	push	ix
207 	pop	hl
208 	call	free		; and free the descriptor
209 	pop	bc
210 	ret
211 
212 
213 ; Entry: ix=fp
214 ; debc=posn
215 ; alt-a = whence
216 ; Exit: dehl = current position or -1
217 handle_seek:
218 	ld	l,(ix+fp_desc)
219 	ld	h,(ix+fp_desc+1)
220 	push	hl		;void *
221 	push	bc		;posn
222 	push	de
223 	ex	af,af
224 	ld	c,a
225 	ld	b,0
226 	push	bc		;whence
227 	ld	l,(ix + fp_extra + 2 + fu_seekfn)
228 	ld	h,(ix + fp_extra + 2 + fu_seekfn + 1)
229 	call	l_jphl
230 	pop	bc
231 	pop	bc
232 	pop	bc
233 	pop	bc
234         ret
235 ENDIF
236 
237 
238 
239 #endasm
240 
241