1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
;
; Low level file I/O routines, ONLY for module loading OR sth similar
;
; Maciej 'YTM/Elysium' Witkowiak <ytm@elysium.pl>
; 25.12.2002
;
; only ONE opened file at a time, only O_RDONLY flag
; int open (const char* name, int flags, ...); /* May take a mode argument */
; int __fastcall__ close (int fd);
; int __fastcall__ read (int fd, void* buf, unsigned count);
FILEDES = 3 ; first free to use file descriptor
.importzp ptr1, ptr2, ptr3, tmp1
.import addysp, popax, popptr1
.import __oserror
.import _FindFile, _ReadByte
.export _open, _close, _read
.include "geossym.inc"
.include "const.inc"
.include "errno.inc"
.include "fcntl.inc"
_open:
cpy #4 ; correct # of arguments (bytes)?
beq @parmok ; parameter count ok
tya ; parm count < 4 shouldn't be needed to be...
sec ; ...checked (it generates a c compiler warning)
sbc #4
tay
jsr addysp ; fix stack, throw away unused parameters
; Parameters ok. Pop the flags and save them into tmp3
@parmok:
jsr popax ; Get flags
sta tmp1
jsr popptr1 ; Get name
lda filedesc ; is there a file already open?
bne @alreadyopen
lda tmp1 ; check open mode
and #(O_RDWR | O_CREAT)
cmp #O_RDONLY ; only O_RDONLY is valid
bne @badmode
lda ptr1
ldx ptr1+1
jsr _FindFile ; try to find the file
tax
bne @oserror
lda dirEntryBuf + OFF_DE_TR_SC ; tr&se for ReadByte (r1)
sta f_track
lda dirEntryBuf + OFF_DE_TR_SC + 1
sta f_sector
lda #<diskBlkBuf ; buffer for ReadByte (r4)
sta f_buffer
lda #>diskBlkBuf
sta f_buffer+1
ldx #0 ; offset for ReadByte (r5)
stx f_offset
stx f_offset+1
lda #0 ; clear errors
sta __oserror
jsr __seterrno
lda #FILEDES ; return fd
sta filedesc
rts
@badmode:
lda #EINVAL ; invalid parameters - invalid open mode
.byte $2c ; skip
@alreadyopen:
lda #EMFILE ; too many opened files (there can be only one)
jmp __directerrno ; set errno, clear oserror, return -1
@oserror:
jmp __mappederrno ; set platform error code, return -1
_close:
lda #0
sta __oserror
jsr __seterrno ; clear errors
lda #0 ; clear fd
sta filedesc
tax
rts
_read:
; a/x - number of bytes
; popax - buffer ptr
; popax - fd, must be == to the above one
; return -1+__oserror or number of bytes read
eor #$ff
sta ptr1
txa
eor #$ff
sta ptr1+1 ; -(# of bytes to read)-1
jsr popax
sta ptr2
stx ptr2+1 ; buffer ptr
jsr popax
cmp #FILEDES ; lo-byte == FILEDES
bne @filenotopen
txa ; hi-byte == 0
beq @fileok ; fd must be == FILEDES
@filenotopen:
lda #EBADF
jmp __directerrno ; Sets _errno, clears _oserror, returns -1
@fileok:
lda #0
sta ptr3
sta ptr3+1 ; put 0 into ptr3 (number of bytes read)
sta __oserror ; clear error flags
jsr __seterrno
lda f_track ; restore stuff for ReadByte
ldx f_sector
sta r1L
stx r1H
lda f_buffer
ldx f_buffer+1
sta r4L
stx r4H
lda f_offset
ldx f_offset+1
sta r5L
stx r5H
clc
bcc @L3 ; branch always
@L0: jsr _ReadByte
ldy #0 ; store the byte
sta (ptr2),y
inc ptr2 ; increment target address
bne @L1
inc ptr2+1
@L1: inc ptr3 ; increment byte count
bne @L2
inc ptr3+1
@L2: lda __oserror ; was there error ?
beq @L3
cmp #BFR_OVERFLOW ; EOF?
beq @done ; yes, we're done
jmp __mappederrno ; no, we're screwed
@L3: inc ptr1 ; decrement the count
bne @L0
inc ptr1+1
bne @L0
@done:
lda r1L ; preserve data for ReadByte
ldx r1H
sta f_track
stx f_sector
lda r4L
ldx r4H
sta f_buffer
stx f_buffer+1
lda r5L
ldx r5H
sta f_offset
stx f_offset+1
lda ptr3 ; return byte count
ldx ptr3+1
rts
.bss
filedesc:
.res 1 ; file open flag - 0 (no file opened) or 1
f_track:
.res 1 ; values preserved for ReadByte
f_sector:
.res 1
f_offset:
.res 2
f_buffer:
.res 2
|