]> git.sur5r.net Git - cc65/blob - libsrc/apple2/exec.s
Behave more like BASIC.SYSTEM and allow for argv[0].
[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         ; Get and push name
27         jsr     popax
28         jsr     pushname
29         bne     oserr
30
31         ; ProDOS TechRefMan, chapter 5.1.5.1:
32         ; "The complete or partial pathname of the system program
33         ;  is stored at $280, starting with a length byte."
34         ; In fact BASIC.SYSTEM does the same for BLOAD and BRUN of
35         ; binary programs so we should do the same too in any case
36         ; especially as _we_ rely on it in mainargs.s for argv[0].
37         ldy     #$00
38         lda     (sp),y
39         tay
40 :       lda     (sp),y
41         sta     $0280,y
42         dey
43         bpl     :-
44
45         ; Set pushed name
46         lda     sp
47         ldx     sp+1
48         sta     mliparam + MLI::INFO::PATHNAME
49         stx     mliparam + MLI::INFO::PATHNAME+1
50
51         ; Get file_type and aux_type
52         lda     #GET_INFO_CALL
53         ldx     #GET_INFO_COUNT
54         jsr     callmli
55         bcs     oserr
56
57         ; If we get here the program file at least exists so we copy
58         ; the loader stub right now and patch it later to set params
59         ldx     #size - 1
60 :       lda     source,x
61         sta     target,x
62         dex
63         bpl     :-
64
65         ; Check program file type
66         lda     mliparam + MLI::INFO::FILE_TYPE
67         cmp     #$FF            ; SYS file?
68         bne     binary          ; No, check for BIN file
69
70         ; SYS programs replace BASIC.SYSTEM so set in the ProDOS system bit map
71         ; protection for pages $80 - $BF just in case BASIC.SYSTEM is there now
72         ldx     #$0F            ; Start with protection for pages $B8 - $BF
73         lda     #%00000001      ; Protect only system global page
74 :       sta     $BF60,x         ; Set protection for 8 pages
75         lda     #$00            ; Protect no page
76         dex
77         bpl     :-
78         bmi     prodos          ; Branch always
79
80 binary: cmp     #$06            ; BIN file?
81         bne     typerr          ; No, wrong file type
82
83         ; Set BIN program load addr
84         lda     mliparam + MLI::INFO::AUX_TYPE
85         ldx     mliparam + MLI::INFO::AUX_TYPE+1
86         sta     data_buffer
87         stx     data_buffer+1
88
89         ; Check ProDOS system bit map for presence of BASIC.SYSTEM
90         lda     $BF6F           ; Protection for pages $B8 - $BF
91         cmp     #%00000001      ; Exactly system global page is protected
92         beq     setvec
93
94         ; Get highest available mem addr from BASIC.SYSTEM
95         ldx     HIMEM+1         ; High byte
96         bne     setbuf          ; Branch always
97
98         ; BIN programs are supposed to quit through one of the two DOS
99         ; vectors so we set up those to point to the ProDOS dispatcher
100 setvec: ldx     #$03 - 1        ; Size of JMP opcode
101 :       lda     dosvec,x
102         sta     DOSWARM,x       ; DOS warm start
103         sta     DOSWARM + 3,x   ; DOS cold start
104         dex
105         bpl     :-
106
107         ; No BASIC.SYSTEM so use addr of ProDOS system global page
108 prodos: ldx     #>$BF00         ; High byte
109
110         ; The I/O buffer needs to be page aligned
111 setbuf: lda     #$00            ; Low byte
112
113         ; The I/O buffer needs four pages
114         dex
115         dex
116         dex
117         dex
118         
119         ; Set I/O buffer
120         sta     mliparam + MLI::OPEN::IO_BUFFER
121         stx     mliparam + MLI::OPEN::IO_BUFFER+1
122
123         ; PATHNAME already set
124         .assert MLI::OPEN::PATHNAME = MLI::INFO::PATHNAME, error
125
126         ; Lower file level to avoid program file
127         ; being closed by C libary shutdown code
128         ldx     LEVEL
129         stx     level
130         beq     :+
131         dec     LEVEL
132         
133         ; Open file
134 :       lda     #OPEN_CALL
135         ldx     #OPEN_COUNT
136         jsr     callmli
137
138         ; Restore file level
139         ldx     level
140         stx     LEVEL
141         bcc     :+
142         jmp     oserr
143
144         ; Get and save fd
145 :       lda     mliparam + MLI::OPEN::REF_NUM
146         sta     read_ref
147         sta     close_ref
148
149         .ifdef  __APPLE2ENH__
150         ; Calling the 80 column firmware needs the ROM switched
151         ; in, otherwise it copies the F8 ROM to the LC (@ $CEF4)
152         bit     $C082
153
154         ; ProDOS TechRefMan, chapter 5.3.1.3:
155         ; "80-column text cards -- and other Apple IIe features -- can
156         ;  be turned off using the following sequence of instructions:"
157         lda     #$15
158         jsr     $C300
159
160         ; Switch in LC bank 2 for R/O
161         bit     $C080
162         .endif
163
164         ; Call loader stub after C libary shutdown
165         lda     #<target
166         ldx     #>target
167         sta     done+1
168         stx     done+2
169
170         ; Initiate C libary shutdown
171         jmp     _exit
172
173         .bss
174
175 level : .res    1
176
177         .rodata
178
179         ; Read whole program file
180 source: jsr     $BF00
181         .byte   READ_CALL
182         .word   read_param
183         bcs     :+
184
185         ; Close program file
186         jsr     $BF00
187         .byte   CLOSE_CALL
188         .word   close_param
189         bcs     :+
190
191         ; Go for it ...
192         jmp     (data_buffer)
193
194 read_param      = * - source + target
195         .byte   $04             ; PARAM_COUNT
196 read_ref        = * - source + target
197         .byte   $00             ; REF_NUM
198 data_buffer     = * - source + target
199         .addr   $2000           ; DATA_BUFFER
200         .word   $FFFF           ; REQUEST_COUNT
201         .word   $0000           ; TRANS_COUNT
202
203 close_param     = * - source + target
204         .byte   $01             ; PARAM_COUNT
205 close_ref       = * - source + target
206         .byte   $00             ; REF_NUM
207
208         ; Quit to ProDOS dispatcher
209 quit            = * - source + target
210 :       jsr     $BF00
211         .byte   $65             ; QUIT
212         .word   quit_param
213
214 quit_param      = * - source + target
215         .byte   $04             ; PARAM_COUNT
216         .byte   $00             ; QUIT_TYPE
217         .word   $0000           ; RESERVED
218         .byte   $00             ; RESERVED
219         .word   $0000           ; RESERVED
220
221 size            = * - source
222
223 target          = DOSWARM - size
224
225 dosvec: jmp     quit