avatar_OffseT

UniDOS, the new multi-device AMSDOS replacement

Started by OffseT, 15:51, 24 January 21

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

OffseT


UniDOS will ask for a description for each drive of the node that indicated an inserted media.

IIRC, calling sequence should be something like that:
GetStatus (for each 0-7 drive from the DOS node), and if both Carry and media inserted bit are set, then GetName & GetDesc.

Anycase, your node shall only set carry for drive numbers it handles. Reply NC otherwise.

You should also double check that your routines do not modify some forbidden registers (only the ones listed as "altered" can be). Modifying unexpected registers could break UniDOS. For performance and memory saving reasons UniDOS does not push/pop its registers when calling a DOS node routine.

zhulien

hmm, GetName is called 8 times, I return C for 6 (now as I have 6 drives), and 2 NC.  Then it calls GetDesc not only for my 6 drives, but also for the 3 drives that are not even related to my Node.

I have attached my code here if you would like to have a play, it has 4 nodes coded - 2 tested (VDU (screen) & DACA (amdrum)).  DACM (music machine) and PRN (printer) I have no printer to test with, and no emulators are working with music machine so I guessed - yet to try the node on my real hardware.  SPCHA (SSA1) and SPCHD (DkTronics) yet to code the write routine.

I had a couple of thoughts wouldn't mind your feedback.  There are only 8 devices in a Node, of course we can have lots of nodes, but these won't take lots of ROM storage so a waste to not support more than 8 devices over time.  Rather than me making lots of devices, I was thinking to make a single device for each category, and a path for the actual things to write to.  eg: PRN for all printers, inside that a virtual folder INTERNAL.  SPCH for all speech synth, inside that SSA1 and DKTRONIC virtual folders.  DACS for all DACs, inside virtual folders AMDRUM and MMACHINE.  Of course instead of SPCH and DACS devices, I could just have AUDIO and put SSA1, DKTRONIC, AMDRUM, MMACHINE all in there?

What do you think is best for future expansion for such streams.  If different folders, then I can read from them too to get device statistics or configure them too, like payback speed by writing to a file in a virtual folder.

Future copy commands that honor unidos correctly will also be e.g. able to copy a text file from a disc, to screen to output it... or to the printer to print it... or to SSA1 to speak it.

org #c000

;write direct #C000, #0a

CODE_START:

ROMType db 2; 1 (secondary ROM) or 2 (expansion ROM)

ROMMark db 1; It is customary that the version of a ROM
ROMVer db 4; is displayed in the form M VR
ROMRev db 1; (i.e. 1.00 here)

ROMRSX dw RSXTable

jp InitROM
jp DOSNode_Init ; implemented, 1: called once, A = 1
jp DOSNode_CheckDrive ; implemented, 3: called once, HL = Streamer, Return 0
jp DOSNode_GetStatus ; implemented, 4: called once, A = 0
jp DOSNode_GetName ; implemented, 2: called 8 times, A = 0 to 7
jp DOSNode_GetDesc ; implemented, 6: called once, A = 0
jp DOSNode_GetFreeSpace ; implemented, 5: called once, A = 0
jp DOSNode_InOpenStream
jp DOSNode_InReadStream
jp DOSNode_InCloseStream
jp DOSNode_InSeekStream
jp DOSNode_OutOpenStream ; implemented
jp DOSNode_OutWriteStream ; implemented
jp DOSNode_OutCloseStream ; implemented
jp DOSNode_OutSeekStream
jp DOSNode_Examine
jp DOSNode_ExamineNext
jp DOSNode_Rename
jp DOSNode_Delete
jp DOSNode_CreateDir
jp DOSNode_SetProtection
jp DOSNode_Format
jp DOSNode_SetFileDate
jp DOSNode_Void
jp DOSNode_Void
jp DOSNode_Void
jp DOSNode_ReadRTC
jp DOSNode_WriteRTC
jp DOSNode_OpenNVRAM
jp DOSNode_CloseNVRAM
jp DOSNode_ReadNVRAM
jp DOSNode_WriteNVRAM
jp DOSNode_SeekNVRAM
; You can add your personal RSX here (if ROM type 1)

RSXTable
str "STREAMER"
str "DOS Node"

db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80
db #80

; You can add your personal RSX here (if ROM type 1)
db 0; End of the RSX table

        ; Actual ROM code starts here
InitROM: cp a
ret

BYTES_FREE_HW equ #00ff ; high word
BYTES_FREE_LW equ #ffff ; low word
DAC_DELAY equ 4 ; slow dac playing a bit
PORT_DACA equ #ff
PORT_DACM equ #f8f0

MC_PRINT_CHAR equ #bd2b
TXT_OUT_CHAR equ #bb5a

Drive_VDU equ #0
Drive_PRN equ #1
Drive_DACA equ #2 ; AMDRUM DAC
Drive_DACM equ #3 ; Music Machine DAC
Drive_SPCHA equ #4 ; Amstrad SSA-1 Speech Synth
Drive_SPCHD equ #5 ; Dk'Tronics Speech Synth

DriveNames:
DriveNameVDU: db "VD", "U" + #80, 0, Drive_VDU
DriveNamePRN: db "PR", "N" + #80, 0, Drive_PRN
DriveNameDACA: db "DAC", "A" + #80, 0, Drive_DACA
DriveNameDACM: db "DAC", "M" + #80, 0, Drive_DACM
DriveNameSPCHA: db "SPCH", "A" + #80, 0, Drive_SPCHA
DriveNameSPCHD: db "SPCH", "D" + #80, 0, Drive_SPCHD
db 0

DriveDescVDU: db "Text To Scree", "n" + #80, 0
DriveDescPRN: db "Standard Printer Por", "t" + #80, 0
DriveDescDACA: db "DAC Cheetah Amdru", "m" + #80, 0
DriveDescDACM: db "DAC RAM Music Machin", "e" + #80, 0
DriveDescSPCHA: db "Speech Amstra", "d" + #80, 0
DriveDescSPCHD: db "Speech Dk'tronic", "s" + #80, 0

;
; Initialize the noeud DOS
;
; Input   - A = initialization status (see flags Init_*)
;               Bit0 = 1 if the CPC is doing a cold boot
;               Other bits are unused
; Output  - If Carry = 1 then the node was intialized
;           If Carry = 0 then the node could not be initialized
; Altered - AF

DOSNode_Init: xor a
jp DOSNode_Success

;
; Check if a drive name is handled by the DOS node
;
; Input   - HL = pointer to the drive name
;                (bit 7 could be set on some character and mush be ignored)
;           C = length of the drive name
; Output - If Carry = 1 a drive was found in the node
;                A = physical drive number
;           If Carry = 0 the drive was not found in the node
; Altered - AF

DOSNode_CheckDrive:
push de
push hl
ld de, DriveNames
ex de, hl
call ListGetIDByName
pop hl
pop de
jp nz, DOSNode_Fail

jp DOSNode_Success

;
; Return a drive status
;
; Input   - A = drive number
; Output  - If Carry = 1 a status was returned
;                A = status of the drive (see flags flags Media_*)
;                    Bit0 = 1 if a media is inserted in the drive
;                    Bit1 = 1 if the media support directories
;                    Bit2 = 1 if the media is write protected
;                    Bit3 = 1 if the media is removable
;                    Bit4 = 1 if the media is a stream (linear read/write only)
;                        $$$ and BAK filesis then disabled
;                    Bit5 = 1 if the media can be reached by the new UniDOS API
;                    Other bits are unused
;           If Carry = 0 then the drive is unknown and no status was returned
; Alteted - AF

DOSNode_GetStatus:
cp Drive_VDU
jr z, DOSNode_GetStatus_VDU

cp Drive_PRN
jr z, DOSNode_GetStatus_PRN

cp Drive_DACA
jr z, DOSNode_GetStatus_DACA

cp Drive_DACM
jr z, DOSNode_GetStatus_DACM

cp Drive_SPCHA
jr z, DOSNode_GetStatus_SPCHA

cp Drive_SPCHD
jr z, DOSNode_GetStatus_SPCHD

jp DOSNode_Fail

DOSNode_GetStatus_VDU:
DOSNode_GetStatus_PRN:
DOSNode_GetStatus_DACA:
DOSNode_GetStatus_DACM:
DOSNode_GetStatus_SPCHA:
DOSNode_GetStatus_SPCHD:
ld a, %000110001
jp DOSNode_Success

;
; Return the name corresponding to a physical drive
;
; Input   - A = drive number
;           DE = address of a buffer of 8 bytes when to store the name
; Output  - If Carry = 1 the name was found
;                DE points to the first character after the end of the copied string
;                (the string is stored with the bit 7 of its last character set)
;          If Carry = 0 not description was found and the buffer is left unchanged.
; Altered - AF,DE

DOSNode_GetName:
cp Drive_VDU
jr z, DOSNode_GetName_VDU

cp Drive_PRN
jr z, DOSNode_GetName_PRN

cp Drive_DACA
jr z, DOSNode_GetName_DACA

cp Drive_DACM
jr z, DOSNode_GetName_DACM

cp Drive_SPCHA
jr z, DOSNode_GetName_SPCHA

cp Drive_SPCHD
jr z, DOSNode_GetName_SPCHD

jp DOSNode_Fail

DOSNode_GetName_VDU:
push hl
ld hl, DriveNameVDU
call StrCopy
pop hl
jp DOSNode_Success

DOSNode_GetName_PRN:
push hl
ld hl, DriveNamePRN
call StrCopy
pop hl
jp DOSNode_Success

DOSNode_GetName_DACA:
push hl
ld hl, DriveNameDACA
call StrCopy
pop hl
jp DOSNode_Success

DOSNode_GetName_DACM:
push hl
ld hl, DriveNameDACM
call StrCopy
pop hl
jp DOSNode_Success

DOSNode_GetName_SPCHA:
push hl
ld hl, DriveNameSPCHA
call StrCopy
pop hl
jp DOSNode_Success

DOSNode_GetName_SPCHD:
push hl
ld hl, DriveNameSPCHD
call StrCopy
pop hl
jp DOSNode_Success

;
; Return the description corresponding to a physical drive
;
; Input  - A = drive number
;          DE = addess of the 32 bytes buffer where to store the description
; Ouput  - If Carry = 1 a description was found
;                DE points to the first character after the end of the copied string
;                (the string is stored with the bit 7 of its last character set)
;          If Carry = 0 not description was found and the buffer is left unchanged.
; Altered - AF,DE

DOSNode_GetDesc:
cp Drive_VDU
jr z, DOSNode_GetDesc_VDU

cp Drive_PRN
jr z, DOSNode_GetDesc_PRN

cp Drive_DACA
jr z, DOSNode_GetDesc_DACA

cp Drive_DACM
jr z, DOSNode_GetDesc_DACM

cp Drive_SPCHA
jr z, DOSNode_GetDesc_SPCHA

cp Drive_SPCHD
jr z, DOSNode_GetDesc_SPCHD

jp DOSNode_Fail

DOSNode_GetDesc_VDU:
push hl
ld hl, DriveDescVDU
call StrCopy
pop hl
jp DOSNode_Success

DOSNode_GetDesc_PRN:
push hl
ld hl, DriveDescPRN
call StrCopy
pop hl
jp DOSNode_Success

DOSNode_GetDesc_DACA:
push hl
ld hl, DriveDescDACA
call StrCopy
pop hl
jp DOSNode_Success

DOSNode_GetDesc_DACM:
push hl
ld hl, DriveDescDACM
call StrCopy
pop hl
jp DOSNode_Success

DOSNode_GetDesc_SPCHA:
push hl
ld hl, DriveDescSPCHA
call StrCopy
pop hl
jp DOSNode_Success

DOSNode_GetDesc_SPCHD:
push hl
ld hl, DriveDescSPCHD
call StrCopy
pop hl
jp DOSNode_Success

;
; Return the free space on a physical drive
;
; Input   - A = drive number
; Output  - If Carry = 1 the routine is supported for this drive
;                If Z then the free space could be obtained
;                    BCDE = free space in kilo-bytes
;                If NZ then an error occured
;                    A = error code
;           If Carry = 0 then the routines is invalid for this drive
; Altered - AF,BC,DE

DOSNode_GetFreeSpace:
cp Drive_VDU
jr z, DOSNode_GetFreeSpace_VDU

cp Drive_PRN
jr z, DOSNode_GetFreeSpace_PRN

cp Drive_DACA
jr z, DOSNode_GetFreeSpace_DACA

cp Drive_DACM
jr z, DOSNode_GetFreeSpace_DACM

cp Drive_SPCHA
jr z, DOSNode_GetFreeSpace_SPCHA

cp Drive_SPCHD
jr z, DOSNode_GetFreeSpace_SPCHD

jp DOSNode_Fail

DOSNode_GetFreeSpace_VDU:
DOSNode_GetFreeSpace_PRN:
DOSNode_GetFreeSpace_DACA:
DOSNode_GetFreeSpace_DACM:
DOSNode_GetFreeSpace_SPCHA:
DOSNode_GetFreeSpace_SPCHD:
ld bc, BYTES_FREE_HW
ld de, BYTES_FREE_LW
xor a
jp DOSNode_Success

;
; Open the input stream
;
; Input   - A = drive number
;           HL = pointer to the normalized name
;               note, if the drive is of type stream then this name can
;               contain 11x&ff in case where no file name was provided
;               by the user (when he uses the anonymous reference ".");
;               the routine should then just open the just encountered
;               file on the stream and can optionally update the name
;               if it could be obtained from the stream itself
;          DE = pointer the normalized path
;          The pointed memory is always located in the current ROM/RAM space area
; Ouput  - If Carry = 1 the routine is supported for the provided drive
;                If Z then a file was opened
;                If NZ then no file could be opened
;                    A = error code
;               In any case, the routine might truncate the provided normalized path to match the nearest parent
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_InOpenStream:
jp DOSNode_Fail

;
; Read from the input stream
;
; Input  - A = drive number
;           HL = address where to stored the read data
;           DE = number of bytes to read
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then data could be read
;                    DE = number of bytes read
;                If NZ then a error occured
;                    A = error code
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF,DE

DOSNode_InReadStream:
jp DOSNode_Fail

;
; Close the input stream
;
; Input   - A = drive number
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then the stream was properly closed
;                If NZ then the stream was closed with an error
;                    A = error code
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_InCloseStream:
jp DOSNode_Fail

;
; Change the position into the input stream
;
; Input   - A = drive number
;           DEHL = new position in the input stream
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then the new position could be reached
;                If NZ then an error occured
;                    A = error code
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_InSeekStream:
jp DOSNode_Fail

;
; Open the output stream
;
; Input   - A = drive number
;           HL = pointer to the normalized name
;           DE = pointer to the normalized path
;          The pointed memory is always located in the current ROM/RAM space area
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then a file was created
;                If NZ then no file was created
;                    A = error code
;               In any case, the routine might truncate the provided normalized path to match the nearest parent
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_OutOpenStream:
cp Drive_VDU
jr z, DOSNode_OutOpenStream_VDU

cp Drive_PRN
jr z, DOSNode_OutOpenStream_PRN

cp Drive_DACA
jr z, DOSNode_OutOpenStream_DACA

cp Drive_DACM
jr z, DOSNode_OutOpenStream_DACM

cp Drive_SPCHA
jr z, DOSNode_OutOpenStream_SPCHA

cp Drive_SPCHD
jr z, DOSNode_OutOpenStream_SPCHD

jp DOSNode_Fail

DOSNode_OutOpenStream_VDU:
DOSNode_OutOpenStream_PRN:
DOSNode_OutOpenStream_DACA:
DOSNode_OutOpenStream_DACM:
DOSNode_OutOpenStream_SPCHA:
DOSNode_OutOpenStream_SPCHD:
jp DOSNode_Success

;
; Write into the ouput stream
;
; Input   - A = drive number
;           HL = address where are located the data to write
;           DE = number of bytes to write
; Sortie - If Carry = 1 the routine is supported for the provided drive
;                If Z then data could be written
;                    DE = nomber of written bytes
;                If NZ then an error occured
;                    A = error code
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF,DE

DOSNode_OutWriteStream:
cp Drive_VDU
jr z, DOSNode_OutWriteStream_VDU

cp Drive_PRN
jr z, DOSNode_OutWriteStream_PRN

cp Drive_DACA
jr z, DOSNode_OutWriteStream_DACA

cp Drive_DACM
jr z, DOSNode_OutWriteStream_DACM

cp Drive_SPCHA
jr z, DOSNode_OutWriteStream_SPCHA

cp Drive_SPCHD
jr z, DOSNode_OutWriteStream_SPCHD

jp DOSNode_Fail

; ----------------------------------------

DOSNode_OutWriteStream_VDU:

push hl

DOSNode_OutWriteStream_VDULoop:
ld a, (hl)
call ValidateChar
jr nc, DOSNode_OutWriteStream_VDUSkip

call TXT_OUT_CHAR

DOSNode_OutWriteStream_VDUSkip:
inc hl
dec de

ld a,d
or e
jr nz, DOSNode_OutWriteStream_VDULoop

DOSNode_OutWriteStream_VDUEnd:
pop hl
jp DOSNode_Success

; ----------------------------------------

DOSNode_OutWriteStream_PRN:

push hl

DOSNode_OutWriteStream_PRNLoop:
ld a, (hl)
;call ValidateChar
;jr nc, DOSNode_OutWriteStream_PRNSkip

call MC_PRINT_CHAR

;DOSNode_OutWriteStream_PRNSkip:
inc hl
dec de

ld a,d
or e
jr nz, DOSNode_OutWriteStream_PRNLoop

DOSNode_OutWriteStream_PRNEnd:
pop hl
jp DOSNode_Success

; ----------------------------------------

DOSNode_OutWriteStream_DACA:

push hl
push bc
di

DOSNode_OutWriteStream_DACALoop:

ld b, DAC_DELAY

DOSNode_OutWriteStream_DACALoop2:

push bc

ld c, (hl)
ld b, PORT_DACA
out (c), c

pop bc
djnz DOSNode_OutWriteStream_DACALoop2

inc hl
dec de

ld a,d
or e
jr nz, DOSNode_OutWriteStream_DACALoop

DOSNode_OutWriteStream_DACAEnd:
ei
pop bc
pop hl
jp DOSNode_Success

; ----------------------------------------

DOSNode_OutWriteStream_DACM:

push hl
push bc
di

DOSNode_OutWriteStream_DACMLoop:

ld b, DAC_DELAY

DOSNode_OutWriteStream_DACMLoop2:

push bc

ld a, (hl)
ld bc, PORT_DACM
out (c), a

pop bc
djnz DOSNode_OutWriteStream_DACMLoop2

inc hl
dec de

ld a,d
or e
jr nz, DOSNode_OutWriteStream_DACMLoop

DOSNode_OutWriteStream_DACMEnd:
ei
pop bc
pop hl
jp DOSNode_Success

; ----------------------------------------

DOSNode_OutWriteStream_SPCHA:

jp DOSNode_Success

; ----------------------------------------

DOSNode_OutWriteStream_SPCHD:

jp DOSNode_Success

;
; Close the output stream
;
; Input   - A = drive number
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then the stream was properly closed
;                If NZ then the stream was closed with an error
;                    A = error code
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_OutCloseStream:
cp Drive_VDU
jr z, DOSNode_OutCloseStream_VDU

cp Drive_PRN
jr z, DOSNode_OutCloseStream_PRN

cp Drive_DACA
jr z, DOSNode_OutCloseStream_DACA

cp Drive_DACM
jr z, DOSNode_OutCloseStream_DACM

cp Drive_SPCHA
jr z, DOSNode_OutCloseStream_SPCHA

cp Drive_SPCHD
jr z, DOSNode_OutCloseStream_SPCHD

jp DOSNode_Fail

DOSNode_OutCloseStream_VDU:
DOSNode_OutCloseStream_PRN:
DOSNode_OutCloseStream_DACA:
DOSNode_OutCloseStream_DACM:
DOSNode_OutCloseStream_SPCHA:
DOSNode_OutCloseStream_SPCHD:
jp DOSNode_Success

;
; Change the position into the output stream
;
; Input   - A = drive number
;           DEHL = new position in the ouput stream
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then the new position could be reached
;                If NZ then an error occured
;                    A = error code
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_OutSeekStream:
jp DOSNode_Fail

;
; Check that a file or directory exists and return associated information
;
; Input   - A = drive number
;           HL = pointer to the normalized name
;               If HL = 0 then it is the contents of the directory which has to be analyzed
;               and ExamineNext will be called next to retrieve each entry
;           DE = pointer to the normalized path
;           IX = buffer where to store last modification time and date
;           The pointed memory is always located in the current ROM/RAM space area
; Output  - If Carry = 1 the routine is supported for the provided drive
;
;                If HL was not 0 in input
;                    If Z then the file or directory exists
;                        A = protection bits of the file
;                            Bit 0 - Read-only
;                            Bit 1 - Hidden
;                            Bit 2 - System
;                            Bit 4 = Directory
;                            Bit 5 = Archived
;                        BCDE = Length of the file
;                        IX = buffer where last modification time and date of the entry were stored
;                            One 16-bit word with year (1978..9999)
;                            One byte with number of month (1..12)
;                            One byte with number of day in the month (1..28,29,30 or 31)
;                            One byte with hours (0..23)
;                            One byte with minutes (0..59)
;                            One byte with seconds (0..59)
;                    If NZ then the file or directory was not found
;                        A = error code
;
;                If HL was 0 in input
;                    If Z then the directory is ready to be examined through ExamineNext
;                    If NZ then an error occurred
;                        A = error code
;
;                In any case, the routine might truncate the provided normalized path to match the nearest parent
;
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_Examine:
jp DOSNode_Fail

;
; Get the next entry from a directory being examined
;
; Input   - A = drive number
;           HL = pointer to the memory where to store the normalize name
;           IX = buffer where to store last modification time and date
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then an entry was found
;                    HL = pointer to the memory updated with the found normalized name
;                        A = protection bits of the file
;                            Bit 0 - Read-only
;                            Bit 1 - Hidden
;                            Bit 2 - System
;                            Bit 4 = Directory
;                            Bit 5 = Archived
;                        BCDE = Length of the file
;                        IX = buffer where last modification time and date of the entry were stored
;                            One 16-bit word with year (1978..9999)
;                            One byte with number of month (1..12)
;                            One byte with number of day in the month (1..28,29,30 or 31)
;                            One byte with hours (0..23)
;                            One byte with minutes (0..59)
;                            One byte with seconds (0..59)
;                If NZ then an error occurred
;                    A = error code (dsk_err_file_not_found indicates that all entries were examined)
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_ExamineNext:
jp DOSNode_Fail

;
; Rename a file or a directory
;
; Input   - A = drive number
;           HL = pointer to the normalized name
;           DE = pointer to the normalized path
;           IX = pointer to the new normalized name
;           BC = pointer to the new normalized path
;           The pointed memory is always located in the current ROM/RAM space area
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then the file or directory was renamed
;                If NZ then the file or directory could not be renamed
;                    A = error code
;                In any case, the routine might truncate the provided normalized path to match the nearest parent
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_Rename: jp DOSNode_Fail

;
; Delete a file or a directory
;
; Input  - A = drive number
;           HL = pointer to the normalized name
;           DE = pointer to the normalized path
;           The pointed memory is always located in the current ROM/RAM space area
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then the file or directory was deleted
;                If NZ then the file or directory could not be deleted
;                    A = error code
;                In any case, the routine might truncate the provided normalized path to match the nearest parent
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_Delete: jp DOSNode_Fail

;
; Create a directory
;
; Input  - A = drive number
;           HL = pointer to the normalized name
;           DE = pointer to the normalized path
;           The pointed memory is always located in the current ROM/RAM space area
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then the directory was created
;                If NZ then the directory could not be created
;                    A = error code
;                In any case, the routine might truncate the provided normalized path to match the nearest parent
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_CreateDir:
jp DOSNode_Fail

;
; Change the protection bits of a file
;
; Input  - A = drive number
;           HL = pointer to the normalized name
;           DE = pointer to the normalized path
;           B = Protections to modify
;           C = New protections
;                Bit 0 - Read-only
;                Bit 1 - Hidden
;                Bit 5 = Archived
;           Other bits are ignored
;           The pointed memory is always located in the current ROM/RAM space area
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then the protections were modified
;                If NZ then the protections could not be modified
;                    A = error code
;                In any case, the routine might truncate the provided normalized path to match the nearest parent
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_SetProtection:
jp DOSNode_Fail

;
; Change last modification time and date of a file or a directory
;
; Input  - A = drive number
;           HL = pointer to the normalized name
;           DE = pointer to the normalized path
;           IX = buffer where last modification time and date to use for the entry are stored
;               One 16-bit word with year (1978..9999)
;               One byte with number of month (1..12)
;               One byte with number of day in the month (1..28,29,30 or 31)
;               One byte with hours (0..23)
;               One byte with minutes (0..59)
;               One byte with seconds (0..59)
;           The pointed memory is always located in the current ROM/RAM space area
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then the time and date were modified
;                If NZ then the time and date could not be modified
;                    A = error code
;                In any case, the routine might truncate the provided normalized path to match the nearest parent
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_SetFileDate:
jp DOSNode_Fail

;
; Format a drive
;
; Input  - A = drive number
; Output  - If Carry = 1 the routine is supported for the provided drive
;                If Z then the drive was formatted
;                If NZ then format failed
;                    A = error code
;           If Carry = 0 then the routine is invalid for the provided drive
; Altered - AF

DOSNode_Format: jp DOSNode_Fail

;
; Read the contents of the real time clock
;
; Input   - IX = buffer where to store current time and date (7 octets)
; Output  - If Carry = 1 the the DOS node handles a relax time clock
;                IX = buffer where current time and date were stored
;                    One 16-bit word with year (1978..9999)
;                    One byte with number of the month (1..12)
;                    One byte with the number of the day in the month (1..28,29,30 or 31)
;                    One byte with hours (0..23)
;                    One byte with minutes (0..59)
;                    One byte with seconds (0..59)
;                 A = number of the day in the week (1..7, from Monday to Sunday)
;           If Carry = 0 the the DOS node do not handle a real time clock
; Altered - AF

DOSNode_ReadRTC:
jp DOSNode_Fail

;
; Write into the real time clock
;
; Input   - IX = buffer containing time and date to write into real time clock (7 bytes)
;               One 16-bit word with year (1978..9999)
;               One byte with number of the month (1..12)
;               One byte with the number of the day in the month (1..28,29,30 or 31)
;               One byte with hours (0..23)
;               One byte with minutes (0..59)
;               One byte with seconds (0..59)
; Output  - If Carry = 1 then the DOS node handles a real time clock
;               If Z then the contents of the real time clock was updated
;               If NZ then an error occurred
;                   A = error code
;          If Carry = 1 then the DOS node do not handle a real time clock
; Altered - AF

DOSNode_WriteRTC:
jp DOSNode_Fail

;
; Open the non volatile memory
;
; Input  - C = opening mode
;                If 0 then the non volatile memory shall be opened with its current contents
;                If 1 then the non volatile memory shall be opened with its contents reset
; Output  - If Carry = 1 then the DOS node provides non volatile memory
;                If Z then the non volatile memory has been opened and is ready for usage
;                If NZ then a error occured
;                    A = error code
;           If Carry = 0 then the DOS node do not provide non volatile memory
; Altered - AF

DOSNode_OpenNVRAM:
jp DOSNode_Fail

;
; Close and update the non volatile memory memory contents
;
; Input  - None
; Output  - If Carry = 1 then the DOS node provides non volatile memory
;                If Z then the non volatile memory was properly updated
;                If NZ then an error occured
;           If Carry = 0 then the DOS node do not provide non volatile memory
; Altered - AF

DOSNode_CloseNVRAM:
jp DOSNode_Fail

;
; Read data from the non volatile memory
;
; Input  - HL = address where to write read data
;           DE = number of bytes to read
; Output  - If Carry = 1 then the DOS node provides non volatile memory
;                If Z then data were read
;                    DE = number of bytes read
;                If NZ then a error occured
;                    A = error code
;           If Carry = 0 then the DOS node do not provide non volatile memory
; Altered - AF,DE

DOSNode_ReadNVRAM:
jp DOSNode_Fail

;
; Write data to the non volatile memory
;
; Input  - HL = address where a located data to write
;           DE = number of bytes to write
; Output  - If Carry = 1 then the DOS node provides non volatile memory
;                If Z then data were written
;                    DE = number of bytes written
;                If NZ then a error occured
;                    A = error code
;           If Carry = 0 then the DOS node do not provide non volatile memory
; Altered - AF,DE

DOSNode_WriteNVRAM:
jp DOSNode_Fail

;
; Change the position in the non volatile memory
;
; Input  - DEHL = new position
; Output  - If Carry = 1 then the DOS node provides non volatile memory
;                If Z then the new position was reached
;                If NZ then a error occured
;                    A = error code
;           If Carry = 0 then the DOS node do not provide non volatile memory
; Altered - AF,DE

DOSNode_SeekNVRAM:
jp DOSNode_Fail

DOSNode_Void: ret

DOSNode_Fail: ccf
ret

DOSNode_Success:
scf
ret

; ------------------------- ListGetIDByName
; -- parameters:
; -- HL = address of list to find a string within
; -- DE = string to find
; --
; -- return:
; -- Z if found, NZ if not
; -- A = entry number of found item
; -- all other registers unknown

ListGetIDByName:
ld a, (hl)
or a
jr z, ListGetIDByNameNotFound

push de
push hl
call StrCompare
pop hl
call StrSkip
pop de

jr z, ListGetIDByNameFound

inc hl
inc hl
jr ListGetIDByName

ListGetIDByNameFound:
inc hl
ld a, (hl)
ret

ListGetIDByNameNotFound:
xor a
ret

; ------------------------- StrCompare
; -- parameters:
; -- HL = zero terminated string source of truth
; -- DE = string to compare
; --
; -- return:
; -- Z if equal, NZ if not
; -- all other registers unknown

StrCompare:
StrCompareLoop:
ld a, (hl)
or a
ret z ; found it, return

call ToUpper
and #7f

push af
ld a, (de)
call ToUpper
and #7f
ld b, a
pop af

cp b
ret nz ; didnt find it, return
inc hl
inc de
jr StrCompareLoop

; ------------------------- ToUpper
; -- parameters:
; -- A = character to make into uppercase
; --
; -- return:
; -- A = uppercase character
; -- all other registers preserved except flags

ToUpper: cp 'a'
ret c
cp 'z' + 1
ret nc
add a, 'A' - 'a'
ret

; ------------------------- StrCopy
; -- parameters:
; -- HL = source string address
; -- DE = destination string address
; --
; -- return:
; -- HL = the address of the source string terminator
; -- DE = the address of the destination string terminator
; -- all other registers unknown

StrCopy:
ld a,(hl)
ld (de), a
or a
ret z ; end of string return
inc hl
inc de
jr StrCopy

StrSkip: push af

StrSkipLoop:
ld a,(hl)
or a
jr z, StrSkipEnd
inc hl
jr StrSkipLoop

StrSkipEnd: pop af
ret

; ------------------------- ValidateChar
; -- parameters:
; -- A = character to validate
; --
; -- return:
; -- C if valid, NC if not
; -- all other registers preserved

ValidateChar:
cp ' '
jr c, DOSNode_Fail

cp 'z'
jr nc, DOSNode_Fail

jp DOSNode_Success

CODE_END: ; ds #4000 - (CODE_END - CODE_START)

; save "STREAMER.ROM", #C000, #4000, AMSDOS

zhulien

BTW, after thought I am leaning towards virtual folders to group device types, such as AUDIO and put the virtual files under there for the streams.

Highly wanted suggestions for the main unidos core:

|s alias sys: for a configured system drive, e.g. we can assign m4: or ide: or whatever to be a system drive which then has an internal alias as sys: also which is preserved in NVM.  This allows us to know what drive is a nominated system drive.

|nvramsave and |nvramrestore for backing it up and/or transferring to other machines.  Separate external utility nvram which takes the saved nvram file and lists info such as which apps, which owners of segments etc...

I am thinking hard on this one... what is the most elegant way to implement piping and redirection.  

What is the current capacity of the nvram per node and did you go ahead with an allocation scheme or can you allocate a slot for me for this node.  Tentatively called streamer.  Perhaps that more stuff can be a separate node.  Tentatively memory manager.  

Soon people will be able to program in basic with some type of device independence for asset storage in extra memory, blitting to screen (and hopefully also v9990) without any of the 42k ram gone or worrying about banking.


OffseT

Quote from: zhulien on 10:04, 23 June 23hmm, GetName is called 8 times, I return C for 6 (now as I have 6 drives), and 2 NC.  Then it calls GetDesc not only for my 6 drives, but also for the 3 drives that are not even related to my Node.
You are right. When |DRIVE is issued, GetName is first called for drives 0-7.
Then CheckDrive will be called for each retrieved device name from GetName.
Then CheckStatus will be called for each retrieved device id from CheckDrive.
Then GetFreeSpace & GetDesc will be called for each device with a media inserted.

So, if your have additional calls, you may return C from CheckDrive when not expected. Unexpected behavior may also happen if your node (or another one) alters forbidden registers.

BTW, what do you mean by "drives that are not related to my node"?
All 0-7 drives are private to your node.

OffseT

Quote from: zhulien on 02:26, 23 June 23If I do a cat on a write only DOS node, I get a Bad Command.
You need to implement minimal Examine/ExamineNext if you want to avoid this error.

OffseT

Quote from: zhulien on 11:32, 23 June 23|s alias sys: for a configured system drive,
Yup, that's the plan!
SYS: alias is already in my todo list. It will come with extended assign support feature. ;)

OffseT

Quote from: zhulien on 11:32, 23 June 23What is the current capacity of the nvram per node
nvram data is at least 2K. But it is totally private to UniDOS atm.
There are plans to add CTRL-J BIOS APIs so that external application could use it, but I still need to figure out what would be the good way to do so.

I first need to finalize extended assign support (both features are somewhat related internally).

OffseT

Quote from: zhulien on 11:32, 23 June 23I am thinking hard on this one... what is the most elegant way to implement piping and redirection.  
According to me the simplest way would be a PIPE: drive working as a FIFO.
To start with, it could allocate system memory to store data, and later it could use the temporary data storage service planned in UniDOS.

OffseT

Quote from: zhulien on 10:04, 23 June 23There are only 8 devices in a Node, of course we can have lots of nodes
Yep, current limitation is 8 nodes from 32 nodes, which makes 256 drives max (8-bit data).
It won't change until a major release because all the internal design as well as AMSDOS compatibility relies on a drive id which can fit in 8 bits.

As you suggested, having a sort of virtual path to dispatch streams might be the best idea to reduce the number of nodes. That said, I'm not sure that having a lot of nodes is an issue even if some of them are almost empty.

OffseT

Quote from: zhulien on 11:32, 23 June 23Soon people will be able to program in basic with some type of device independence for asset storage in extra memory, blitting to screen (and hopefully also v9990) without any of the 42k ram gone or worrying about banking.
Sounds great!

zhulien

Quote from: OffseT on 16:04, 23 June 23
Quote from: zhulien on 11:32, 23 June 23|s alias sys: for a configured system drive,
Yup, that's the plan!
SYS: alias is already in my todo list. It will come with extended assign support feature. ;)
If you implement SYS:  Then the NVRAM is less needed as we could store config info in a SYS:UNIDOS folder for each node, perhaps we could standardise on node names for filenames.  If SYS: is also implemented then it will make my virtual memory more reliable than without - as e.g. SYS: could be nominated to IDE: regardless of which other drives are assigned to A and B.


zhulien

Here is the oddity I am getting with the descriptions:

zhulien

Perhaps Stream devices could be listed in their own section?  But I'm ok either way.  If I consolidate them to virtual folders / files, then they will become less.

OffseT

Quote from: zhulien on 17:52, 23 June 23Here is the oddity I am getting with the descriptions:
Hmmm, looks like a display issue... This is typically what could happen if one of your DOSNode_* API is modifying a register which is not allowed (i.e. a register which is not lister as "Altered" in routine header). You may want to double check this.

If everything is ok on your side, please send me your node ROM file so that I could check what happens with the UniDOS |DRIVE display routine.

OffseT

Quote from: zhulien on 17:53, 23 June 23Perhaps Stream devices could be listed in their own section?  But I'm ok either way.  If I consolidate them to virtual folders / files, then they will become less.
Yep, that's a good idea. Drives could be displayed in two separated lists. I add this to my todo list.

zhulien

#290
Do you have a simple example of how Examine and ExamineNext work?  The documentation for Examine doesn't mention copying anything to the buffer, but ExamineNext does - however if i look at DOSNode.a sourcecode, it appears that both might be copying to the buffer.

Examine - Check that a file or directory exists and return associated information

I am guessing that if HL = 0, then we return Z and C to force ExamineNext to get at least the first directory to examine.  What else calls ExamineNext to be called?

ld a, 1 ; test code
ld (#be80), a

ld a, h ; examine directory via ExamineNext
or l ;
jp z, DOSNode_Success ;

; do something else
xor a
ld a, %00010000
ld bc, 0
ld de, 0

jp DOSNode_Success


ExamineNext - Get the next entry from a directory being examined

If ExamineNext is called, how do i know where I am so far in a list of directory entries to return?  As I am returning 1 at a time.

ld a, (#be80)
or a
jp z, DOSNode_Fail

dec a
ld (#be80), a

ld de, DIRNAME
ex de, hl
ld bc, 11
ldir

xor a
ld a, %00010000
ld bc, 0
ld de, 0
jp DOSNode_Success

DIRNAME: db "TESTFILE   "

This example was for me just to try get it to list 1 hardcoded filename, but it gets stuck calling ExamineNext indefinitely.  The counter in #be80 was only to try force it to change behaviour after 1.  I must be not understanding the way the 2 functions work.

OffseT

Quote from: zhulien on 19:13, 23 June 23Do you have a simple example of how Examine and ExamineNext work?
You can check the source code of Albireo node which is simple enough regarding catalog handling.

Anyway, the sequence is:
Call Examine with HL=0 to start examination of directory pointed by DE.
Call ExamineNext for each entry until it returns with C/NZ and A=dsk_err_file_not_found.

This is very similar to APIs from other operating systems to explore directory contents. It is up to the node to manage the current entry and the examination termination. Private data area to be used for Examine/ExamineNext management is located at (DOS_ROM_BASE_ADDRESS)+&3D0 and is &80 bytes long (which is usually far than enough).

All detailed are here:
https://unidos.cpcscene.net/doku.php?id=en:nœud_dos#routines_analyzing_files_and_directories

I hope it helps.

zhulien

Thanks, seems to be me not returning the correct statuses in this case.  I still didn't resolve the description coming back for "other" nodes, but I can look into that again later when this Node becomes more functional.

zhulien

Hi @OffseT is there any chance you can put a sys: or similar drive or is there one ready so that I can read a config file in my stream ROM.  Or... would you prefer I use the NVM somehow?  I could let someone make a config file and provide an rsx to load a form of its content into NVM.

OffseT

Quote from: zhulien on 18:25, 03 August 23Hi @OffseT is there any chance you can put a sys: or similar drive or is there one ready so that I can read a config file in my stream ROM.  Or... would you prefer I use the NVM somehow?  I could let someone make a config file and provide an rsx to load a form of its content into NVM.
SYS: (or whatever name that will be used) is planned, not ready yet, because I have some preliminary work to do before (basically parts of UniDOS ROM are to be moved to UniTools ROM to save place for core features).

Btw, I should be able to release a new version before end of this year (including this feature plus some others).

poulette73

Hi OffSet,

Don't know if you see on CPCRulez but I found an issue with UniDOS few weeks ago.

OffseT

Quote from: poulette73 on 12:21, 05 August 23Hi OffSet,

Don't know if you see on CPCRulez but I found an issue with UniDOS few weeks ago.
I actually missed this post, thank you for pointing me out.
I just answered on CPCRulez.
That's not a bug, that's a feature. 8)

GUNHED

As I understood, the Unidos is supposed to serve all mass storage devices.

Here my question: Is it planned to support the Dobbertin HD20 hard-disc?
(BTW: The HD20 is now emulated by the Symbiface 3 / RSF3).
http://futureos.de --> Get the revolutionary FutureOS (Update: 2023.11.30)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> Get the RSX-ROM for LambdaSpeak :-) (Updated: 2021.12.26)

Prodatron

Quote from: GUNHED on 18:02, 06 August 23Is it planned to support the Dobbertin HD20 hard-disc?
As nobody owns this device in real, there is no need for a support, and emulators also don't support it.
But why don't you write a UniDOS driver for it, if it's so important for you?

GRAPHICAL Z80 MULTITASKING OPERATING SYSTEM

GUNHED

#299
Quote from: Prodatron on 22:44, 06 August 23
Quote from: GUNHED on 18:02, 06 August 23Is it planned to support the Dobbertin HD20 hard-disc?
As nobody owns this device in real, there is no need for a support, and emulators also don't support it.
But why don't you write a UniDOS driver for it, if it's so important for you?
Well, I know at least five guys who own it. Four of them are visiting this place sometimes, some more often, some frequently. There is quite some interest.

It's imho very important, because of all the software for it. Perfect implementation for the native OS, for CP/M 2.2, for CP/M Plus and for the Z-System!!! (and other OS too, yes f.e. FutureOS). And in addition some bigger software projects are using it. (COSMOS f.e.). Have a look at the Wiki.
http://futureos.de --> Get the revolutionary FutureOS (Update: 2023.11.30)
http://futureos.cpc-live.com/files/LambdaSpeak_RSX_by_TFM.zip --> Get the RSX-ROM for LambdaSpeak :-) (Updated: 2021.12.26)

Powered by SMFPacks Menu Editor Mod