Add CD command

This commit is contained in:
Joshua Bell 2021-04-17 09:58:22 -07:00
parent 48f8921431
commit 46b4462a9e
7 changed files with 270 additions and 20 deletions

View File

@ -5,6 +5,7 @@ LDFLAGS := --config apple2-asm.cfg
OUTDIR := out
TARGETS := $(OUTDIR)/path.BIN \
$(OUTDIR)/cd.CMD \
$(OUTDIR)/chtype.CMD $(OUTDIR)/chtime.CMD $(OUTDIR)/buzz.CMD \
$(OUTDIR)/copy.CMD $(OUTDIR)/date.CMD $(OUTDIR)/type.CMD \
$(OUTDIR)/bell.CMD $(OUTDIR)/hello.CMD $(OUTDIR)/echo.CMD $(OUTDIR)/online.CMD

View File

@ -9,7 +9,7 @@ Build with [ca65](https://cc65.github.io/doc/ca65.html)
## Instructions For Users
Installation:
* Copy files from the floppy disk image to your Apple's hard disk, in a subdirectory e.g. `/HD/CMD`
* Copy files from the floppy disk image to your Apple's hard disk, in a subdirectory e.g. `/HD/CMD`
* From BASIC.SYSTEM prompt, run: `PATH`, e.g. `-/HD/CMD/PATH`, either from `STARTUP` or manually
After installation, the usage is:
@ -40,6 +40,7 @@ Notes:
Sample commands included:
* `HELLO` - shows a short message, for testing purposes
* `ECHO` - echoes back anything following the command
* `CD` - like `PREFIX` but accepts `..`, e.g. `cd ../dir`
* `ONLINE` - lists online volumes (volume name, slot and drive)
* `COPY` - copy a single file, e.g. `copy /path/to/file,dstfile`
* `TYPE` - show file contents (TXT, BAS, or BIN/other), e.g. `type filename`

237
cd.cmd.s Normal file
View File

@ -0,0 +1,237 @@
;;; ============================================================
;;;
;;; CD - Change Directory (like PREFIX, plus .. support)
;;;
;;; Usage: CD path
;;;
;;; * path can be absolute, e.g. CD /VOL/DIR
;;; * path can be relative, e.g. CD SUBDIR/SUBDIR
;;; * segments can be .. to go up a dir, e.g. CD ../DIR
;;; * segments can be . to mean same dir, e.g. CD ./SUBDIR
;;; * with no path, echoes current PREFIX
;;;
;;; ============================================================
.include "apple2.inc"
.include "more_apple2.inc"
.include "prodos.inc"
;;; ============================================================
.org $4000
;; Follow the BI external command protocol. Although
;; the parser is not used, this allows returning
;; BI error codes.
;; Point BI's parser at the command execution routine.
lda #<execute
sta XTRNADDR
page_num2 := *+1 ; address needing updating
lda #>execute
sta XTRNADDR+1
;; Mark command as external (zero).
lda #0
sta XCNUM
;; Set accepted parameter flags
lda #0
sta PBITS
lda #0
sta PBITS+1
clc ; Success (so far)
rts1: rts ; Return to BASIC.SYSTEM
;;; ============================================================
PFXBUF := $280
tmp := $06
execute:
;; Skip command and leading spaces
ldx XLEN
inx
jsr SkipSpaces
;; Absolute?
lda INBUF,x
cmp #'/'|$80
beq abs
;; No, will need current prefix
stx tmp
jsr GetPrefix
bcs rts1
ldx tmp
;; Empty?
lda INBUF,x
cmp #$8D ; CR
bne common ; no, start processing
;; Echo the current prefix
jsr CROUT
ldx #0
: inx
lda PFXBUF,x
ora #$80
jsr COUT
cpx PFXBUF
bne :-
jsr CROUT
jsr CROUT
clc
rts
;;; --------------------------------------------------
;;; Absolute path
abs: lda #1 ; init prefix to just '/'
sta PFXBUF
lda #'/'
sta PFXBUF+1
inx ; consume leading '/'
;; fall through
;;; --------------------------------------------------
;;; Process the relative path
;;;
;;; PFXBUF has the prefix; Y holds the length
;;; X holds position in INBUF
common: ldy PFXBUF
;; Loop over segments
loop: jsr GetC
cmp #$D ; EOL?
beq done
cmp #'.' ; Maybe "." or ".." ?
beq dot
put: jsr PutC
jsr GetC
cmp #$D ; EOL?
beq done
cmp #'/' ; end of segment?
bne put
jsr PutC
bne loop ; always
dot: jsr GetC
cmp #'.' ; ".." ?
bne :+
jsr Pop ; yes, pop the last segment
jsr GetC
: cmp #$D ; EOL?
beq done ; groovy
cmp #'/' ; "./" or "../"?
beq loop ; also groovy
lda #BI_ERR_SYNTAX_ERROR
sec
rts
;;; --------------------------------------------------
;;; Try setting the new PREFIX
done: sty PFXBUF
MLI_CALL SET_PREFIX, get_set_prefix_params
bcc :+
jsr BADCALL ; Convert MLI error to BI error
: rts
;;; ============================================================
;;; Pop a segment
.proc Pop
cpy #1
beq done
: dey
lda PFXBUF,y
cmp #'/'
bne :-
done: rts
.endproc
;;; ============================================================
;;; Get next character from INBUF at X.
.proc GetC
lda INBUF,x
inx
and #$7F
rts
.endproc
;;; ============================================================
;;; Append to PFXBUF at Y. Returns non-zero.
.proc PutC
iny
sta PFXBUF,y
rts
.endproc
;;; ============================================================
;;; Skip over spaces in INBUF, advancing X; returns first non-space.
.proc SkipSpaces
repeat: lda INBUF,x
cmp #' '|$80
beq :+
rts
: inx
jmp repeat
.endproc
;;; ============================================================
;;; Leave PREFIX at PFXBUF; infers it the same way as BI if empty.
;;; Returns with Carry set on failure.
.proc GetPrefix
;; Try fetching prefix
MLI_CALL GET_PREFIX, get_set_prefix_params
lda PFXBUF
bne done
;; Use BI's current slot and drive to construct unit number
lda DEFSLT ; xxxxxSSS
asl ; xxxxSSS0
asl ; xxxSSS00
asl ; xxSSS000
asl ; xSSS0000
asl ; SSS00000
ldx DEFDRV
cpx #2 ; C=0 if 1, C=1 if 2
ror ; DSSS0000
sta unit
;; Get volume name and convert to path
MLI_CALL ON_LINE, on_line_params
bcc :+
jsr BADCALL ; sets Carry
rts
: lda PFXBUF+1
and #$0F ; mask off name_len
tax
inx ; leading and trailing '/'
inx
stx PFXBUF
lda #'/'
sta PFXBUF+1 ; leading '/'
sta PFXBUF,x ; trailing '/'
done: clc
rts
on_line_params:
.byte 2
unit: .byte 0
.addr PFXBUF+1 ; leave room to insert leading '/'
.endproc
get_set_prefix_params:
.byte 1
.addr PFXBUF

View File

@ -315,5 +315,15 @@ unit: .byte 0
done: rts
.endproc
.proc SkipSpaces
repeat: lda INBUF,x
cmp #' '|$80
beq :+
rts
: inx
jmp repeat
.endproc
cmd_length = .strlen("echo")
.assert * <= FN2BUF, error, "Too long"

View File

@ -1,31 +1,16 @@
.include "apple2.inc"
.include "more_apple2.inc"
.include "prodos.inc"
.org $4000
jsr CROUT
ldx #0
;; Skip any leading spaces
jsr SkipSpaces
;; Invoked with "-" ?
lda INBUF,x
cmp #'-'|$80
bne :+
;; Skip command and any leading spaces
ldx XLEN
inx
:
;; Skip any more leading spaces
jsr SkipSpaces
;; Skip command name (i.e. "echo")
txa
clc
adc #cmd_length
tax
;; Skip leading spaces before string to echo
jsr SkipSpaces
;; Echo string

View File

@ -18,7 +18,7 @@ add_file () {
}
add_file "out/path.BIN" "path#062000"
for file in bell echo hello online chtype chtime copy date type buzz; do
for file in bell echo hello online chtype chtime copy date type buzz cd; do
add_file "out/${file}.CMD" "${file}#F04000"
done

View File

@ -15,6 +15,7 @@ CREATE = $C0
SET_FILE_INFO = $C3
GET_FILE_INFO = $C4
ON_LINE = $C5
SET_PREFIX = $C6
GET_PREFIX = $C7
OPEN = $C8
READ = $CA
@ -140,9 +141,24 @@ RSHIMEM := $BEFB
;;; Error Codes
BI_ERR_RANGE_ERROR = 2
BI_ERR_NO_DEVICE_CONNECTED = 3
BI_ERR_WRITE_PROTECTED = 4
BI_ERR_END_OF_DATA = 5
BI_ERR_PATH_NOT_FOUND = 6
BI_ERR_VOLUME_DIR_NOT_FOUND = 7 ; Also shows as PATH NOT FOUND
BI_ERR_IO_ERROR = 8
BI_ERR_DISK_FULL = 9
BI_ERR_FILE_LOCKED = 10
BI_ERR_INVALID_PARAMETER = 11
BI_ERR_NO_BUFFERS_AVAILABLE = 12
BI_ERR_FILE_TYPE_MISMATCH = 13
BI_ERR_PROGRAM_TOO_LARGE = 14
BI_ERR_NOT_DIRECT_COMMAND = 15
BI_ERR_SYNTAX_ERROR = 16
BI_ERR_DIRECTORY_FULL = 17
BI_ERR_FILE_NOT_OPEN = 18
BI_ERR_DUPLICATE_FILE_NAME = 19
BI_ERR_FILE_BUSY = 20
BI_ERR_FILES_STILL_OPEN = 21
BI_ERR_DIRECT_COMMAND = 22