diff --git a/.gitignore b/.gitignore index c6127b3..d54ffb8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# Vim swap files +*.swp + # Prerequisites *.d diff --git a/Makefile b/Makefile index 7a45122..a4c1c40 100644 --- a/Makefile +++ b/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) diff --git a/Makefile.onl b/Makefile.onl new file mode 100644 index 0000000..73294b7 --- /dev/null +++ b/Makefile.onl @@ -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) + diff --git a/copy.s b/copy.s new file mode 100644 index 0000000..67d7afa --- /dev/null +++ b/copy.s @@ -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+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 + diff --git a/errorhandler.s b/errorhandler.s new file mode 100644 index 0000000..d5908b5 --- /dev/null +++ b/errorhandler.s @@ -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 diff --git a/old/Makefile b/old/Makefile new file mode 100644 index 0000000..d3d40a9 --- /dev/null +++ b/old/Makefile @@ -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) + diff --git a/old/copy-ca65.s b/old/copy-ca65.s new file mode 100644 index 0000000..56a52f6 --- /dev/null +++ b/old/copy-ca65.s @@ -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 + diff --git a/old/copy.c b/old/copy.c new file mode 100644 index 0000000..d0d4ecf --- /dev/null +++ b/old/copy.c @@ -0,0 +1,63 @@ +#include /* FILENAME_MAX */ +#include /* strerror */ +#include /* 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; + } +} diff --git a/old/online-mli.s b/old/online-mli.s new file mode 100644 index 0000000..80b154f --- /dev/null +++ b/old/online-mli.s @@ -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 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 + diff --git a/old/online-old.c b/old/online-old.c new file mode 100644 index 0000000..71741bf --- /dev/null +++ b/old/online-old.c @@ -0,0 +1,33 @@ +#include + +#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; +} + diff --git a/old/online.c b/old/online.c new file mode 100644 index 0000000..a48dde3 --- /dev/null +++ b/old/online.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include +#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); + } +} + diff --git a/old/prodos-util.c b/old/prodos-util.c new file mode 100644 index 0000000..c04881e --- /dev/null +++ b/old/prodos-util.c @@ -0,0 +1,42 @@ +#include /* 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; +} + diff --git a/old/prodos.h b/old/prodos.h new file mode 100644 index 0000000..f84a4f4 --- /dev/null +++ b/old/prodos.h @@ -0,0 +1,66 @@ +#ifndef PRODOS +#define PRODOS + +#include /* 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 + diff --git a/old/prodos.s b/old/prodos.s new file mode 100644 index 0000000..25983a7 --- /dev/null +++ b/old/prodos.s @@ -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 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 + diff --git a/old/prodos.s.bak b/old/prodos.s.bak new file mode 100644 index 0000000..24d3abe --- /dev/null +++ b/old/prodos.s.bak @@ -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 + diff --git a/online.c b/online.c index 71741bf..0e556f3 100644 --- a/online.c +++ b/online.c @@ -1,33 +1,55 @@ +#include #include #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]); } diff --git a/online.s b/online.s deleted file mode 100644 index 331cc6e..0000000 --- a/online.s +++ /dev/null @@ -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 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 - diff --git a/onlinesys.s b/onlinesys.s new file mode 100644 index 0000000..a19d3e1 --- /dev/null +++ b/onlinesys.s @@ -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