mirror of https://github.com/gungwald/copy.git
Added online impl
This commit is contained in:
parent
a63dc4abee
commit
9297b9687f
|
@ -1,3 +1,6 @@
|
|||
# Vim swap files
|
||||
*.swp
|
||||
|
||||
# Prerequisites
|
||||
*.d
|
||||
|
||||
|
|
58
Makefile
58
Makefile
|
@ -1,44 +1,30 @@
|
|||
# Builds copy command
|
||||
|
||||
# Requirements:
|
||||
# 1. Gmake must be used.
|
||||
# 2. The cc65 compiler must be properly setup.
|
||||
|
||||
ifndef CC65_TARGET
|
||||
CC65_TARGET:=apple2enh
|
||||
# Compiles with https://www.brutaldeluxe.fr/products/crossdevtools/merlin/
|
||||
#
|
||||
ifeq ($(OS),Windows_NT)
|
||||
MERLIN_DIR=C:/opt/Merlin32_v1.0
|
||||
MERLIN_LIB=$(MERLIN_DIR)/Library
|
||||
MERLIN=$(MERLIN_DIR)/Windows/Merlin32
|
||||
RM=del /s
|
||||
else
|
||||
MERLIN_DIR=$(HOME)/opt/Merlin32_v1.0
|
||||
MERLIN_LIB=$(MERLIN_DIR)/Library
|
||||
MERLIN=$(MERLIN_DIR)/Linux64/Merlin32
|
||||
RM=rm -f
|
||||
endif
|
||||
|
||||
CC=cl65
|
||||
CFLAGS=-O -t $(CC65_TARGET) -DTRACE
|
||||
LDFLAGS=-t $(CC65_TARGET)
|
||||
PGM=copy
|
||||
DISK_VOL=$(PGM)
|
||||
DISK=$(DISK_VOL).dsk
|
||||
AC=java -jar AppleCommander-ac-1.4.0.jar
|
||||
SYS_LOAD_ADDR=0x2000
|
||||
BIN_LOAD_ADDR=0x0803
|
||||
BASIC_AUX_TYPE=0x0801
|
||||
READ_TIME_LOAD_ADDR=0x0260
|
||||
MKDISK=$(AC) -pro140 $(DISK) $(DISK_VOL)
|
||||
SRC=copy.s
|
||||
PGM=copy
|
||||
VOL=$(PGM)
|
||||
DSK=$(PGM).dsk
|
||||
|
||||
########################################
|
||||
$(DSK): $(PGM)
|
||||
$(AC) -pro140 $(DSK) $(VOL)
|
||||
$(AC) -p $(DSK) $(PGM) SYS < $(PGM)
|
||||
|
||||
all: $(DISK)
|
||||
|
||||
$(DISK): $(PGM)
|
||||
$(RM) $(DISK)
|
||||
$(AC) -pro140 $(DISK) $(DISK_VOL)
|
||||
$(AC) -as $(DISK) $(PGM) BIN < $(PGM)
|
||||
|
||||
$(PGM): online.o $(PGM).o
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
$(PGM).o: $(PGM).c
|
||||
$(CC) $(CFLAGS) $^
|
||||
|
||||
online.o: online.c
|
||||
$(CC) $(CFLAGS) $^
|
||||
$(PGM): $(SRC)
|
||||
$(MERLIN) $(MERLIN_LIB) $(SRC)
|
||||
|
||||
clean:
|
||||
$(RM) *.o $(PGM) $(DISK)
|
||||
$(RM) $(DSK) $(PGM)
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
# Builds online
|
||||
|
||||
# Requirements:
|
||||
# 1. Gmake must be used.
|
||||
# 2. The cc65 compiler must be properly setup.
|
||||
|
||||
ifndef CC65_TARGET
|
||||
CC65_TARGET:=apple2enh
|
||||
endif
|
||||
|
||||
CC=cl65
|
||||
CFLAGS=-O -t $(CC65_TARGET) -DTRACE
|
||||
# The -S $6000 makes the start address $6000 so that both hi-res
|
||||
# pages are available.
|
||||
LDFLAGS=-t $(CC65_TARGET) -u __EXEHDR__ --start-addr 0x6000
|
||||
PGM=online
|
||||
DISK_VOL=$(PGM)
|
||||
DISK=$(DISK_VOL).dsk
|
||||
BASIC_AUX_TYPE=0x0801
|
||||
READ_TIME_LOAD_ADDR=0x0260
|
||||
AC=java -jar AppleCommander-ac-1.4.0.jar
|
||||
SYS_LOAD_ADDR=0x2000
|
||||
BIN_LOAD_ADDR=0x0803
|
||||
|
||||
########################################
|
||||
|
||||
all: $(DISK)
|
||||
|
||||
$(DISK): $(PGM)
|
||||
$(RM) $(DISK)
|
||||
$(AC) -pro140 $(DISK) $(DISK_VOL)
|
||||
$(AC) -as $(DISK) $(PGM) BIN < $(PGM)
|
||||
|
||||
$(PGM): $(PGM).o
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
$(PGM).o: $(PGM).c
|
||||
$(CC) $(CFLAGS) $(PGM).c
|
||||
|
||||
clean:
|
||||
$(RM) *.o $(PGM) $(DISK)
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
********************************
|
||||
* *
|
||||
* COPY - COPIES FILES *
|
||||
* *
|
||||
* AUTHOR: BILL CHATFIELD *
|
||||
* LICENSE: GPL2 *
|
||||
* *
|
||||
********************************
|
||||
|
||||
org $2000
|
||||
dsk copy
|
||||
typ $ff ;System type
|
||||
|
||||
********************************
|
||||
* *
|
||||
* CONSTANTS *
|
||||
* *
|
||||
********************************
|
||||
|
||||
IN equ $0200
|
||||
RDKEY equ $FD0C ;Reads 1 character
|
||||
GETLN equ $fd6a
|
||||
GETLN1 equ $fd6f ;Get line, no prompt
|
||||
CROUT equ $FD8E ;Output carriage return
|
||||
COUT equ $FDED ;Output a character
|
||||
PRBYTE equ $FDDA ;Print error message
|
||||
BELL equ $FF3A ;Subroutine to beep
|
||||
PRODOS_MLI equ $bf00 ;Address for MLI subroutine entry point
|
||||
SET_FILE_INFO equ $c3 ;Code for system call
|
||||
GET_FILE_INFO equ $c4 ;Code for system call
|
||||
ON_LINE equ $c5 ;Id for ON_LINE MLI system call
|
||||
|
||||
********************************
|
||||
* *
|
||||
* puts *
|
||||
* *
|
||||
********************************
|
||||
|
||||
puts mac
|
||||
tya ;Preserve y
|
||||
pha
|
||||
ldy #0 ;Prepare loop index
|
||||
]nextchar lda ]1,y ;Load a character
|
||||
cmp #0 ;Check for end of string
|
||||
beq finish
|
||||
jsr COUT
|
||||
iny
|
||||
jmp ]nextchar
|
||||
finish pla ;Restore y
|
||||
tay
|
||||
<<<
|
||||
|
||||
********************************
|
||||
* *
|
||||
* movb - Move byte *
|
||||
* *
|
||||
********************************
|
||||
|
||||
movb mac
|
||||
lda ]2
|
||||
sta ]1
|
||||
<<<
|
||||
|
||||
********************************
|
||||
* *
|
||||
* mova - Move addrs *
|
||||
* *
|
||||
********************************
|
||||
|
||||
mova mac
|
||||
lda src
|
||||
sta dest
|
||||
lda src+1
|
||||
sta dest+1
|
||||
<<<
|
||||
|
||||
********************************
|
||||
* *
|
||||
* Main *
|
||||
* *
|
||||
********************************
|
||||
|
||||
main
|
||||
|
||||
; Read in source file name and store it in srcFile
|
||||
|
||||
getSource puts srcPrompt
|
||||
jsr GETLN1
|
||||
cpx #64
|
||||
bpl getSource
|
||||
|
||||
stx srcFileLength
|
||||
ldx #0
|
||||
srcChar lda IN,x
|
||||
sta srcFileChars,x
|
||||
inx
|
||||
cpx srcFileLength
|
||||
bmi srcChar
|
||||
|
||||
; Set fiParamCount parameter
|
||||
|
||||
lda #$a
|
||||
sta fiParamCount
|
||||
|
||||
; Set fiPathName parameter
|
||||
|
||||
lda #<srcFile
|
||||
sta fiPathName
|
||||
lda #>srcFile
|
||||
sta fiPathName+1
|
||||
|
||||
jsr PRODOS_MLI ;Call MLI subroutine
|
||||
db GET_FILE_INFO ;Identify the system call
|
||||
da fileInfo ;Address of system call args
|
||||
beq cont1 ;Returns 0 on success
|
||||
jsr handleError
|
||||
cont1
|
||||
|
||||
; Read in destination file name and store it in dstFile
|
||||
|
||||
getDest puts dstPrompt
|
||||
jsr GETLN1
|
||||
cpx #64
|
||||
bpl getDest
|
||||
|
||||
stx dstFileLength
|
||||
ldx #0
|
||||
dstChar lda IN,x
|
||||
sta dstFileChars,x
|
||||
inx
|
||||
cpx dstFileLength
|
||||
bmi dstChar
|
||||
|
||||
rts
|
||||
|
||||
********************************
|
||||
* *
|
||||
* Data *
|
||||
* *
|
||||
********************************
|
||||
|
||||
srcPrompt asc "File to copy: ",00
|
||||
srcFile
|
||||
srcFileLength db 0 ;Length byte
|
||||
srcFileChars ds 64 ;Characters of srcFile
|
||||
|
||||
dstFile
|
||||
dstFileLength db 0 ;Length byte
|
||||
dstFileChars ds 64 ;Characters of dstFile
|
||||
|
||||
onlineVols ds 256 ;Space for 16 disk vol records
|
||||
|
||||
onlineArgs
|
||||
olParamCount db 2 ;Parameter count
|
||||
olUnitNumber db 0 ;Unit number, 0=all
|
||||
olBufferAddr da onlineVols ;Address of output buffer
|
||||
|
||||
fileInfo
|
||||
fiParamCount db 0
|
||||
fiPathName da 0
|
||||
fiAccess db 0
|
||||
fiFileType db 0
|
||||
fiAuxType dw 0
|
||||
fiStorageType db 0
|
||||
fiBlocksUsed dw 0
|
||||
fiModDate dw 0
|
||||
fiModTime dw 0
|
||||
fiCreateDate dw 0
|
||||
fiCreateTime dw 0
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
|
||||
ENOERR equ $00
|
||||
EBADCALLNUM equ $01
|
||||
EBADPARMCNT equ $04
|
||||
EINTRTBLFULL equ $25
|
||||
EIO equ $27
|
||||
ENODEV equ $28
|
||||
EROFS equ $b2
|
||||
EDISKSWITCHED equ $2e
|
||||
EINVALIDPATH equ $40
|
||||
EMAXFILES equ $42
|
||||
EINVALIDREF equ $43
|
||||
EDIRNOTFOUND equ $44
|
||||
EVOLNOTFOUND equ $45
|
||||
ENOENT equ $46
|
||||
EDUPFILENAME equ $47
|
||||
EVOLFULL equ $48
|
||||
EVOLDIRFULL equ $49
|
||||
EFILEFORMAT equ $4a
|
||||
ESTRGTYPE equ $4b
|
||||
EEOF equ $4c
|
||||
EOUTOFRANGE equ $4d
|
||||
EFILELOCKED equ $4e
|
||||
EFILEISOPEN equ $50
|
||||
EDAMAGEDDIR equ $51
|
||||
ENOTPRODOS equ $52
|
||||
EBADPARAM equ $53
|
||||
EVCBTBLFULL equ $55
|
||||
EBADADDR equ $56
|
||||
EDUPVOL equ $57
|
||||
EDAMAGEDFILE equ $5a
|
||||
|
||||
handleError
|
||||
sta errorCode
|
||||
ldx #0
|
||||
ldy #0
|
||||
nextCode
|
||||
lda errorCodes,x
|
||||
cmp errorCode
|
||||
beq foundCode
|
||||
inx
|
||||
iny
|
||||
iny
|
||||
cpy errorCodeCount
|
||||
bmi nextCode
|
||||
unknownCode
|
||||
puts errorLabel
|
||||
lda errorCode
|
||||
jsr PRBYTE
|
||||
jsr CROUT
|
||||
rts
|
||||
foundCode
|
||||
lda errorMessages,y
|
||||
sta errorMessage
|
||||
iny
|
||||
lda errorMessage,y
|
||||
sta errorMessage+1
|
||||
puts (errorMessage)
|
||||
rts
|
||||
|
||||
errorCode db 0
|
||||
errorMessage da 0
|
||||
errorLabel asc "Error ",00
|
||||
|
||||
EMNOERR ASC "No error",00 ;$00
|
||||
EMBADCALLNUM ASC "Bad system call number",00 ;$01
|
||||
EMBADPARMCNT ASC "Bad system call parameter count",00 ;$04
|
||||
EMINTRTBLFULL ASC "Interrupt table full",00 ;$25
|
||||
EMIO ASC "I/O error",00 ;$27
|
||||
EMNODEV ASC "No device connected",00 ;$28
|
||||
EMROFS ASC "Disk write protected",00 ;$b2
|
||||
EMDISKSWITCHED ASC "Disk switched",00 ;$2e
|
||||
EMINVALIDPATH ASC "Invalid pathname",00 ;$40
|
||||
EMMAXFILES ASC "Maximum number of files open",00 ;$42
|
||||
EMINVALIDREF ASC "Invalid reference number",00 ;$43
|
||||
EMDIRNOTFOUND ASC "Directory not found",00 ;$44
|
||||
EMVOLNOTFOUND ASC "Volume not found",00 ;$45
|
||||
EMNOENT ASC "File not found",00 ;$46
|
||||
EMDUPFILENAME ASC "Duplicate filename",00 ;$47
|
||||
EMVOLFULL ASC "Volume full",00 ;$48
|
||||
EMVOLDIRFULL ASC "Volume directory full",00 ;$49
|
||||
EMFILEFORMAT ASC "Incompatible file format",00 ;$4a
|
||||
EMSTRGTYPE ASC "Unsupported storage_type",00 ;$4b
|
||||
EMEOF ASC "End of file encountered",00 ;$4c
|
||||
EMOUTOFRANGE ASC "Position out of range",00 ;$4d
|
||||
EMFILELOCKED ASC "File access error or file locked",00 ;$4e
|
||||
EMFILEISOPEN ASC "File is open",00 ;$50
|
||||
EMDAMAGEDDIR ASC "Directory structure damaged",00 ;$51
|
||||
EMNOTPRODOS ASC "Not a ProDOS volume",00 ;$52
|
||||
EMBADPARAM ASC "Invalid system call parameter",00 ;$53
|
||||
EMVCBTBLFULL ASC "Volume Control Block table full",00 ;$55
|
||||
EMBADADDR ASC "Bad buffer address",00 ;$56
|
||||
EMDUPVOL ASC "Duplicate volume",00 ;$57
|
||||
EMDAMAGEDFILE ASC "File structure damaged",00 ;$5a
|
||||
|
||||
errorCodes
|
||||
DB ENOERR
|
||||
DB EBADCALLNUM
|
||||
db EBADPARMCNT
|
||||
db EINTRTBLFULL
|
||||
db EIO
|
||||
db ENODEV
|
||||
db EROFS
|
||||
db EDISKSWITCHED
|
||||
db EINVALIDPATH
|
||||
db EMAXFILES
|
||||
db EINVALIDREF
|
||||
db EDIRNOTFOUND
|
||||
db EVOLNOTFOUND
|
||||
db ENOENT
|
||||
db EDUPFILENAME
|
||||
db EVOLFULL
|
||||
db EVOLDIRFULL
|
||||
db EFILEFORMAT
|
||||
db ESTRGTYPE
|
||||
db EEOF
|
||||
db EOUTOFRANGE
|
||||
db EFILELOCKED
|
||||
db EFILEISOPEN
|
||||
db EDAMAGEDDIR
|
||||
db ENOTPRODOS
|
||||
db EBADPARAM
|
||||
db EVCBTBLFULL
|
||||
db EBADADDR
|
||||
db EDUPVOL
|
||||
db EDAMAGEDFILE
|
||||
errorCodeCount
|
||||
db errorCodeCount - errorCodes
|
||||
|
||||
errorMessages
|
||||
DA EMNOERR
|
||||
DA EMBADCALLNUM
|
||||
da EMBADPARMCNT
|
||||
da EMINTRTBLFULL
|
||||
da EMIO
|
||||
da EMNODEV
|
||||
da EMROFS
|
||||
da EMDISKSWITCHED
|
||||
da EMINVALIDPATH
|
||||
da EMMAXFILES
|
||||
da EMINVALIDREF
|
||||
da EMDIRNOTFOUND
|
||||
da EMVOLNOTFOUND
|
||||
da EMNOENT
|
||||
da EMDUPFILENAME
|
||||
da EMVOLFULL
|
||||
da EMVOLDIRFULL
|
||||
da EMFILEFORMAT
|
||||
da EMSTRGTYPE
|
||||
da EMEOF
|
||||
da EMOUTOFRANGE
|
||||
da EMFILELOCKED
|
||||
da EMFILEISOPEN
|
||||
da EMDAMAGEDDIR
|
||||
da EMNOTPRODOS
|
||||
da EMBADPARAM
|
||||
da EMVCBTBLFULL
|
||||
da EMBADADDR
|
||||
da EMDUPVOL
|
||||
da EMDAMAGEDFILE
|
|
@ -0,0 +1,52 @@
|
|||
# Builds copy command
|
||||
|
||||
# Requirements:
|
||||
# 1. Gmake must be used.
|
||||
# 2. The cc65 compiler must be properly setup.
|
||||
|
||||
ifndef CC65_TARGET
|
||||
CC65_TARGET:=apple2enh
|
||||
endif
|
||||
|
||||
CC=cl65
|
||||
CFLAGS=-O -t $(CC65_TARGET) -DTRACE
|
||||
LDFLAGS=-t $(CC65_TARGET)
|
||||
PGM=copy
|
||||
DISK_VOL=$(PGM)
|
||||
DISK=$(DISK_VOL).dsk
|
||||
AC=java -jar AppleCommander-ac-1.4.0.jar
|
||||
SYS_LOAD_ADDR=0x2000
|
||||
BIN_LOAD_ADDR=0x0803
|
||||
BASIC_AUX_TYPE=0x0801
|
||||
READ_TIME_LOAD_ADDR=0x0260
|
||||
MKDISK=$(AC) -pro140 $(DISK) $(DISK_VOL)
|
||||
OBJS=copy.o online.o prodos.o prodos-util.o
|
||||
SRCS=copy.c online.c prodos-util.c
|
||||
|
||||
########################################
|
||||
|
||||
all: $(DISK)
|
||||
|
||||
$(DISK): $(PGM)
|
||||
$(RM) $(DISK)
|
||||
$(AC) -pro140 $(DISK) $(DISK_VOL)
|
||||
$(AC) -as $(DISK) $(PGM) BIN < $(PGM)
|
||||
|
||||
$(PGM): $(OBJS)
|
||||
$(CC) $(LDFLAGS) -o $@ $^
|
||||
|
||||
copy.o: copy.c prodos.h
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
online.o: online.c prodos.h
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
prodos-util.o: prodos-util.c prodos.h
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
prodos.o: prodos.s prodos.h
|
||||
ca65 -t $(CC65_TARGET) $<
|
||||
|
||||
clean:
|
||||
$(RM) $(OBJS) $(PGM) $(DISK)
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
********************************
|
||||
* *
|
||||
* COPY - COPIES FILES *
|
||||
* *
|
||||
* AUTHOR: BILL CHATFIELD *
|
||||
* LICENSE: GPL2 *
|
||||
* *
|
||||
********************************
|
||||
|
||||
********************************
|
||||
* *
|
||||
* CONSTANTS *
|
||||
* *
|
||||
********************************
|
||||
|
||||
RDKEY EQU $FD0C ;READS 1 CHAR
|
||||
CROUT EQU $FD8E ;SUB TO OUTPUT CARRIAGE RETURN
|
||||
COUT EQU $FDED ;SUB TO OUTPUT A CHARACTER
|
||||
PRBYTE EQU $FDDA ;SUB TO PRINT ERROR MESSAGE
|
||||
BELL EQU $FF3A ;SUBROUTINE TO BEEP
|
||||
PRODOS_MLI = $bf00 ;Address for MLI subroutine entry point
|
||||
SET_FILE_INFO = $c3 ;Code for system call
|
||||
GET_FILE_INFO = $c4 ;Code for system call
|
||||
ON_LINE = $c5 ;ID FOR ON_LINE MLI SYSTEM CALL
|
||||
|
||||
|
||||
********************************
|
||||
* *
|
||||
* puts *
|
||||
* *
|
||||
********************************
|
||||
|
||||
.macro puts s
|
||||
.local nextchar
|
||||
.local finish
|
||||
tya ;Preserve y
|
||||
pha
|
||||
ldy #0 ;Prepare loop index
|
||||
nextchar: lda s,y ;Load a character
|
||||
cmp #0 ;Check for end of string
|
||||
beq finish
|
||||
jsr cout
|
||||
iny
|
||||
jmp nextchar
|
||||
finish: pla ;Restore y
|
||||
tay
|
||||
.endmacro
|
||||
|
||||
.macro movb dest,src
|
||||
lda src
|
||||
sta dest
|
||||
.endmacro
|
||||
|
||||
.macro mova dest,src
|
||||
lda src
|
||||
sta dest
|
||||
lda src+1
|
||||
sta dest+1
|
||||
.endmacro
|
||||
|
||||
.proc handleError
|
||||
rts
|
||||
.endproc
|
||||
|
||||
********************************
|
||||
* *
|
||||
* Main *
|
||||
* *
|
||||
********************************
|
||||
|
||||
main:
|
||||
movb fileInfo+FileInfo::paramCount,$a
|
||||
mova fileInfo+FileInfo::pathName,srcFile
|
||||
|
||||
jsr PRODOS_MLI ;Call MLI subroutine
|
||||
.byte GET_FILE_INFO ;Identify the system call
|
||||
.addr fileInfo ;Address of system call args
|
||||
beq cont1 ;Returns 0 on success
|
||||
jsr handleError
|
||||
rts
|
||||
|
||||
|
||||
; BSS is Block Started by Symbol for zero-initialized read/write data
|
||||
; Constructed by loader and zeroed out based on required size
|
||||
.bss
|
||||
|
||||
onlineVols: .res 256 ;SPACE FOR 16 DISK VOL RECORDS
|
||||
srcFile .byte ;Length byte
|
||||
.res 64 ;Characters of srcFile
|
||||
|
||||
|
||||
; DATA contains initialized read/write data - encoded into binary
|
||||
.data
|
||||
|
||||
onlineArgs: .byte 2 ;PARAMETER COUNT
|
||||
.byte 0 ;UNIT NUMBER, 0=ALL
|
||||
.addr _onlineVols ;ADDRESS OF OUTPUT BUFFER
|
||||
|
||||
.struct FileInfo
|
||||
paramCount .byte
|
||||
pathName .addr
|
||||
access .byte
|
||||
fileType .byte
|
||||
auxType .word
|
||||
storageType .byte
|
||||
blocksUsed .word
|
||||
modDate .word
|
||||
modTime .word
|
||||
createDate .word
|
||||
createTime .word
|
||||
.endstruct
|
||||
|
||||
fileInfo: .tag FileInfo
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
#include <stdio.h> /* FILENAME_MAX */
|
||||
#include <string.h> /* strerror */
|
||||
#include <errno.h> /* errno */
|
||||
#include "prodos.h" /* prodosGetFileInfo, prodosSetFileInfo */
|
||||
|
||||
void copy(const char *srcName, const char *dstName);
|
||||
|
||||
#define BUFFER_SIZE 2048
|
||||
|
||||
char src[FILENAME_MAX];
|
||||
char dst[FILENAME_MAX];
|
||||
char buf[BUFFER_SIZE];
|
||||
|
||||
struct ProdosFileInfo fileAttributes;
|
||||
struct ProdosPathName srcPathName;
|
||||
struct ProdosPathName dstPathName;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
printf("Source file:");
|
||||
fgets(src, FILENAME_MAX, stdin);
|
||||
printf("Destination file:");
|
||||
fgets(dst, FILENAME_MAX, stdin);
|
||||
|
||||
copy(src, dst);
|
||||
}
|
||||
|
||||
void copy(const char *srcName, const char *dstName)
|
||||
{
|
||||
FILE *src, *dst;
|
||||
size_t readCount;
|
||||
int errorCode;
|
||||
|
||||
fileAttributes.paramCount = PRODOS_GET_FILE_INFO_PARAM_COUNT;
|
||||
fileAttributes.pathName = prodosAssignPathName(&srcPathName, srcName);
|
||||
errorCode = prodosGetFileInfo(&fileAttributes);
|
||||
if (errorCode > 0) {
|
||||
fprintf(stderr, "%s: %s\n", srcName, prodosGetMessage(errorCode));
|
||||
return;
|
||||
}
|
||||
|
||||
src = fopen(srcName, "r");
|
||||
dst = fopen(dstName, "w");
|
||||
|
||||
while ((readCount = fread(buf,1,BUFFER_SIZE,src)) == BUFFER_SIZE) {
|
||||
fwrite(buf,1,BUFFER_SIZE,dst);
|
||||
}
|
||||
if (feof(src) && readCount > 0) {
|
||||
fwrite(buf,1,readCount,dst);
|
||||
} else if (ferror(src)) {
|
||||
fprintf(stderr, "%s: %s\n", srcName, strerror(errno));
|
||||
}
|
||||
fclose(dst);
|
||||
fclose(src);
|
||||
|
||||
fileAttributes.paramCount = PRODOS_SET_FILE_INFO_PARAM_COUNT;
|
||||
fileAttributes.pathName = prodosAssignPathName(&dstPathName, dstName);
|
||||
errorCode = prodosSetFileInfo(&fileAttributes);
|
||||
if (errorCode > 0) {
|
||||
fprintf(stderr, "%s: %s\n", dstName, prodosGetMessage(errorCode));
|
||||
return;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
.export _onlineSysCall
|
||||
.export _onlineVols
|
||||
|
||||
ON_LINE = $c5 ;ID FOR ON_LINE MLI SYSTEM CALL
|
||||
PRODOS_MLI = $bf00 ;ADDRESS OF MLI ENTRY POINT
|
||||
|
||||
.proc _onlineSysCall
|
||||
|
||||
jsr PRODOS_MLI ;CALL MACHINE LANGUAGE INTERFACE
|
||||
.byte ON_LINE ;SPECIFY THE ON_LINE SYSTEM CALL
|
||||
.addr onlineArgs ;SPECIFY ADDRESS OF ARGUMENTS
|
||||
|
||||
; sta retCode ;Store the return code
|
||||
; lda #<retCode ;PUT LOW BYTE INTO ACCUMULATOR
|
||||
; ldx #>retCode ;PUT HIGH BYTE INTO X
|
||||
rts
|
||||
.endproc
|
||||
|
||||
; BSS is Block Started by Symbol for zero-initialized read/write data
|
||||
; Constructed by loader and zeroed out based on required size
|
||||
.bss
|
||||
|
||||
retCode: .byte 0
|
||||
_onlineVols:.res 256 ;SPACE FOR 16 DISK VOL RECORDS
|
||||
|
||||
; DATA contains initialized read/write data - encoded into binary
|
||||
.data
|
||||
|
||||
onlineArgs: .byte 2 ;PARAMETER COUNT
|
||||
.byte 0 ;UNIT NUMBER, 0=ALL
|
||||
.addr _onlineVols ;ADDRESS OF OUTPUT BUFFER
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#define PRODOS_MLI 0xbf00
|
||||
#define ON_LINE_SYSTEM_CALL 0xc5
|
||||
#define PRODOS_FILE_NAME_MAX_LEN 15
|
||||
typedef char ProdosFileName[PRODOS_FILE_NAME_MAX_LEN + 1];
|
||||
typedef ProdosFileName ProdosFileNameArray16[16];
|
||||
typedef struct OnlineSystemCallArguments {
|
||||
uint8_t argumentCount;
|
||||
uint8_t unitNumber;
|
||||
ProdosFileNameArray16 *volumesOutputBuffer;
|
||||
} OnlineSystemCallArguments;
|
||||
|
||||
static ProdosFileNameArray16 volumes;
|
||||
static OnlineSystemCallArguments arguments;
|
||||
|
||||
ProdosFileNameArray16 *online(uint8_t *errorCode)
|
||||
{
|
||||
arguments.argumentCount = 2;
|
||||
arguments.unitNumber = 0; // All units
|
||||
arguments.volumesOutputBuffer = &volumes;
|
||||
|
||||
__asm__("jsr %w", PRODOS_MLI);
|
||||
__asm__("db %b", ON_LINE_SYSTEM_CALL);
|
||||
__asm__("da %v", &arguments);
|
||||
__asm__("bne %g", errorHandler);
|
||||
|
||||
return &volumes;
|
||||
|
||||
errorHandler:
|
||||
return errorCode;
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <device.h>
|
||||
#include "prodos.h"
|
||||
|
||||
extern uint8_t onlineVols[];
|
||||
extern uint8_t onlineSysCall();
|
||||
|
||||
enum ProdosErrorCode online(struct ProdosVolumes *vols)
|
||||
{
|
||||
uint8_t byte;
|
||||
uint8_t i;
|
||||
uint8_t nameLength;
|
||||
enum ProdosErrorCode errorCode;
|
||||
struct ProdosVolume *volume;
|
||||
|
||||
errorCode = onlineSysCall();
|
||||
if (errorCode != PRODOS_ERR_NO_ERROR) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < PRODOS_MAX_VOLUME_COUNT; ++i) {
|
||||
byte = onlineVols[i*16];
|
||||
if (byte == 0) {
|
||||
vols->count = i;
|
||||
break;
|
||||
}
|
||||
volume = &(vols->volumes[i]);
|
||||
volume->drive = ((byte & 0x80) >> 7) + 1;
|
||||
volume->slot = (byte & 0x70) >> 4;
|
||||
nameLength = byte & 0x0f;
|
||||
strncpy(volume->name, &(onlineVols[i*16+1]), nameLength);
|
||||
volume->name[nameLength] = '\0';
|
||||
}
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
struct ProdosVolume volume;
|
||||
struct ProdosVolumes volumes;
|
||||
enum ProdosErrorCode errorCode;
|
||||
|
||||
void printOnline(void)
|
||||
{
|
||||
uint8_t i, dev;
|
||||
char volName[FILENAME_MAX];
|
||||
|
||||
errorCode = online(&volumes);
|
||||
if (errorCode > 0) {
|
||||
printf("Error: %d\n", errorCode);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (i = 0; i < volumes.count; ++i) {
|
||||
volume = volumes.volumes[i];
|
||||
if (strlen(volume.name)>0) {
|
||||
printf("S%d,D%d /%s\n", volume.slot, volume.drive, volume.name);
|
||||
}
|
||||
}
|
||||
|
||||
dev = getfirstdevice();
|
||||
while (dev != INVALID_DEVICE) {
|
||||
getdevicedir(dev, volName, sizeof(volName));
|
||||
printf("device=%d volume=%s\n", dev, volName);
|
||||
dev = getnextdevice(dev);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
#include <string.h> /* size_t */
|
||||
#include "prodos.h"
|
||||
|
||||
struct ProdosPathName *
|
||||
prodosAssignPathName(struct ProdosPathName *dest, const char *src)
|
||||
{
|
||||
size_t i;
|
||||
char c;
|
||||
char *name;
|
||||
|
||||
name = dest->name;
|
||||
for (i = 0; i < PRODOS_MAX_PATHNAME_LENGTH && (c = src[i]) != '\0'; ++i) {
|
||||
name[i] = c;
|
||||
}
|
||||
dest->length = i;
|
||||
return dest;
|
||||
}
|
||||
|
||||
char *
|
||||
prodosGetMessage(enum ProdosErrorCode code)
|
||||
{
|
||||
char *message;
|
||||
|
||||
switch (code) {
|
||||
case PRODOS_ERR_NO_ERROR:
|
||||
message = "No error";
|
||||
break;
|
||||
case PRODOS_ERR_BAD_SYS_CALL_NUM:
|
||||
message = "Bad system call number";
|
||||
break;
|
||||
case PRODOS_ERR_BAD_PARAM_COUNT:
|
||||
message = "Bad parameter count";
|
||||
break;
|
||||
case PRODOS_ERR_INTR_VECT_TBL_FULL:
|
||||
message = "Interrupt vector table full";
|
||||
break;
|
||||
default:
|
||||
message = "Unknown error";
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
#ifndef PRODOS
|
||||
#define PRODOS
|
||||
|
||||
#include <stdint.h> /* uint8_t, uint16_t */
|
||||
|
||||
#define PRODOS_GET_FILE_INFO_PARAM_COUNT 0x0a
|
||||
#define PRODOS_SET_FILE_INFO_PARAM_COUNT 0x07
|
||||
#define PRODOS_MAX_PATHNAME_LENGTH 64
|
||||
|
||||
#define PRODOS_MAX_VOLUME_NAME_LEN 15
|
||||
#define PRODOS_MAX_VOLUME_COUNT 16
|
||||
|
||||
enum ProdosErrorCode {
|
||||
PRODOS_ERR_NO_ERROR = 0,
|
||||
PRODOS_ERR_BAD_SYS_CALL_NUM = 1,
|
||||
PRODOS_ERR_BAD_PARAM_COUNT = 4,
|
||||
PRODOS_ERR_INTR_VECT_TBL_FULL = 25,
|
||||
};
|
||||
|
||||
struct ProdosVolume {
|
||||
uint8_t drive;
|
||||
uint8_t slot;
|
||||
uint8_t nameLength;
|
||||
char name[PRODOS_MAX_VOLUME_NAME_LEN+1];
|
||||
};
|
||||
|
||||
struct ProdosVolumes {
|
||||
uint8_t count;
|
||||
struct ProdosVolume volumes[PRODOS_MAX_VOLUME_COUNT];
|
||||
};
|
||||
|
||||
struct ProdosPathName
|
||||
{
|
||||
uint8_t length;
|
||||
char name[PRODOS_MAX_PATHNAME_LENGTH];
|
||||
};
|
||||
|
||||
struct ProdosFileInfo
|
||||
{
|
||||
uint8_t paramCount;
|
||||
struct ProdosPathName *pathName;
|
||||
uint8_t access;
|
||||
uint8_t fileType;
|
||||
uint16_t auxType;
|
||||
uint8_t storageType;
|
||||
uint16_t blocksUsed;
|
||||
uint16_t modDate;
|
||||
uint16_t modTime;
|
||||
uint16_t createDate;
|
||||
uint16_t createTime;
|
||||
};
|
||||
|
||||
extern int __fastcall__
|
||||
prodosGetFileInfo(struct ProdosFileInfo *fileInfo);
|
||||
|
||||
extern int __fastcall__
|
||||
prodosSetFileInfo(struct ProdosFileInfo *fileInfo);
|
||||
|
||||
extern struct ProdosPathName *
|
||||
prodosAssignPathName(struct ProdosPathName *dest, const char *src);
|
||||
|
||||
extern char *
|
||||
prodosGetMessage(enum ProdosErrorCode code);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
.export _prodosGetFileInfo
|
||||
.export _prodosSetFileInfo
|
||||
.export _onlineSysCall
|
||||
.export _onlineVols
|
||||
|
||||
|
||||
PRODOS_MLI = $bf00 ;Address for MLI subroutine entry point
|
||||
SET_FILE_INFO = $c3 ;Code for system call
|
||||
GET_FILE_INFO = $c4 ;Code for system call
|
||||
ON_LINE = $c5 ;ID FOR ON_LINE MLI SYSTEM CALL
|
||||
|
||||
.proc _prodosGetFileInfo
|
||||
sta fileInfo ;Store low-byte of C address param
|
||||
stx fileInfo+1 ;Store high-byte of C address param
|
||||
jsr PRODOS_MLI ;Call MLI subroutine
|
||||
.byte GET_FILE_INFO ;Identify the system call
|
||||
fileInfo: .addr $0000 ;Address of system call args
|
||||
ldx #0 ;Zero high byte of int return value
|
||||
rts ;Accum has error code, low byte of int
|
||||
.endproc
|
||||
|
||||
.proc _prodosSetFileInfo
|
||||
sta fileInfo ;Store low-byte of C address param
|
||||
stx fileInfo+1 ;Store high-byte of C address param
|
||||
jsr PRODOS_MLI ;Call MLI subroutine
|
||||
.byte SET_FILE_INFO ;Identify the system call
|
||||
fileInfo: .addr $0000 ;Address of system call args
|
||||
ldx #0 ;Zero high byte of int return value
|
||||
rts ;Accumulator has error code
|
||||
.endproc
|
||||
|
||||
.proc _onlineSysCall
|
||||
|
||||
jsr PRODOS_MLI ;CALL MACHINE LANGUAGE INTERFACE
|
||||
.byte ON_LINE ;SPECIFY THE ON_LINE SYSTEM CALL
|
||||
.addr onlineArgs ;SPECIFY ADDRESS OF ARGUMENTS
|
||||
|
||||
; sta retCode ;Store the return code
|
||||
; lda #<retCode ;PUT LOW BYTE INTO ACCUMULATOR
|
||||
; ldx #>retCode ;PUT HIGH BYTE INTO X
|
||||
rts
|
||||
.endproc
|
||||
|
||||
; BSS is Block Started by Symbol for zero-initialized read/write data
|
||||
; Constructed by loader and zeroed out based on required size
|
||||
.bss
|
||||
|
||||
retCode: .byte 0
|
||||
_onlineVols:.res 256 ;SPACE FOR 16 DISK VOL RECORDS
|
||||
|
||||
; DATA contains initialized read/write data - encoded into binary
|
||||
.data
|
||||
|
||||
onlineArgs: .byte 2 ;PARAMETER COUNT
|
||||
.byte 0 ;UNIT NUMBER, 0=ALL
|
||||
.addr _onlineVols ;ADDRESS OF OUTPUT BUFFER
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
.export _mliGetFileInfo
|
||||
.export _mliSetFileInfo
|
||||
|
||||
SET_FILE_INFO = $c3 ;Code for system call
|
||||
GET_FILE_INFO = $c4 ;Code for system call
|
||||
PRODOS_MLI = $bf00 ;Address for MLI subroutine entry point
|
||||
|
||||
.proc _mliGetFileInfo
|
||||
sta fileInfo ;Store low-byte of C address param
|
||||
stx fileInfo+1 ;Store high-byte of C address param
|
||||
jsr PRODOS_MLI ;Call MLI subroutine
|
||||
.byte GET_FILE_INFO ;Identify the system call
|
||||
fileInfo: .addr $0000 ;Address of system call args
|
||||
ldx #0 ;Zero high byte of int return value
|
||||
rts ;Accum has error code, low byte of int
|
||||
.endproc
|
||||
|
||||
.proc _mliSetFileInfo
|
||||
sta fileInfo ;Store low-byte of C address param
|
||||
stx fileInfo+1 ;Store high-byte of C address param
|
||||
jsr PRODOS_MLI ;Call MLI subroutine
|
||||
.byte SET_FILE_INFO ;Identify the system call
|
||||
fileInfo: .addr $0000 ;Address of system call args
|
||||
ldx #0 ;Zero high byte of int return value
|
||||
rts ;Accumulator has error code
|
||||
.endproc
|
||||
|
||||
; BSS is Block Started by Symbol for zero-initialized read/write data
|
||||
; Constructed by loader and zeroed out based on required size
|
||||
|
||||
.bss
|
||||
|
||||
; DATA segment contains initialized read/write data - encoded into binary
|
||||
|
||||
.data
|
||||
|
54
online.c
54
online.c
|
@ -1,33 +1,55 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PRODOS_MLI 0xbf00
|
||||
#define ON_LINE_SYSTEM_CALL 0xc5
|
||||
#define PRODOS_FILE_NAME_MAX_LEN 15
|
||||
typedef char ProdosFileName[PRODOS_FILE_NAME_MAX_LEN + 1];
|
||||
typedef ProdosFileName ProdosFileNameArray16[16];
|
||||
typedef struct OnlineSystemCallArguments {
|
||||
#define ON_LINE (uint8_t) 0xc5
|
||||
#define PRODOS_NAME_CAPACITY 16
|
||||
|
||||
struct OnlineArguments {
|
||||
uint8_t argumentCount;
|
||||
uint8_t unitNumber;
|
||||
ProdosFileNameArray16 *volumesOutputBuffer;
|
||||
} OnlineSystemCallArguments;
|
||||
char **volumes;
|
||||
};
|
||||
|
||||
static ProdosFileNameArray16 volumes;
|
||||
static OnlineSystemCallArguments arguments;
|
||||
struct OnlineArguments arguments;
|
||||
char volumes[16][PRODOS_NAME_CAPACITY];
|
||||
uint8_t argumentsAddrLowByte;
|
||||
uint8_t argumentsAddrHighByte;
|
||||
|
||||
ProdosFileNameArray16 *online(uint8_t *errorCode)
|
||||
void online(void)
|
||||
{
|
||||
arguments.argumentCount = 2;
|
||||
arguments.unitNumber = 0; // All units
|
||||
arguments.volumesOutputBuffer = &volumes;
|
||||
arguments.volumes = volumes;
|
||||
|
||||
__asm__("lda #%b", ON_LINE);
|
||||
__asm__("sta %g", l1);
|
||||
|
||||
argumentsAddrLowByte = (uint8_t) &arguments;
|
||||
argumentsAddrLowByte = (uint8_t) &arguments >> 4;
|
||||
|
||||
__asm__("lda %v", argumentsAddrLowByte);
|
||||
__asm__("sta %g", l2);
|
||||
|
||||
__asm__("lda %v", argumentsAddrHighByte);
|
||||
__asm__("sta %g", l3);
|
||||
|
||||
__asm__("jsr %w", PRODOS_MLI);
|
||||
__asm__("db %b", ON_LINE_SYSTEM_CALL);
|
||||
__asm__("da %v", &arguments);
|
||||
l1:
|
||||
__asm__("nop");
|
||||
l2:
|
||||
__asm__("nop");
|
||||
l3:
|
||||
__asm__("nop");
|
||||
__asm__("bne %g", errorHandler);
|
||||
|
||||
return &volumes;
|
||||
|
||||
errorHandler:
|
||||
return errorCode;
|
||||
fprintf(stderr, "Online system call failed\n");
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
online();
|
||||
puts(volumes[0]);
|
||||
}
|
||||
|
||||
|
|
26
online.s
26
online.s
|
@ -1,26 +0,0 @@
|
|||
.export _onLineSysCall
|
||||
.export _onLineVols
|
||||
|
||||
ON_LINE = $c5 ;ID FOR ON_LINE MLI SYSTEM CALL
|
||||
PRODOS_MLI = $bf00 ;ADDRESS OF MLI ENTRY POINT
|
||||
|
||||
.proc _onLineSysCall
|
||||
|
||||
jsr PRODOS_MLI ;CALL MACHINE LANGUAGE INTERFACE
|
||||
.byte ON_LINE ;SPECIFY THE ON_LINE SYSTEM CALL
|
||||
.addr onlineArgs ;SPECIFY ADDRESS OF ARGUMENTS
|
||||
|
||||
sta retCode ;Store the return code
|
||||
lda #<retCode ;PUT LOW BYTE INTO ACCUMULATOR
|
||||
ldx #>retCode ;PUT HIGH BYTE INTO X
|
||||
rts
|
||||
.endproc
|
||||
|
||||
.bss
|
||||
retCode: .byte 0
|
||||
_onLineVols:.res 256 ;SPACE FOR 16 DISK VOL RECORDS
|
||||
|
||||
onlineArgs: .byte 2 ;PARAMETER COUNT
|
||||
.byte 0 ;UNIT NUMBER, 0=ALL
|
||||
.addr _onLineVols ;ADDRESS OF OUTPUT BUFFER
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
.export _online
|
||||
.export _olerr
|
||||
|
||||
.include "mli.inc"
|
||||
|
||||
.bss
|
||||
|
||||
_olerr: .byte $00
|
||||
|
||||
.code
|
||||
|
||||
_open:
|
||||
lda #ON_LINE_CALL
|
||||
ldx #ON_LINE_COUNT
|
||||
jsr callmli
|
||||
bcc done
|
||||
|
||||
sta _olerr
|
||||
|
||||
done:
|
||||
rts
|
Loading…
Reference in New Issue