]> git.sur5r.net Git - cc65/blob - libsrc/atari/exec.s
atari: split color.s into bordercolor.s and bgcolor.s
[cc65] / libsrc / atari / exec.s
1 ;
2 ; Christian Groessler, 12-Jun-2016
3 ;
4 ; int __fastcall__ exec (const char* progname, const char* cmdline);
5 ;
6 ; supports only XDOS at the moment
7
8         .export         _exec
9
10         .import         popax
11         .import         __dos_type
12         .import         findfreeiocb
13         .import         incsp2
14         .import         excexit                 ; from crt0.s
15         .import         SP_save                 ; from crt0.s
16 .ifdef  UCASE_FILENAME
17         .import         ucase_fn
18         .import         addysp
19 .endif
20
21         .include        "zeropage.inc"
22         .include        "errno.inc"
23         .include        "atari.inc"
24
25 ; area $0100 to $0128 might be in use (e.g. Hias' high speed patch)
26 CMDLINE_BUFFER          =       $0129           ; put progname + cmdline as one single string there
27 ; alternatively:
28 ;CMDLINE_BUFFER          =       $0480           ; put progname + cmdline as one single string there
29 CMDLINE_MAX             =       40+3            ; max. length of drive + progname + cmdline
30
31         .code
32
33 notsupp:lda     #ENOSYS         ; "unsupported system call"
34         .byte   $2C             ; bit opcode, eats the next 2 bytes
35 noiocb: lda     #EMFILE         ; "too many open files"
36         jsr     incsp2          ; clean up stack
37 seterr: jmp     __directerrno
38
39
40 ; entry point
41
42 _exec:
43         ; save cmdline
44         sta     ptr3
45         stx     ptr3+1
46
47         ldy     __dos_type
48         cpy     #XDOS
49         bne     notsupp
50
51         jsr     findfreeiocb
52         bne     noiocb
53
54         stx     tmp4            ; remember IOCB index
55
56         ; get program name
57         jsr     popax
58
59 .ifdef  UCASE_FILENAME
60 .ifdef  DEFAULT_DEVICE
61         ldy     #$80
62 .else
63         ldy     #$00
64 .endif
65         sty     tmp2            ; set flag for ucase_fn
66         jsr     ucase_fn
67         bcc     ucok1
68 invret: lda     #EINVAL         ; file name is too long
69         bne     seterr
70 ucok1:
71 .endif  ; defined UCASE_FILENAME
72
73 ; copy program name and arguments to CMDLINE_BUFFER
74
75         sta     ptr4            ; ptr4: pointer to program name
76         stx     ptr4+1
77         ldy     #0
78         ; TODO: check stack ptr and and use min(CMDLINE_MAX,available_stack)
79 copyp:  lda     (ptr4),y
80         beq     copypd
81         sta     CMDLINE_BUFFER,y
82         iny
83         cpy     #CMDLINE_MAX
84         bne     copyp
85
86         ; programe name too long
87         beq     invret
88
89 .ifndef  UCASE_FILENAME
90 invret: lda     #EINVAL
91         bne     seterr
92 .endif
93
94 ; file name copied, check for args
95
96 copypd: tya                     ; put Y into X (index into CMDLINE_BUFFER)
97         tax
98         lda     ptr3
99         ora     ptr3+1          ; do we have arguments?
100         beq     copycd          ; no
101         ldy     #0
102         lda     (ptr3),y        ; get first byte of cmdline parameter
103         beq     copycd          ; nothing there...
104         lda     #' '            ; add a space btw. progname and cmdline
105         bne     copyc1
106
107 ; copy args
108
109 copyc:  lda     (ptr3),y
110         beq     copycd
111         iny
112 copyc1: sta     CMDLINE_BUFFER,x
113         inx
114         cpx     #CMDLINE_MAX
115         bne     copyc
116         ; progname + arguments too long
117         beq     invret
118
119 invexe: jsr     close
120         lda     #XNTBIN
121         bne     setmerr
122
123 copycd: lda     #ATEOL
124         sta     CMDLINE_BUFFER,x
125
126 ; open the program file, read the first two bytes and compare them to $FF
127
128         ldx     tmp4            ; get IOCB index
129         lda     ptr4            ; ptr4 points to progname
130         sta     ICBAL,x
131         lda     ptr4+1
132         sta     ICBAH,x
133         lda     #OPNIN          ; open for input
134         sta     ICAX1,x
135         lda     #OPEN
136         sta     ICCOM,x
137         jsr     CIOV
138
139         tya
140
141 .ifdef  UCASE_FILENAME
142         ldy     tmp3            ; get size
143         jsr     addysp          ; free used space on the stack
144         ; the following 'bpl' depends on 'addysp' restoring A as last command before 'rts'
145 .endif  ; defined UCASE_FILENAME
146
147         bpl     openok
148         pha                     ; remember error code
149         jsr     close           ; close the IOCB (required even if open failed)
150         pla                     ; put error code back into A
151 setmerr:jmp     __mappederrno   ; update errno from OS specific error code in A
152
153 openok: lda     #>buf
154         sta     ICBAH,x         ; set buffer address
155         lda     #<buf
156         sta     ICBAL,x
157         lda     #0              ; set buffer length
158         sta     ICBLH,x
159         lda     #2
160         sta     ICBLL,x
161         lda     #GETCHR         ; iocb command code
162         sta     ICCOM,x
163         jsr     CIOV            ; read it
164         bmi     invexe          ; read operation failed, return error
165
166         lda     ICBLL,x         ; # of bytes read
167         cmp     #2
168         bne     invexe
169         lda     #$FF            ; check file format (need $FFFF at the beginning)
170         cmp     buf
171         bne     invexe
172         cmp     buf+1
173         bne     invexe
174
175         jsr     close           ; close program file
176
177 ; program file appears to be available and good
178 ; here's the point of no return
179
180         ldx     SP_save
181         txs                     ; reset stack pointer to what it was at program entry
182         lda     tmp4            ; get IOCB index
183         pha                     ; and save it ('excexit' calls destructors and they might destroy tmp4)
184         jsr     excexit         ; on atarixl this will enable the ROM again, making all high variables inaccessible
185         pla
186         tax                     ; IOCB index in X
187
188         lda     #<CMDLINE_BUFFER
189         sta     ICBAL,x         ; address
190         lda     #>CMDLINE_BUFFER
191         sta     ICBAH,x
192         lda     #0
193         sta     ICBLL,x         ; length shouldn't be random, but 0 is ok
194         sta     ICBLH,x
195         sta     ICAX1,x
196         sta     ICAX2,x
197         lda     #80             ; XDOS: run DUP command
198         sta     ICCOM,x
199         jmp     CIOV_org        ; no way to display an error message in case of failure, and we will return to DOS
200
201
202 ; close IOCB, index in X
203 .proc   close
204         lda    #CLOSE
205         sta    ICCOM,x
206         jmp    CIOV             ; close IOCB
207 .endproc
208
209         .bss
210
211 buf:    .res    2