]> git.sur5r.net Git - cc65/blob - libsrc/apple2/exec.s
lseek: Return EINVAL if new position is less than 0 or greater than 2^24 - 1.
[cc65] / libsrc / apple2 / exec.s
1 ;
2 ; Oliver Schmidt, 2011-01-26
3 ;
4 ; int __fastcall__ exec (const char* progname, const char* cmdline);
5 ;
6
7         .export         _exec
8         .import         pushname, popname
9         .import         popax, done, _exit
10
11         .include        "zeropage.inc"
12         .include        "errno.inc"
13         .include        "apple2.inc"
14         .include        "mli.inc"
15
16         ; Wrong file type
17 typerr: lda     #$4A            ; "Incompatible file format"
18
19         ; Cleanup name
20 oserr:  jsr     popname         ; Preserves A
21         
22         ; Set __oserror
23         jmp     __mappederrno
24
25 _exec:
26         ; Save cmdline
27         sta     ptr4
28         stx     ptr4+1
29
30         ; Get and push name
31         jsr     popax
32         jsr     pushname
33         bne     oserr
34
35         ; ProDOS TechRefMan, chapter 5.1.5.1:
36         ; "The complete or partial pathname of the system program
37         ;  is stored at $280, starting with a length byte."
38         ; In fact BASIC.SYSTEM does the same for BLOAD and BRUN of
39         ; binary programs so we should do the same too in any case
40         ; especially as _we_ rely on it in mainargs.s for argv[0]
41         ldy     #$00
42         lda     (sp),y
43         tay
44 :       lda     (sp),y
45         sta     $0280,y
46         dey
47         bpl     :-
48
49         ; Set pushed name
50         lda     sp
51         ldx     sp+1
52         sta     mliparam + MLI::INFO::PATHNAME
53         stx     mliparam + MLI::INFO::PATHNAME+1
54
55         ; Get file_type and aux_type
56         lda     #GET_INFO_CALL
57         ldx     #GET_INFO_COUNT
58         jsr     callmli
59         bcs     oserr
60
61         ; If we get here the program file at least exists so we copy
62         ; the loader stub right now and patch it later to set params
63         ldx     #size - 1
64 :       lda     source,x
65         sta     target,x
66         dex
67         bpl     :-
68
69         ; Check program file type
70         lda     mliparam + MLI::INFO::FILE_TYPE
71         cmp     #$FF            ; SYS file?
72         bne     binary          ; No, check for BIN file
73         sta     file_type       ; Save file type for cmdline handling
74
75         ; SYS programs replace BASIC.SYSTEM so set in the ProDOS system bit map
76         ; protection for pages $80 - $BF just in case BASIC.SYSTEM is there now
77         ldx     #$0F            ; Start with protection for pages $B8 - $BF
78         lda     #%00000001      ; Protect only system global page
79 :       sta     $BF60,x         ; Set protection for 8 pages
80         lda     #%00000000      ; Protect no page
81         dex
82         bpl     :-
83         bmi     prodos          ; Branch always
84
85 binary: cmp     #$06            ; BIN file?
86         bne     typerr          ; No, wrong file type
87
88         ; Set BIN program load addr
89         lda     mliparam + MLI::INFO::AUX_TYPE
90         ldx     mliparam + MLI::INFO::AUX_TYPE+1
91         sta     data_buffer
92         stx     data_buffer+1
93
94         ; Check ProDOS system bit map for presence of BASIC.SYSTEM
95         lda     $BF6F           ; Protection for pages $B8 - $BF
96         cmp     #%00000001      ; Exactly system global page is protected
97         beq     setvec
98
99         ; Get highest available mem addr from BASIC.SYSTEM
100         ldx     HIMEM+1         ; High byte
101         bne     setbuf          ; Branch always
102
103         ; BIN programs are supposed to quit through one of the two DOS
104         ; vectors so we set up those to point to the ProDOS dispatcher
105 setvec: ldx     #$03 - 1        ; Size of JMP opcode
106 :       lda     dosvec,x
107         sta     DOSWARM,x       ; DOS warm start
108         sta     DOSWARM + 3,x   ; DOS cold start
109         dex
110         bpl     :-
111
112         ; No BASIC.SYSTEM so use addr of ProDOS system global page
113 prodos: ldx     #>$BF00         ; High byte
114
115         ; The I/O buffer needs to be page aligned
116 setbuf: lda     #$00            ; Low byte
117
118         ; The I/O buffer needs four pages
119         dex
120         dex
121         dex
122         dex
123
124         ; Set I/O buffer
125         sta     mliparam + MLI::OPEN::IO_BUFFER
126         stx     mliparam + MLI::OPEN::IO_BUFFER+1
127
128         ; PATHNAME already set
129         .assert MLI::OPEN::PATHNAME = MLI::INFO::PATHNAME, error
130
131         ; Lower file level to avoid program file
132         ; being closed by C libary shutdown code
133         ldx     LEVEL
134         stx     level
135         beq     :+
136         dec     LEVEL
137
138         ; Open file
139 :       lda     #OPEN_CALL
140         ldx     #OPEN_COUNT
141         jsr     callmli
142
143         ; Restore file level
144         ldx     level
145         stx     LEVEL
146         bcc     :+
147         jmp     oserr
148
149         ; Get and save fd
150 :       lda     mliparam + MLI::OPEN::REF_NUM
151         sta     read_ref
152         sta     close_ref
153
154         .ifdef  __APPLE2ENH__
155         ; Calling the 80 column firmware needs the ROM switched
156         ; in, otherwise it copies the F8 ROM to the LC (@ $CEF4)
157         bit     $C082
158
159         ; ProDOS TechRefMan, chapter 5.3.1.3:
160         ; "80-column text cards -- and other Apple IIe features -- can
161         ;  be turned off using the following sequence of instructions:"
162         lda     #$15
163         jsr     $C300
164
165         ; Switch in LC bank 2 for R/O
166         bit     $C080
167         .endif
168
169         ; Reset stack as we already passed
170         ; the point of no return anyway
171         ldx     #$FF
172         txs
173
174         ; Store up to 127 chars of cmdline (if any)
175         ; including terminating zero in stack page
176         ldy     #$00
177         lda     ptr4+1          ; NULL?
178         beq     :++             ; Yes, store as '\0'
179 :       lda     (ptr4),y
180 :       sta     $0100,y
181         beq     :+              ; '\0' stored, done
182         iny
183         cpy     #$7E
184         bcc     :--
185         lda     #$00            ; '\0'
186         beq     :-              ; Branch always
187
188         ; Call loader stub after C libary shutdown
189 :       lda     #<target
190         ldx     #>target
191         sta     done+1
192         stx     done+2
193
194         ; Initiate C libary shutdown
195         jmp     _exit
196
197         .bss
198
199 level : .res    1
200
201         .rodata
202
203         ; Read whole program file
204 source: jsr     $BF00
205         .byte   READ_CALL
206         .word   read_param
207         bcs     error
208
209         ; Close program file
210         jsr     $BF00
211         .byte   CLOSE_CALL
212         .word   close_param
213         bcs     error
214
215         ; Check for cmdline handling
216         lda     $0100           ; Valid cmdline?
217         beq     jump            ; No, jump to program right away
218         ldx     file_type       ; SYS file?
219         bne     system          ; Yes, check for startup filename
220
221         ; Store REM and cmdline in BASIC input buffer
222         lda     #$B2            ; REM token
223         bne     :++             ; Branch always
224 :       inx
225         lda     a:$0100-1,x
226 :       sta     $0200,x
227         bne     :--
228         beq     jump            ; Branch always
229
230         ; Check for startup filename support
231         ; ProDOS TechRefMan, chapter 5.1.5.1:
232         ; "$2000 is a jump instruction. $2003 and $2004 are $EE."
233 system: lda     #$4C
234         cmp     $2000
235         bne     jump
236         lda     #$EE
237         cmp     $2003
238         bne     jump
239         cmp     $2004
240         bne     jump
241
242         ; Store cmdline in startup filename buffer
243         ldx     #$01
244 :       lda     a:$0100-1,x
245         beq     :+
246         sta     $2006,x
247         inx
248         cpx     $2005           ; Buffer full?
249         bcc     :-              ; No, continue
250 :       dex
251         stx     $2006           ; Store cmdline length
252
253         ; Go for it ...
254 jump:   jmp     (data_buffer)
255
256 file_type       = * - source + target
257         .byte   $00
258
259 read_param      = * - source + target
260         .byte   $04             ; PARAM_COUNT
261 read_ref        = * - source + target
262         .byte   $00             ; REF_NUM
263 data_buffer     = * - source + target
264         .addr   $2000           ; DATA_BUFFER
265         .word   $FFFF           ; REQUEST_COUNT
266         .word   $0000           ; TRANS_COUNT
267
268 close_param     = * - source + target
269         .byte   $01             ; PARAM_COUNT
270 close_ref       = * - source + target
271         .byte   $00             ; REF_NUM
272
273         ; Quit to ProDOS dispatcher
274 quit            = * - source + target
275 error:  jsr     $BF00
276         .byte   $65             ; QUIT
277         .word   quit_param
278
279 quit_param      = * - source + target
280         .byte   $04             ; PARAM_COUNT
281         .byte   $00             ; QUIT_TYPE
282         .word   $0000           ; RESERVED
283         .byte   $00             ; RESERVED
284         .word   $0000           ; RESERVED
285
286 size            = * - source
287
288 target          = DOSWARM - size
289
290 dosvec: jmp     quit