Implement exec() for Atari XDOS.
- Adds new ENOEXEC error code, also used by Apple2 targets. - Maximum command line length is 40, incl. program name. This is an XDOS restriction. - testcode/lib/tinyshell.c has been extended to be able to run programs.
This commit is contained in:
@@ -45,7 +45,7 @@ ErrTab: .byte $01, ENOSYS ; Bad system call number
|
||||
.byte $47, EEXIST ; Duplicate filename
|
||||
.byte $48, ENOSPC ; Volume full
|
||||
.byte $49, ENOSPC ; Volume directory full
|
||||
; .byte $4A, EUNKNOWN ; Incompatible file format
|
||||
.byte $4A, ENOEXEC ; Incompatible file format
|
||||
.byte $4B, EINVAL ; Unsupported storage_type
|
||||
; .byte $4C, EUNKNOWN ; End of file encountered
|
||||
.byte $4D, ESPIPE ; Position out of range
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
;
|
||||
|
||||
.export __STARTUP__ : absolute = 1 ; Mark as startup
|
||||
.export _exit, start
|
||||
.export _exit, start, excexit, SP_save
|
||||
|
||||
.import initlib, donelib
|
||||
.import callmain, zerobss
|
||||
@@ -109,12 +109,12 @@ start:
|
||||
|
||||
; Call the module destructors. This is also the exit() entry.
|
||||
|
||||
_exit: jsr donelib ; Run module destructors
|
||||
_exit: ldx SP_save
|
||||
txs ; Restore stack pointer
|
||||
|
||||
; Restore the system stuff.
|
||||
|
||||
ldx SP_save
|
||||
txs ; Restore stack pointer
|
||||
excexit:jsr donelib ; Run module destructors; 'excexit' is called from the exec routine
|
||||
|
||||
; Restore the left margin.
|
||||
|
||||
|
||||
207
libsrc/atari/exec.s
Normal file
207
libsrc/atari/exec.s
Normal file
@@ -0,0 +1,207 @@
|
||||
;
|
||||
; 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 __do_oserror
|
||||
.import excexit ; from crt0.s
|
||||
.import SP_save ; from crt0.s
|
||||
.ifdef UCASE_FILENAME
|
||||
.importzp tmp3
|
||||
.import ucase_fn
|
||||
.import addysp
|
||||
.endif
|
||||
|
||||
.include "zeropage.inc"
|
||||
.include "errno.inc"
|
||||
.include "atari.inc"
|
||||
|
||||
CMDLINE_BUFFER = $0100 ; 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: jsr __directerrno
|
||||
lda #$FF
|
||||
tax
|
||||
rts ; return -1
|
||||
|
||||
; 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
|
||||
|
||||
; 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
|
||||
|
||||
lda tmp4 ; get IOCB index
|
||||
pha ; and save it ('excexit' calls destructors and they might destroy tmp4)
|
||||
jsr excexit
|
||||
pla
|
||||
ldx SP_save
|
||||
txs ; reset stack pointer
|
||||
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
|
||||
@@ -95,7 +95,7 @@ maptable:
|
||||
.byte EUNKNOWN ; 177 - haven't found documentation
|
||||
.byte EUNKNOWN ; 178 - haven't found documentation
|
||||
.byte EUNKNOWN ; 179 - haven't found documentation
|
||||
.byte EUNKNOWN ; 180 - not a binary file
|
||||
.byte ENOEXEC ; 180 - not a binary file
|
||||
.byte EUNKNOWN ; 181 - [MYDOS] invalid address range
|
||||
.byte EUNKNOWN ; 182 - [XDOS] invalid parameter
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ const char* const _sys_errlist[] = {
|
||||
"Illegal seek", /* ESPIPE */
|
||||
"Range error", /* ERANGE */
|
||||
"Bad file number", /* EBADF */
|
||||
"Exec format error", /* ENOEXEC */
|
||||
"Unknown OS error code", /* EUNKNOWN */
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user