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