chtype/chtype.s

296 lines
8.1 KiB
ArmAsm
Raw Permalink Normal View History

2019-01-01 04:18:35 +00:00
;;; ============================================================
;;;
;;; CHTYPE - File type changing command for ProDOS-8
;;;
;;; Install:
;;; -CHTYPE (from BASIC.SYSTEM prompt)
;;; Usage:
;;; CHTYPE filename[,Ttype][,Aaux][,S#][,D#]
2019-01-01 04:18:35 +00:00
;;;
;;; * filename can be relative or absolute path
;;; * specify T$nn to set file type
;;; * specify A$nnnn to set aux type info
2019-01-01 04:18:35 +00:00
;;; * type can be BIN, SYS, TXT (etc) or $nn
;;; * with neither T nor A option, prints current values
2019-01-01 04:18:35 +00:00
;;;
;;; Build with: ca65 - https://cc65.github.io/doc/ca65.html
2018-12-31 20:21:38 +00:00
;;;
2018-12-31 23:49:26 +00:00
;;; ============================================================
2018-12-31 20:27:07 +00:00
2019-01-01 04:18:35 +00:00
.org $2000
2018-12-31 20:27:07 +00:00
2018-12-31 23:49:26 +00:00
;;; ============================================================
2019-01-01 04:18:35 +00:00
INBUF := $200 ; GETLN input buffer
2018-12-31 23:49:26 +00:00
;;; ============================================================
;;; Monitor ROM routines
CROUT := $FD8E
PRBYTE := $FDDA
COUT := $FDED
2019-01-01 04:18:35 +00:00
;;; ============================================================
;;; ProDOS MLI / Global Page
2018-12-31 23:49:26 +00:00
2019-01-01 04:18:35 +00:00
SET_FILE_INFO = $C3
GET_FILE_INFO = $C4
2018-12-31 23:49:26 +00:00
2019-01-01 04:18:35 +00:00
DATE := $BF90
2018-12-31 23:49:26 +00:00
2019-01-01 04:18:35 +00:00
;;; ============================================================
;;; BASIC.SYSTEM Global Page
EXTRNCMD := $BE06 ; External command jmp vector
ERROUT := $BE09 ; Error routine jmp vector
XTRNADDR := $BE50 ; Ext cmd implementation addr
XLEN := $BE52 ; Length of command string minus 1
XCNUM := $BE53 ; Command number (ext cmd = 0).
PBITS := $BE54 ; Command parameter bits
FBITS := $BE56 ; Found parameter bits
.enum PBitsFlags
;; PBITS
PFIX = $80 ; Prefix needs fetching
SLOT = $40 ; No parameters to be processed
RRUN = $20 ; Command only valid during program
FNOPT = $10 ; Filename is optional
CRFLG = $08 ; CREATE allowed
T = $04 ; File type
FN2 = $02 ; Filename '2' for RENAME
FN1 = $01 ; Filename expected
;; PBITS+1
2019-01-02 18:28:25 +00:00
AD = $80 ; Address
2019-01-01 04:18:35 +00:00
B = $40 ; Byte
E = $20 ; End address
L = $10 ; Length
LINE = $08 ; '@' line number
SD = $04 ; Slot and drive numbers
F = $02 ; Field
R = $01 ; Record
;; Setting SD in PBITS+1 enables desired automatic behavior: if
;; a relative path is given, an appropriate prefix is computed,
;; using S# and D# options if supplied. Without this, absolute
;; paths must be used if no prefix is set.
.endenum
VADDR := $BE58 ; Address parameter
VSLOT := $BE61 ; Slot parameter
VTYPE := $BE6A ; Type parameter
VPATH1 := $BE6C ; Pathname buffer
GOSYSTEM := $BE70 ; Use instead of MLI
SSGINFO := $BEB4 ; Get/Set Info Parameter block
FIFILID := $BEB8 ; (set size to set=7 or get=$A)
FIAUXID := $BEB9
FIMDATE := $BEBE
2019-01-01 04:47:35 +00:00
GETBUFR := $BEF5
2019-01-01 04:18:35 +00:00
;;; ============================================================
;; Save previous external command address
2018-12-31 20:27:07 +00:00
lda EXTRNCMD+1
2019-01-01 04:18:35 +00:00
sta next_command
2018-12-31 20:27:07 +00:00
lda EXTRNCMD+2
2019-01-01 04:18:35 +00:00
sta next_command+1
2019-01-01 04:47:35 +00:00
;; Request a 1-page buffer
lda #1
jsr GETBUFR
bcc :+
lda #$C ; NO BUFFERS AVAILABLE
rts
:
;; A = MSB of new page - update absolute addresses
;; (aligned to page boundary so only MSB changes)
sta page_num1
sta page_num2
sta page_num3
;; Install new address in external command address
2019-01-01 04:18:35 +00:00
sta EXTRNCMD+2
2019-01-01 04:47:35 +00:00
lda #0
sta EXTRNCMD+1
;; Relocate
ldx #0
: lda handler,x
page_num3 := *+2
sta $2100,x ; self-modified
inx
bne :-
;; Complete
2018-12-31 23:49:26 +00:00
rts
2019-01-01 04:18:35 +00:00
;;; ============================================================
;;; Command Handler
;;; ============================================================
2019-01-01 04:47:35 +00:00
;; Align handler to page boundary for easier
;; relocation
.res $2100 - *, 0
.proc handler
2019-01-01 04:18:35 +00:00
;; Check for this command, character by character.
ldx #0
nxtchr: lda INBUF,x
2018-12-31 23:49:26 +00:00
2019-01-01 04:18:35 +00:00
and #$7F ; Convert to ASCII
cmp #'a' ; Convert to upper-case
2018-12-31 23:49:26 +00:00
bcc :+
cmp #'z'+1
bcs :+
and #$DF
2019-01-01 04:47:35 +00:00
page_num1 := *+2 ; address needing updating
: cmp command_string,x
2019-01-01 04:18:35 +00:00
bne not_ours
inx
2019-01-01 04:47:35 +00:00
cpx #command_length
2019-01-01 04:18:35 +00:00
bne nxtchr
;; A match - indicate end of command string for BI's parser.
2019-01-01 04:47:35 +00:00
lda #command_length-1
2019-01-01 04:18:35 +00:00
sta XLEN
;; Point BI's parser at the command execution routine.
lda #<execute
sta XTRNADDR
2019-01-01 04:47:35 +00:00
page_num2 := *+1 ; address needing updating
2019-01-01 04:18:35 +00:00
lda #>execute
2018-12-31 20:27:07 +00:00
sta XTRNADDR+1
2018-12-31 23:49:26 +00:00
2019-01-01 04:18:35 +00:00
;; Mark command as external (zero).
lda #0
sta XCNUM
;; Set accepted parameter flags (Name, Type, Address)
lda #PBitsFlags::T | PBitsFlags::FN1 ; Filename and Type
2018-12-31 23:49:26 +00:00
sta PBITS
2019-01-01 04:18:35 +00:00
lda #PBitsFlags::AD | PBitsFlags::SD ; Address, Slot & Drive handling
sta PBITS+1
clc ; Success (so far)
rts ; Return to BASIC.SYSTEM
2018-12-31 23:49:26 +00:00
;;; ============================================================
2019-01-01 04:18:35 +00:00
not_ours:
sec ; Signal failure...
next_command := *+1
jmp $ffff ; Execute next command in chain
2018-12-31 23:49:26 +00:00
;;; ============================================================
2018-12-31 20:27:07 +00:00
execute:
2019-01-01 04:18:35 +00:00
;; Verify required arguments
2018-12-31 23:49:26 +00:00
lda FBITS
2019-01-01 04:18:35 +00:00
and #PBitsFlags::FN1 ; Filename?
2018-12-31 23:49:26 +00:00
bne :+
lda #$10 ; SYNTAX ERROR
sec
2019-01-01 04:18:35 +00:00
rts1: rts
2018-12-31 23:49:26 +00:00
:
2019-01-01 04:18:35 +00:00
;;; --------------------------------------------------
2018-12-31 23:49:26 +00:00
2019-01-01 04:18:35 +00:00
;; Get the existing file info
2018-12-31 23:49:26 +00:00
lda #$A
sta SSGINFO
2019-01-01 04:18:35 +00:00
lda #GET_FILE_INFO
2018-12-31 23:49:26 +00:00
jsr GOSYSTEM
bcs rts1
2019-01-01 04:18:35 +00:00
;;; --------------------------------------------------
;; Apply options
ldy #0 ; count number of options
2019-01-01 04:18:35 +00:00
;; Apply optional Type argument as new file type
lda FBITS
and #PBitsFlags::T ; Type set?
beq :+
iny
2018-12-31 23:49:26 +00:00
lda VTYPE
sta FIFILID
:
2018-12-31 23:49:26 +00:00
2019-01-01 04:18:35 +00:00
;; Apply optional Address argument as new aux type
lda FBITS+1
and #PBitsFlags::AD ; Address set?
2019-01-01 04:18:35 +00:00
beq :+
iny
2019-01-01 04:18:35 +00:00
lda VADDR
sta FIAUXID
lda VADDR+1
sta FIAUXID+1
:
;; If no options were used, show current details instead.
cpy #0
beq show
2019-01-01 04:18:35 +00:00
;; Apply current date/time
ldx #3
: lda DATE,x
sta FIMDATE,x
dex
bpl :-
;; Set new file info
lda #$7
sta SSGINFO
2019-01-01 04:18:35 +00:00
lda #SET_FILE_INFO
jmp GOSYSTEM
2018-12-31 23:49:26 +00:00
;;; --------------------------------------------------
show:
lda #'T'|$80
jsr COUT
lda #'='|$80
jsr COUT
lda #'$'|$80
jsr COUT
2019-03-03 01:51:07 +00:00
lda FIFILID
jsr PRBYTE
jsr CROUT
lda #'A'|$80
jsr COUT
lda #'='|$80
jsr COUT
lda #'$'|$80
jsr COUT
2019-03-03 01:51:07 +00:00
lda FIAUXID+1
jsr PRBYTE
2019-03-03 01:51:07 +00:00
lda FIAUXID
jsr PRBYTE
jsr CROUT
clc
rts
2018-12-31 23:49:26 +00:00
;;; ============================================================
;;; Data
2019-01-01 04:47:35 +00:00
command_string:
.byte "CHTYPE" ; Command string
command_length = *-command_string
.endproc
.assert .sizeof(handler) <= $100, error, "Must fit on one page"
page_num1 := handler::page_num1
page_num2 := handler::page_num2
next_command := handler::next_command