1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-27 00:29:31 +00:00
cc65/libsrc/atari/exec.s
2016-06-16 00:47:13 +02:00

212 lines
6.0 KiB
ArmAsm

;
; Christian Groessler, 12-Jun-2016
;
; int __fastcall__ exec (const char* progname, const char* cmdline);
;
; supports only XDOS at the moment
.export _exec
.import popax
.import __dos_type
.import findfreeiocb
.import incsp2
.import excexit ; from crt0.s
.import SP_save ; from crt0.s
.ifdef UCASE_FILENAME
.import ucase_fn
.import addysp
.endif
.include "zeropage.inc"
.include "errno.inc"
.include "atari.inc"
; area $0100 to $0128 might be in use (e.g. Hias' high speed patch)
CMDLINE_BUFFER = $0129 ; put progname + cmdline as one single string there
; alternatively:
;CMDLINE_BUFFER = $0480 ; put progname + cmdline as one single string there
CMDLINE_MAX = 40+3 ; max. length of drive + progname + cmdline
.code
notsupp:lda #ENOSYS ; "unsupported system call"
.byte $2C ; bit opcode, eats the next 2 bytes
noiocb: lda #EMFILE ; "too many open files"
jsr incsp2 ; clean up stack
seterr: jmp __directerrno
; entry point
_exec:
; save cmdline
sta ptr3
stx ptr3+1
ldy __dos_type
cpy #XDOS
bne notsupp
jsr findfreeiocb
bne noiocb
stx tmp4 ; remember IOCB index
; get program name
jsr popax
.ifdef UCASE_FILENAME
.ifdef DEFAULT_DEVICE
ldy #$80
.else
ldy #$00
.endif
sty tmp2 ; set flag for ucase_fn
jsr ucase_fn
bcc ucok1
invret: lda #EINVAL ; file name is too long
bne seterr
ucok1:
.endif ; defined UCASE_FILENAME
; copy program name and arguments to CMDLINE_BUFFER
sta ptr4 ; ptr4: pointer to program name
stx ptr4+1
ldy #0
; TODO: check stack ptr and and use min(CMDLINE_MAX,available_stack)
copyp: lda (ptr4),y
beq copypd
sta CMDLINE_BUFFER,y
iny
cpy #CMDLINE_MAX
bne copyp
; programe name too long
beq invret
.ifndef UCASE_FILENAME
invret: lda #EINVAL
bne seterr
.endif
; file name copied, check for args
copypd: tya ; put Y into X (index into CMDLINE_BUFFER)
tax
lda ptr3
ora ptr3+1 ; do we have arguments?
beq copycd ; no
ldy #0
lda (ptr3),y ; get first byte of cmdline parameter
beq copycd ; nothing there...
lda #' ' ; add a space btw. progname and cmdline
bne copyc1
; copy args
copyc: lda (ptr3),y
beq copycd
iny
copyc1: sta CMDLINE_BUFFER,x
inx
cpx #CMDLINE_MAX
bne copyc
; progname + arguments too long
beq invret
invexe: jsr close
lda #XNTBIN
bne setmerr
copycd: lda #ATEOL
sta CMDLINE_BUFFER,x
; open the program file, read the first two bytes and compare them to $FF
ldx tmp4 ; get IOCB index
lda ptr4 ; ptr4 points to progname
sta ICBAL,x
lda ptr4+1
sta ICBAH,x
lda #OPNIN ; open for input
sta ICAX1,x
lda #OPEN
sta ICCOM,x
jsr CIOV
tya
.ifdef UCASE_FILENAME
ldy tmp3 ; get size
jsr addysp ; free used space on the stack
; the following 'bpl' depends on 'addysp' restoring A as last command before 'rts'
.endif ; defined UCASE_FILENAME
bpl openok
pha ; remember error code
jsr close ; close the IOCB (required even if open failed)
pla ; put error code back into A
setmerr:jmp __mappederrno ; update errno from OS specific error code in A
openok: lda #>buf
sta ICBAH,x ; set buffer address
lda #<buf
sta ICBAL,x
lda #0 ; set buffer length
sta ICBLH,x
lda #2
sta ICBLL,x
lda #GETCHR ; iocb command code
sta ICCOM,x
jsr CIOV ; read it
bmi invexe ; read operation failed, return error
lda ICBLL,x ; # of bytes read
cmp #2
bne invexe
lda #$FF ; check file format (need $FFFF at the beginning)
cmp buf
bne invexe
cmp buf+1
bne invexe
jsr close ; close program file
; program file appears to be available and good
; here's the point of no return
ldx SP_save
txs ; reset stack pointer to what it was at program entry
lda tmp4 ; get IOCB index
pha ; and save it ('excexit' calls destructors and they might destroy tmp4)
jsr excexit ; on atarixl this will enable the ROM again, making all high variables inaccessible
pla
tax ; IOCB index in X
lda #<CMDLINE_BUFFER
sta ICBAL,x ; address
lda #>CMDLINE_BUFFER
sta ICBAH,x
lda #0
sta ICBLL,x ; length shouldn't be random, but 0 is ok
sta ICBLH,x
sta ICAX1,x
sta ICAX2,x
lda #80 ; XDOS: run DUP command
sta ICCOM,x
jmp CIOV_org ; no way to display an error message in case of failure, and we will return to DOS
; close IOCB, index in X
.proc close
lda #CLOSE
sta ICCOM,x
jmp CIOV ; close IOCB
.endproc
.bss
buf: .res 2