Previous Page > Hardware index > Deep Thought ACE DOS code listing.
Archive Search  

Deep Thought ACE DOS code listing.

The DOS system was written by Jeff Shepherd.


; *********************************************************
; ***	                                                ***
; ***	            Jump Table                          ***
; ***	                                                ***
; *********************************************************

Find-index          JP $F900          ; $F800
Find-header         JP $F923          ; $F803
Save-block          JP $F953          ; $F806
Load-block          JP $F9D0          ; $F809
Wait                JP $FA03          ; $F80C
On                  JP $FA0D          ; $F80F
Off                 JP $FA24          ; $F812
Setup               JP $FA2B          ; $F815
Step                JP $FA64          ; $F818
Step-out            JP $FA62          ; $F81B
DRIVE               JP $FA74          ; $F81E
Print               JP $FA86          ; $F821
Track00             JP $FAAS          ; $F824
Save-cat            JP $FAB1          ; $F827
Load-cat            JP $FAC3          ; $F82A
Print-error         JP $FAE7          ; $F82D
XFORMAT             JP $FB0A          ; $F830
Save-file           JP $FB31          ; $F833
Load-file           JP $FB6D          ; $F836
Find-word           JP $FBA6          ; $F839
Enter-word          JP $FBDS          ; $F83C
Lookup-word         JP $FC18          ; $F83F
Hex-byte            JP $FC2C          ; $F842
Hex-char            JP $FC35          ; $F845
CAT                 JP $FC41          ; $F848
Dict-size           JP $FCCA          ; $F84B
Block-length        JP $FCD4          ; $F84E
Delete file         JP $FCDF          ; $F851
DELETE              JP $FD19          ; $F854
Error-?             JP $FD2A          ; $F857
Store               JP $FD35          ; $F85A
DSAVE               JP $FD65          ; $F85D
DBSAVE              JP $FD70          ; $F860
DBLOAD              JP $FD90          ; $F863
RESAVE              JP $FDB2          ; $F866
Word                JP $FDC3          ; $F869
MAP                 JP $FDD0          ; $F86C
DLOAD               JP $F880          ; $F872
SCRATCH             JP $F8D5          ; $F875
Fill-length         JP $FDF0          ; $F878


; *********************************************************
; ***                                                   ***
; ***               Constants                           ***
; ***                                                   ***
; *********************************************************

Acia-status     EQU  $21        ; Acia status register.
Acia-in         EQU  $23        ; Acia data input register.
Acia-control    EQU  $01        ; Acia control register.
Acia-out        EQU  $03        ; Acia data output register.

Pia-a-i         EQU  $29        ; PIA port A data input.
Pia-a-o         EQU  $09        ; PIA port A data output.
Pia-b-o         EQU  $0D        ; PIA port B data output.
Pia-a-cr        EQU  $0B        ; PIA port A control register.
Pia-b-cr        EQU  $0F        ; PIA port B control register.

Dos-words       EQU  $FFFD      ; Address of name length field
                                ; of first DOS FORTH word.
Forth-link      EQU  $3C47      ; Address of the link field
                                ; of the word FORTH.
Cat-size        EQU  $F8FE      ; Address of the first of two
                                ; bytes holding the length
                                ; of the cat in bytes + 1.
Message-space   EQU  $FE30      ; Address of the first string
                                ; used by Print.
Pad             EQU  $2701      ; Address of the Forth PAD
RAMTOP          EQU  $3C18      ; Hold the address of the highest
                                ; byte used by the Jupiter Ace.
                                ; The drive number is stored at
                                ; (RAMTOP). The cat starts at
                                ; (RAMTOP) + 1.
                                ; where a word read by WORD
                                ; is placed.
Enter-forth     EQU  $4B9       ; Enter forth from machine code.
WORD            EQU  $5AB       ; Parameter field address of WORD.
End-forth       EQU  $1A0E      ; Forth word to enter Z-80 code.



 
; *********************************************************
; ***                                                   ***
; ***               Find-index                          ***
; ***                                                   ***
; *********************************************************


; * Waits for the index hole to pass.

; * No arguments or results
; * DE and HL preserved.
; * Can give "Wot no disk" or "Wot no index hole".

; * Calls: None
; * Called by: Find-header and Save-block.


            ; First, loop till high, then loop till low.

            LD BC,$7D00             ; Time out count.
Whilelo     DEC BC                  ; Decrease count
            LD A,B                  ; and test
            OR C                    ; for zero.
            LD A,3                  ; If zero then call Error-?
            CALL Z,Error-?          ; with 3 for "Wot no disk".
            IN A, (Pia-a-i)
            AND 1                   ; Test bit 0.
            JR Z,Whilelo            ; Loop till high.

            LD BC,$7D00             ; Time out count.
Whilehi     DEC BC                  ; Decrease count
            LD A,B                  ; and test
            OR C                    ; for zero.
            LD A,4                  ; Error 4 is
            CALL Z,Error-?          ; "Wot no index hole"
            IN A, (Pia-a-i)
            AND 1                   ; Test bit 0.
            JR NZ,Whilehi           ; Loop till low.
            RET



 
; *********************************************************
; ***                                                   ***
; ***               Find-header                         ***
; ***                                                   ***
; *********************************************************

; * Waits for the index hole to pass and then reads
; * the header which is a sequence of $FF's followed by
; * a 42.

; * A=0 if header found in time.
; * A=5 if header not found.
; * DE and HL preserved.
; * Can give "Wot no disk" or "Wot no index hole".

; * Calls: Find-index.
; * Called by: Load-block and Save-block.

            CALL Find-index
            LD BC,$7D00             ; Time out count.
 NotFF      DEC BC                  ; Decrease count
            LD A,B                  ; and test for zero.
            OR C
            LD A,5                  ; Return with 5 if zero.
            RET Z
            IN A,(Acia-status)
            AND 1                   ; Test Read-full bit.
            JR Z,NotFF              ; Loop if not ready.
            IN A,(Acia-in)          ; Read byte from disk.
            CP $FF
            JR NZ,NotFF             ; Loop while byte is FF.

IsFF        DEC BC                  ; Check for timeout
            LD A,B                  ; again as before.
            OR C                    ; Test for zero.
            LD A,5                  ; Return 5 for "Wot no header"
            RET Z                   ; if zero.
            IN A,(Acia-status)
            AND 1                   ; Test Read-full bit.
            JR Z,IsFF               ; Loop if not ready.
            IN A,(Acia-in)          ; Read byte from disk.
            CP $FF
            JR Z,IsFF               ; Loop while byte is FF.
            CP 42                   ; If its not FF and
            JR NZ,NotFF             ; its not 42, look for a FF again.
            XOR A                   ; Clear A (No error).
            RET



 
; *********************************************************
; ***                                                   ***
; ***               Save-block                          ***
; ***                                                   ***
; *********************************************************

; * Saves a single block of data and then verifies it against
; * memory. Assumes that the head is at the correct track.

; * On entry, HL = start address of data to be saved,
;             DE = number of bytes to be saved.

; * Calls: Wait, Find-header and Find-index.
; * Called by: Save-cat and Save-file.

            IN A,(Pia-a-i)          ; Test write-protect
            AND 4                   ; line.
            LD A,6                  ; Give "Disk is write protected"
            CALL Z,Error-?          ; if line low.
                                    ; (Assumes disk enabled).
            LD C,20                 ; Wait for 20ms,
            CALL Wait               ; for head to settle.

            DI                      ; Disable interrupts,
                                    ; Writing is time dependant.
            CALL Find-index

            PUSH DE                 ; Save start and length
            PUSH HL                 ; for verify.

            LD A,%10110111          ; Motor on, write enable.
            OUT (Pia-a-o),A

            LD C,2                  ; Wait for lms to set
            CALL Wait               ; blank at start of track.

            LD B,8                  ; Write 8 $FFs onto disk.
NextFF      IN A, (Acia-status)     ; Test ready for data.
            AND 2
            JR Z,NextFF             ; Loop till ACIA ready.
            LD A,$FF
            OUT (Acia-out),A
            DJNZ NextFF             ; Repeat for other bytes.

            ; B has been set to zero a this point as it
            ; is used as checksum.

Wait42      IN A,(Acia-status)      ; Write a single 42,
            AND 2                   ; first waiting
            JR Z,Wait42             ; for ACIA ready.
            LD A,42
            OUT (Acia-out),A

            ; Now store the data.

Mainst      IN A, (Acia-status)     ; Wait for
            AND 2                   ; ACIA ready.
            JR Z, Mainst

            LD A, (HL)              ; Get byte form data.
            OUT (Acia-out),A        ; Write it to disk.
            ADD B                   ; Add it to check sun so far,
            LD B,A
            INC HL                  ; Point to next byte in data.
            DEC DE                  ; One less byte to be written.
            LD A,D                  ; Loop
            OR E                    ; till
            JR NZ,Mainst            ; count zero.

            ; Write check sun at end.

Checkw      IN A, (Acia-status)     ; Wait for
            AND 2                   ; ACIA ready.
            JR Z,Checkw
            LD A,B                  ; Write checksum.
            OUT (Acia-out),A

            LD C,1                  ; Wait 1ms for ACIA to
            CALL Wait	            ; finish writing last bytes.

            LD A,%10111111          ; Motor on, write disable.
            OUT (Pia-a-o),A

            POP HL                  ; Recover start and length.
            POP DE

            ; Verify data.

            CALL Find-header
            CALL Error-?            ; Error if header not found.

Vloop       IN A, (Acia-status)     ; Wait for data
            LD C,A                  ; keeping status for possible
            AND 1                   ; error message.
            JR Z,Vloop

            IN A,(Acia-in)          ; Get byte from disk.
            CP (HL)                 ; Is it the same as memory ?
            LD A,2                  ; Raise "Verify error" if not.
            CALL NZ,Error-?

            LD A,C                  ; Test for error from ACIA.
            AND %1110000            ; Framing, parity or overrun.
            CALL NZ,Error-?

            INC HL                  ; Point to next byte in data.
            DEC DE                  ; One less byte to be checked.
            LD A,D                  ; Loop
            OR E                    ; till
            JR NZ,Vloop             ; count zero.

            ; Checksum not read.

            EI
            RET

 
; *********************************************************
; ***                                                   ***
; ***               Load-block                          ***
; ***                                                   ***
; *********************************************************

; * Loads a single block of data.
; * Assumes that the head is at the correct track.

; * On entry, HL = start address to load data at.
; *           DE = number of bytes to be loaded.
; *                 (must be the same as when saved).
; * On exit, A = error number, 0 if no error.

; * Calls: Wait and Find-header.
; * Called by: Load-cat and Load-file.

            LD C,20                 ; Wait for 20ms,
            CALL Wait               ; for head to settle.
            DI                      ; Disable interrupts,
                                    ; Loading is time dependant.

            CALL Find-header
            OR A                    ; Test for not error (=0).
            RET NZ                  ; Return if error in finding header.

            LD B,A                  ; B := 0, Zero checksum to start with.

Loadlop     IN A, (Acia-status)     ; Wait for data
            LD C,A                  ; keeping status for possible
            AND 1                   ; error message.
            JR Z,Loadlop

            IN A, (Acia-in)         ; Get byte from disk.
            LD (HL),A               ; Store it into memory.
            ADD A,B                 ; Checksum so far.
            LD B,A

            LD A,C                  ; Test for error from ACIA.
            AND %1110000            ; Framing, parity or overrun.
            JR NZ,IntoffR           ; Return if error.

            INC HL                  ; Point to next byte in data.
            DEC DE                  ; One less byte to be loaded.
            LD A,D                  ; Loop
            OR E                    ; till
            JR NZ,Loadlop           ; count zero.

            ; Load and check checksum.
            ; ACIA error not checked on checksum read.

LChLoop     IN A, (Acia-status)     ; Wait for data
            AND 1
            jR Z,LChLoop
            IN A, (Acia-in)         ; Checksum from disk.
            CP B                    ; Compare with sum calculated.
            ID A,1                  ; Error 1 if not the same.
            JR NZ,IntoffR
            XOR A                   ; A := 0 for no error.

IntoffR     EI
            RET



 
; *********************************************************
; ***                                                   ***
; ***               Wait                                ***
; ***                                                   ***
; *********************************************************

; * Waits a specified number of milli seconds.
; * Depends on a Z-80 clock of 3.25 MHz.

; * On entry, C is the time to be waited in ms.
; * BC,DE,HL and A are preserved.

; * Calls: None.
; * Called by: Load-block, Save-block, On and Step.

            PUSH BC                 ; Must be the same on exit.
Wait1       LD B,$FA                ; Loop lasting 1ms.
Wait        DJNZ Wait2
            DEC C                   ; Repeat the number in C times.
            JR NZ,Waitl
            POP BC
            RET

 
; *********************************************************
; ***                                                   ***
; ***               On                                  ***
; ***                                                   ***
; *********************************************************

; * Switchs the drive motor on and then, after a delay,
; * selects the drive.

; * No arguments or results.
: * Uses HL, A, C

; * Calls Wait.
; * Called by: Load-cat, XFORMAT.

            LD A,%10111111          ; Motor on.
            OUT (Pia-a-o),A

            LD C,255                ; Wait about half a second.
            CALL Wait
            CALL Wait

            LD HL, (RAMTOP)         ; Point to first byte
            LD A, (HL)              ; reserved for disk.
                                    ; This is setup by DRIVE.
            OUT (Pia-b-o),A         ; Select drive.
            LD C,$40                ; Wait for head load.
            JP Wait


  
; *********************************************************
; ***                                                   ***
; ***               Off                                 ***
; ***                                                   ***
; *********************************************************

; * Switchs the drive motor off and selects no drive.

; * No arguments or results.
; * Uses A only.

; * Calls: None.
; * Called by: XFORMAT,Save-cat,Error-?,CAT,LD and BLD.

            LD A,%11111111          ; All high (disabled).
            OUT (Pia-b-o),A         ; Deselect drive.
            OUT (Pia-a-o),A         ; Motor off.
            RET



 
; *********************************************************
; ***                                                   ***
; ***               Setup                               ***
; ***                                                   ***
; *********************************************************

; * Initializes PIA and ACIA,
; * and then allocates RAM for the cat and sets to drive 0.

; * Calls: Wait.
; * Called by: None.

            LD BC, (Catsize)        ; HL = top of detected RAM.
            OR A                    ; Clear carry.
            SBC HL, DE
            LD (RAMTOP),HL
            LD SP, HL
            LD (HL),$FD             ; Drive 0.
            LD C,100                ; Wait 0.1s for PIA reset
            CALL Wait               ; to be high.
            LD B,A

            ; First initialise PIA.

            XOR A                   ; A := 0
            OUT (Pia-a-cr),A        ; Set both control registers
            OUT (Pia-b-cr),A        ; to allow access to direction
                                    ; control registers.
            DEC A                   ; A := $FF
            OUT (Pia-b-o),A         ; All lines output for port B.
            LD A,%11111000          ; Three lines input for
            OUT (Pia-a-o),A         ; port A.
            LD A,4                  ; Set both control registers
            OUT (Pia-a-cr),A        ; to allow access to
            OUT (Pia-b-cr),A        ; data registers.
            LD A,$FF                ; Set all outputs high (inactive).
            OUT (Pia-a-o),A
            OUT (Pia-b-o),A

            ; Initialise ACIA.

            ID A,3                  ; Reset ACIA.
            OUT (Acia-control),A
            LD A,%11100             ; Set ACIA to 9-bit parity.
            OUT (Acia-control),A

            LD A,B
            JP $32                  ; Resume startup.






  
; *********************************************************
; ***                                                   ***
; ***               Step-out                            ***
; ***                                                   ***
; *********************************************************

; * Steps head one track further out.

; * No arguments or results.
; * DE and HL preserved.

; * Calls: Wait.
; * Called by: Save-cat, Load-cat, Save-file and Load-file.

                LD A,%10101111	    ; Direction and motor on low.

                ; Implicit CALL Step and RET.





  
; *********************************************************
; ***                                                   ***
; ***               Step                                ***
; ***                                                   ***
; *********************************************************

; * Steps head in or out depending on argument.

; * Step in if A = %10111111.
; * Step out if A = % 10101111.
; * DE and HL preserved.

; * Calls: Wait.
; * A Called by: Step-out and Track00.

            OUT (Pia-a-o),A         ; Specify direction.
            LD C,5                  ; Can do one step every 5ms.
            CALL Wait
            SUB %100000             ; Pull step low.
            OUT (Pia-a-o),A
            ADD %100000             ; And then high again.
            OUT (Pia-a-o),A
            RET


 
; *********************************************************
; ***                                                   ***
; ***               DRIVE                               ***
; ***                                                   ***
; *********************************************************

; * Forth word to select drive and side.
; * Least significant bit of number on parameter stack
; * gives side, next two bits give drive number.


                RST 24              ; Pop DE from parameter stack.

                ; Convert number to correct form for PIA register.
                ; A := not((E and 1) | (1 << (E >> 1))).

                LD A,%11111110
                LD B,E
                INC B
drlab1          RLCA
                DEC B
                JR Z,drlab2
                DJNZ drlabl
                DEC A

                ; Store it in the first byte above RAMTOP.

drlab2          LD HL, (RAMTOP)
                LD (HL),A
                JP (1Y)             ; Forth return.





 
; *********************************************************
; ***                                                   ***
; ***               Print                               ***
; ***                                                   ***
; *********************************************************

; * Prints a text message specified by a number in A.
; * A The text store used has message arranged consecutively
; * in order of increasing number.
; * 00 is used to separate message.
; * Characters with codes > 127 are interpreted as messages
; * to be inserted recursively.
; * This method of store is used to save memory as many
; * messages are similar.

; * On entry A= message number.

; * Calls: none.
; * Called by:

                LD DE,message-space ; Start of message store.
                LD B,A              ; Count 00's the number in A.
Prsrch          LD A,(DE)
                INC DE
                OR A                ; Test zero.
                JR NZ,Prsrch
                DJNZ Prsrch

Prloop          LD A,(DE)           ; First character of message.
                INC DE              ; point to next character.
                OR A                ; Test for zero which
                RET Z               ; marks the end.
                LD B,A              ; See if the top bit is set.
                AND $7F             ; Making a copy with the
                CP B                ; top bit clear at the same time.
                OR Z,Prwrch         ; If bit not set print as character.
                PUSH DE             ; Else call Print recursively.
                CALL Print
                POP DE
                JR Prloop

Prwrch          RST 8              ; Wrch.
                JR Prloop


 
; *********************************************************
; ***                                                   ***
; ***               Track00                             ***
; ***                                                   ***
; *********************************************************

; A Moves head to track zero.

; * No args or results.
; * DE and HL preserved.

: * Calls: Step.
; * A Called by: Save-cat and Load-cat.

Trk001p         IN A,(Pia-a-i)          ; Input lines
                AND 2                   ; track00 bit.
                RET Z                   ; Quit if already at track00.
                LD A,%10111111          ; For step in.
                CALL Step
                JR Trk001p              ; Test again.



; *********************************************************
; ***                                                   ***
; ***               Save-cat                            ***
; ***                                                   ***
; *********************************************************

: * Saves the cat to disk.
; * No args or results.

: * Calls Track00,Dictsize,Save-block,Step-out.
; * Called by: STORE,RESTORE,BSTORE,XFORMAT and DELETE.

            CALL Track00
            CALL Dictsize
            CALL Save-block             ; Save first copy on track 0.
            CALL Step-out
            CALL Dictsize
            JP	Save-block              ; Save second copy on track 1.






; *********************************************************
; ***                                                   ***
; ***               Load-cat                            ***
; ***                                                   ***
; *********************************************************

; * Loads the cat from disk after switching on the drive.

; * No args or results.

; * Calls: On,TrackOO,Dictsize, Load-block, Step-out,Print,
           Print-error and Error-?
; * Called by: STQRE/RESTORE,BSTORE,LD,BLD,CAT and DELETE.

              CALL On
              CALL Track00
              CALL Dictsize           ; Load first copy.
              CALL Load-block
              PUSH AF
              CALL Step-out           ; Move to track 1.
              POP AF
              OR A
              RET Z                   ; Return if no error.
              CALL Print-error
              LD A,$18                ; "Second cat read".
              CALL Print
              CALL Dictsize
              CALL Load-block         ; Load second copy.
              JP Error-?


 
; *********************************************************
; ***                                                   ***
; ***               Print-error                         ***
; ***                                                   ***
; *********************************************************

; * If A holds an error number, it prints the error.
; * Otherwise, it has no effect.

; * On entry A = error number.

                OR A                ; Test for A = 0
                RET Z               ; Return if so.
                LD B,A              ; Error number in B.
                LD A,$0D            ; Print carriage return.
                RST 8               ; Wrch.

                LD A,B
                AND $70             ; Test for ACIA error.
                JR Z,Erknown        ; Skip if it isn't.
                LD B,$12
                LD C,A
                AND $40
                JR NZ,Erknown       ; Parity error.
                DEC B
                LD C,A
                AND $20
                JR NZ,Erknown       ; Overrun error.
                                    ; (Should be impossible).
                DEC B               ; Else, Framing error.
Erknown         LD A,B
                ADD 5               ; Errors start a message 5.
                CALL Print
                LD A,$0D            ; Print carriage return.
                RST 8               ; Wrch.
                RET



 
; *********************************************************
; ***                                                   ***
; ***                 XFORMAT                           ***
; ***                                                   ***
; *********************************************************

; * Forth word to write a blank catalogue to disk.
; * This specifies the block length and number of tracks.

; * Top of the parameter stack is the number of track.
; * Next on the parameter stack is the number of bytes
; * per track.

                CALL On
                RST 24              ; Pop DE from parameter stack.
                LD A,E              ; Only least significant byte.
                RST 24              ; Pop DE from parameter stack.

                LD HL,(RAMTOP)
                INC HL              ; First byte of cat.
                LD (HL),A           ; Number of tracks.
                INC HL
                LD (HL),E           ; Number of bytes per track.
                INC HL
                LD (HL),D
                INC HL

                LD (HL),0           ; Rest of the cat is filled
                LD D,H              ; with zeros.
                LD E,L
                INC DE
                LD BC, (Cat-size)
                DEC BC
                DEC BC
                DEC BC
                DEC BC
                LDIR

                CALL Save-cat
                CALL Off
                JP (IY)             ; Forth return.


  
; *********************************************************
; ***                                                   ***
; ***                 Save-file                         ***
; ***                                                   ***
; *********************************************************

; * Saves an area of memory to disk.
; * Doesn't read or alter the disk catalogue.

; * On entry:   HL = starting address of the memory to be saved.
; *             DE = the number of bytes to be saved.
; *              B = the file number of the file to be created.

: * Calls: Block-length,Step-out and Save-block.
; * Called by: STORE, BSTORE and RESTORE.


                LD C,2              ; Offset from (RAMTOP)+l of byte
                                    ; below start of track file table.
Sfnextb         PUSH HL             ; Save start address,
                PUSH DE             ; length.

Sfnextt         LD HL,(RAMTOP)
                INC HL              ; Load number of tracks.
                LD A, (HL)

                CP C                ; If the previous tack number
                LD A,$A             ; was equal to the limit, raise
                CALL Z,Error-?      ; a "Disk is full" error.

                PUSH BC             ; Move head to next track.
                CALL Step-out
                POP BC              ; Only BC was corrupted
                                    ; in Step-out.

                INC C               ; Pointer to table slot for
                                    ; this track.

                LD D,0              ; Calculate address in the cat
                LD E,C              ; of this tracks file entry.
                ADD HL,DE
                LD A,(HL)           ; The file for this track.
                OR A                ; Is it empty (=0) ?
                JR NZ,Sfnextt       ; If it isn't, try next track.

                LD (HL),B           ; If it is, claim it for this file.

                POP HL              ; HL := file length.
                POP DE              ; DE := start address.
                PUSH BC             ; Save BC.
                PUSH DE             ; Save start address.
                CALL block-length   ; DE := block length.

                OR A                ; CY := 0
                SBC HL,DE
                JR Z,Sfend          ; If file is exactly one block.
                JR C,Sfend          ; If file less than one block.

                 EX (SP),HL

                ; At this point, HL - start address,
                ; DE = block length, and remaining file length
                ; and track and file numbers saved.

                CALL Save-block     ; Leaves HL pointing to start
                                    ; of next block.

                POP DE              ; Save remaining file.
                POP BC
                JR Sfnextb

Sfend           ADD HL,DE           ; File was shorter than a block
                                    ; so make length positive again.
                EX DE,HL            ; DE := length still to be saved.
                POP HL              ; HL := start address.

                CALL Save-block
                POP BC
                RET



  
; *********************************************************
; ***                                                   ***
; ***               Load-file                           ***
; ***                                                   ***
; *********************************************************

; * Loads a file into an area of memory.
; * Doesn't read or alter the disk catalogue.
; 
; * On entry: HL = the starting address of the memory.
; *           DE = the number of bytes to be loaded
; *            B = the file number of the file to be loaded.

; * Calls: Block-length, Step-out and load-block.
; * Called by: LD,RUN and BLD.

              LD C,3                ; Offset from (RAMTOP) of the byte
                                    ; below start of track file table.
Lfnextb       PUSH HL               ; Save start address,
              PUSH DE               ; length.

Lfnextt       PUSH BC               ; Move head to next track.
              CALL Step-out
              POP BC                ; Only BC was corrupted in Step-out

              INC C                 ; Pointer to slot for this track.

              LD HL,(RAMTOP)
              LD D,O                ; Calculate the address in the cat
              LD E,C                ; of this tracks file entry.
              ADD HL,DE
              LD A,(HL)             ; The file for this track.
              CP B                  ; Is it the file we want ?
              JR NZ,Lfnextt         ; Try next track it if isn't.
              
              POP HL                ; HL := file length.
              POP DE                ; DE := start address.
              PUSH BC               ; Save BC.
              PUSH DE               ; Save start address.
              CALL block-length     ; DE := block length.

              OR A                  ; CY := 0
              SBC HL,DE
              JR Z,Lfend            ; If file is exactly one block.
              JR C,Lfend            ; If file less than one block.

              EX (SP),HL
            
             ; At this point, HL = start address,
             ; DE = block length, and remaining file length and
             ; track and file numbers saved.
              
              CALL Load-block       ; Leaves HL pointing to start
                                    ; of the next block.
            CALL Error-?

            POP DB                  ; Load remaining file.
            POP BC
            JR Sfnextb

Lfend      ADD HL,DE               ; File was shorter than a block
                                    ; so make it positive again.
            EX DE,HL                ; DE := length still to be loaded.
            POP HL                  ; HL := start address.

            CALL Load-block
            CALL Error-?

            POP BC
            RET

 
; *********************************************************
; ***                                                   ***
; ***               Find-word                           ***
; ***                                                   ***
; *********************************************************

; * Finds the address of a word in the cat if it exists and
; * the address of the first free point in the cat if it doesn't.

; * On exit:    if A=0, word not found, HL = end of used cat.
; *             else, word found, DE = address of first data field.
; *                               HL = address of length field,
                                   A = file number.
; * Calls: WORD.
; * Called by: Enter-word, Lookup-word and DELETE.

                LD C,0              ; File number in C.

                LD HL,(RAMTOP)      ; Find start of names in cat.
                INC HL
                LD E, (HL)
                LD D,0
                INC HL
                ADD HL,DE

                LD DE,Pad           ; Address of name to be used.

Fwloop          EX HL,DE            ; DE := pos in cat, HL = pos in PAD.
                INC C               ; Next file number.

                LD A, (DE)          ; Length field.
                OR A                ; Zero marks the end of cat.
                RET Z               ; So return if zero.

                PUSH DE
                PUSH HL

                LD B,A              ; Length field in B.
                INC B

FwComp          CP (HL)             ; Compare lengths first, then chars.
                JR NZ,Fwnotf        ; Break if any difference.
                INC HL              ; Next character in PAD.
                INC DE              ; Next character in cat.
                LD A,(DE)           ; Next character.
                DJNZ Fwcomp         ; End of string ?

                ; File name has been found

                POP HL	            ; Throw away pad pointer.
                POP HL              ; Recover address of length field.

                LD A,C              ; File number in A.
                RET

Fwnotf          LD A,B              ; Find start of next word.
                ADD 4
                LD L,A
                LD H,0
                ADD HL,DE
                POP DE              ; Recover start of pad pointer.
                INC SP              ; Through away address of previous
                INC SP              ; length field.
                JR Fwloop           ; Try next word.




  
; *********************************************************
; ***                                                   ***
; ***               Enter-word                          ***
; ***                                                   ***
; *********************************************************

; * Enters a new file name into the catalogue.

; * On entry, the file name is in the input buffer.
; * HL = start address of file (0 for a DICT file).
; * DE = length of file in bytes.
; * On exit, DE and HL have their entry values and
: * B = the file number of the file.

* Calls: Find-word and Error-?
* Called by: STORE and BSTORE.

                PUSH DE             ; Save DE and HL.
                PUSH HL
                PUSH DE             ; Two copies of DE.

                CALL Find-word      ; Sets C to file number.
                OR A                ; Test for found.
                LD A,7              ; "File name already exist".
                CALL NZ,Error-?     ; Call if found.

                LD B,(HL)           ; HL was set to point at
                                    ; the name in the PAD by Find-word.
                LD A,B
                LD (DE),A           ; Store name length in cat.
                                    ; Find word made DE point to
                                    ; the first free point in the cat.

                PUSH HL
                PUSH DE

                LD HL, (RAMTOP)     ; Start of cat.
                OR A                ; Clear carry.
                SBC HL,DE           ; HL := -bytes used.

                LD DE, ($F8FE)      ; Cat size.
                ADD HL,DE           ; HL := bytes free.

                ADD 8               ; bytes needed +3.
                LD E,A
                LD D,0
                OR A                ; Clear carry.
                SBC HL,DE           ; Set carry if not enough room.

                POP DE
                POP HL
                LD A,9              ; "Cat full".

                CALL C,Error-?

Ewcopy          INC DE              ; Next position in the cat.
                INC HL              ; Next character in the name.
                LD A,(HL)           ; Copy character.
                LD (DE),A
                DJNZ Ewcopy         ; Repeat for length of name.

                EX HL,DE            ; HL := pointer to cat.
                POP DE              ; file length.

                INC HL              ; Store length.
                LD (HL),E
                INC HL
                LD (HL),D

                POP DE              ; File start address.
                INC HL
                LD (HL),E
                INC HL
                LD (HL),D

                INC HL              ; Zero marks end of names.
                LD (HL),0

                POP HL
                EX HL,DE            ; HL := start, DE := length.
                LD B,C              ; B := file number.
                RET

 
; *********************************************************
; ***                                                   ***
; ***               Lookup- word                        ***
; ***                                                   ***
; *********************************************************


; * Finds the file number, length and start address of the ;
; * file with name in the input buffer.

; * On exit: B = file number,
; *          DE = length,
; *          HL = start address (0 of DICT files).

; * Calls: Find-word and Error-?.
; * Called by: LD, BLD and RUN.

                CALL Find-word
                LD B,A              ; B := file number.
                OR A                ; Test for file not found.
                LD A,8              ; "File name not found".
                CALL Z,Error-?      ; Raise error if not found.

                EX HL,DE            ; HL points to first data field.

                LD E,(HL)           ; Load DE with length.
                INC HL
                LD D, (HL)
                INC HL

                LD A, (HL)          ; Load HL with start address.
                INC HL
                LD H, (HL)
                LD L,A

                RET



 
; *********************************************************
; ***                                                   ***
; ***               Hex-byte                            ***
; ***                                                   ***
; *********************************************************

; * Prints the contents of A as a two digit hexadecimal number.

; * On entry: A = number to be printed.
; * Only register A is used.

; * Calls: Hex-char.
; * Called by: CAT.

                PUSH AF
                RR A                ; Get most significant nibble.
                RR A
                RR A
                RR A
                CALL Hex-char       ; Print it.
                POP AF              ; Implicit CALL of Hex-char
                                    ; and then return.



  
; *********************************************************
; ***                                                   ***
; ***               Hex-char                            ***
; ***                                                   ***
; *********************************************************


; * Prints the least significant nibble of the byte in A
; * as a single hexadecimal digit.

; * On entry: A = nibble to be printed.
; * Only register A is used.

; * Calls: None.
; * Called by: Hex-digit and CAT.

                AND $F              ; Mask off high nibble.
                CP $A               ; if >= 10,
                JR C,Numdigt        ; add "A"-"9"+1.
                ADD 7
Numdigt         ADD $30             ; ASCII for "0".
                RST 8               ; Wrch.
                RET



  
; *********************************************************
; ***                                                   ***
; ***                     CAT                           ***
; ***                                                   ***
; *********************************************************

; * Gives a list of all the file names on the disk together
; * with their lengths and starting addresses.
; * (Dictionary files have "DICT" in place of the starting
; * address).
; * It then gives the number of bytes free for use on the disk
; * and a map of track usage.
; * It is a FORTH word.

; * Calls: Load-cat, Off, Hex-byte, Hex-char and Block-length.

                CALL Load-cat       ; Turns the motor on first.
                CALL Off

                LD A,$D             ; CR.
                RST 8               ; Wrch.

                LD HL, (RAMTOP)     ; Point to start of names.
                INC HL
                LD E,(HL)           ; number of tracks.
                LD D,0
                INC HL
                ADD HL,DE

Namelp          LD C,$15            ; Number of character for name.
                LD A, (HL)
                OR A                ; Zero marks end of names.
                JR Z,findfre

                LD B,A              ; Name length in B.
Namepr          INC HL
                DEC C
                LD A, (HL)
                RST 8               ; Wrch.
                DJNZ Namepr         ; Print rest of name.

                ; Pad with spaces to get to the same column.

                LD A,C
                AND $1F             ; File name might have been
                                    ; longer than a line.
                                    ; (Assumes 32 chars per line).
                LD B,A
Catpdlp         LD A,$20            ; ASCII for space.
                RST 8               ; Wrch.
                DJNZ Catpdlp

                ; Print length in hex.

                INC HL
                LD C, (HL)
                INC HL
                LD A, (HL)
                CALL Hex-byte

                LD A,C
                CALL Hex-byte

                ; Print space.

                LD A,$20            ; ASCII for space.
                RST 8               ; Wrch.

                ; Print start address in hex of "DICT".

                INC HL
                LD C, (HL)
                INC HL
                LD A, (HL)
                INC HL              ; Point to start of next word.

                LD B,A              ; Test start = 0.
                OR C
                JR NZ,Catbyts
                LD A,$19            ; "DICT".
                CALL Print
                JR Catjn

Catbyts         LD A,B              ; Print as hex
                CALL Hex-byte
                LD A,C
                CALL Hex-byte

                LD A,$D             ; CR.
                RST 8               ; Wrch.
                JR Namelp           ; Next file name.

Findfre         LD A,$D             ; CR.
                RST 8               ; Wrch.

                LD HL, (RAMTOP)     ; Find start of file for track
                INC HL              ; vector.
                LD B,(HL)           ; Number of tracks.
                DEC B               ; Two tracks used for cats.
                DEC B
                CALL Block-length   ; DE := number of bytes on a track.
                INC HL
                INC HL              ; First element of vector.

                PUSH HL             ; Temp start of vector.
                LD HL,0             ; Bytes free accumulated in HL
                LD C,0              ; and C.

Freelp          EX HL, (SP)         ; HL = vector pointer.
                INC HL              ; Next track.
                LD A, (HL)          ; File number of track.
                EX HL, (SP)         ; HL = Count.

                OR A                ; Test A=0 ie free.
                JR NZ,Notfree       ; If its used, don't count it.
                ADD HL,DE           ; If it is free, add a track full
                                    ; of bytes.
                JR NC,Notfree       ; Use C for high byte if 16 bits
                INC C               ; overflow.
Notfree         DJNZ Freelp         ; Try all tracks.

                POP DE             ; discard vector pointer.

                LD A,C              ; Most significant byte of count.
                CALL Hex-byte
                LD A,H              ; Middle byte of count.
                CALL Hex-byte
                LD A,L              ; Least significant byte of count.
                CALL Hex-byte

                LD A,$1A            ; " bytes free".
                CALL Print

                JP (IY)             ; Forth return.

 
; *********************************************************
; ***                                                   ***
; ***               Dict-size                           ***
; ***                                                   ***
; *********************************************************

; * Sets DE and HL to the start and length of the catalogue.

; * DE = length of cat on exit.
; * HL = starting address of cat on exit.

; Calls: none.
; Called by: Load-cat and Save-cat.

                LD HL,(RAMTOP)
                INC HL              ; Miss the byte used for DRIVE.
                LD DE,($F8FE)       ; Cat size.
                DEC DE              ; Don't save drive number.
                RET

 
; *********************************************************
; ***                                                   ***
; ***               Block-length                        ***
; ***                                                   ***
; *********************************************************

; * Loads the block length of the current disk into DE without
; * changing any other registers.

; * DE = Block length on exit.

; * Calls: None.
; * Called by: Load-file, Save-file.

                PUSH HL             ; HL must be the same at the end.
                LD HL, (RAMTOP)
                INC HL
                INC HL              ; The block length is in the second
                LD E,(HL)           ; and third bytes of the cat.
                INC HL
                LD D,(HL)
                POP HL              ; Recover HL.
                RET


 
; *********************************************************
; ***                                                   ***
; ***               Delete-file                         ***
; ***                                                   ***
; *********************************************************

; * Deletes the file with its name in the pad from the
; * catalogue copy in RAM.

; * No args or results.

; * Calls: Find-word.
; * Called by: DELETE and RESTORE.

                CALL Find-word          ; DE := data field of word,
                                        ; HL := name length field,
                                        ; C := file number.

                LD C,A

                OR A                    ; Test for word not found.
                LD A,8                  ; "File name does not exit".
                CALL Z,Error-?

                PUSH DE
                PUSH HL

                ; First free all blocks used by this file and
                ; decrease the file number entries if they are
                ; greater than this file.

                LD HL,(RAMTOP)          ; Find the start of the
                INC HL                  ; block usage vector.
                LD B,(HL)               ; number of tracks.
                DEC B                   ; Two tracks used for cats.
                DEC B
                INC HL
                INC HL                  ; Skip block size bytes.

Delfl           INC HL                  ; Next track.
                LD A,(HL)               ; File for this track.
                CP C                    ; Is if used for this file.
                JR Z, Delfd             ; If it is, set it free.
                JR C, Delfst            ; If its < this file, leave it.
                DEC A                   ; If its greater than this file,
                                        ; the file number will have decreased
                                        ; by one.
                JR Delfst
Delfd           XOR A                   ; A := 0 for empty track.
Delfst          LD (HL),A               ; Store back to cat.
                DJNZ Delfl              ; Repeat for all tracks.

                ; Second, remove the name it self by shuffling
                ; all the names above it down.

                POP DE                  ; name length field.
                POP HL                  ; data field.
                INC HL                  ; HL := name length field
                INC HL                  ;       of next word.
                INC HL
                INC HL

Delfl2          LD A, (HL)              ; Name length.
                LD (DE),A               ; Store it even it its zero.
                OR A                    ; If it is zero, stop.
                RET Z
                ADD 4                   ; Four data bytes to copy as well.
                LD B,A

Delfl3          INC HL                  ; Copy one name and data.
                INC DE
                LD A, (HL)
                LD (DE),A
                DJNZ Delfl3
                INC HL                  ; Then repeat for the rest
                INC DE                  ; of the names.
                JR Delfl2


; *********************************************************
; ***                                                   ***
; ***               DELETE                              ***
; ***                                                   ***
; *********************************************************

; * Forth word to delete a file.

; * No arguments or results.

; * Calls; Load-cat,Delete-file, Save-cat and Off.

                CALL Word
                CALL Load-cat
                CALL Delete-file
                CALL Save-cat
                CALL Off
                JP (IY)             ; Forth return.


; *********************************************************
; ***                                                   ***
; ***               Error-?                             ***
; ***                                                   ***
; *********************************************************

; * Prints and error message and then ABORTS (if A>0).

; * A = error number on entry.
; * If A = 0, the routine returns immediately.

; * Calls: Print-error and Off.
; * Called by: Almost everything.

                OR A                ; Test A=0
                RET Z               ; Return if it is.

                CALL Print-error
                CALL Off            ; Switch drive off.
                                    ; (Doesn't matter if it wasn't on).

                EI                  ; Could have been called with
                                    ; interrupts off.
                RST 32              ; ABORT.
                $FF                 ; No error number.


  
; *********************************************************
; ***                                                   ***
; ***               Store                               ***
; ***                                                   ***
; *********************************************************

; * Store a dictionary file.

; * No arguments or results.

; * Calls; Save-file,Save-cat and Off.

                CALL Fill-length
                LD HL,(STKBOT)          ; End of dict.
                LD DE, (Forth)          ; Newest word in FORTH.
                LD (HL),E               ; Save it at the end of the dict.
                INC HL
                LD (HL),D
                INC HL

                LD DE,DCTRAM            ; Start of dict (after FORTH).
                OR A                    ; Clear carry.
                SBC HL,DE
                EX HL,DE                ; HL = start, DE = length.
                LD A,E                  ; Is there anything to save.
                SUB 2                   ; Two bytes added even if nothing.
                OR D
                LD A,$D                 ; "Why save 0 bytes".
                CALL Z,Error-?

                PUSH HL
                LD HL,0                 ; 0 represents a DICT file.
                CALL Enter-word
                POP HL
                CALL Save-file
                CALL Save-cat
                CALL Off
                RET



; *********************************************************
; ***                                                   ***
; ***               DSAVE                               ***
; ***                                                   ***
; *********************************************************

; * Forth word to store a dictionary file.
; * Disk equivalent of SAVE.

; * No arguments or results.

; * Calls; Load-cat and Store.

                CALL Word
                CALL Load-cat
                CALL Save
                JP (IY)


 
; *********************************************************
; ***                                                   ***
; ***               DBSAVE                              ***
; ***                                                   ***
; *********************************************************

; * Forth word to store a bytes file.
; * Disk equivalent of BSAVE.

; * No arguments or results.

; * Calls; Load-cat,Save-file,Save-cat and Off.

                CALL Word
                CALL Load-cat

                RST 24                  ; Pop DE from parameter stack.
                PUSH DE
                RST 24                  ; Pop DE from parameter stack.
                POP HL
                EX DE,HL                ; DE = length, HL = start.

                LD A,D                  ; Test len = 0.
                OR E
                LD A,$D                 ; "Why BSTORE 0 bytes".
                CALL Z,Error-?

                CALL Enter-word
                CALL Save-file
                CALL Save-cat
                CALL Off
                JP (IY)                 ; Forth return.



; *********************************************************
; ***                                                   ***
; ***               DLOAD                               ***
; ***                                                   ***
; *********************************************************

; * Forth word to load a bytes file.
; * Disk equivalent of BLOAD.

; * No arguments or results.

; * Calls; Load-cat,Load-file, Error-? and Off.

                CALL Word
                CALL Load-cat
                RST 24                  ; Pop DE from parameter stack.
                                        ; First argument ignored.
                RST 24                  ; Pop DE from parameter stack.
                PUSH DE                 ; Save start address.
                CALL Lookup-word

                LD A,H                  ; Check not DICT.
                OR L
                LD A,$B                 ; "BLD a DICT".
                CALL Z,Error-?

                EX HL, (SP)             ; HL = parameter start.
                LD A,H                  ; If zero ...
                OR L
                JR Z,Bldlb              ; Use start from cat.
                EX HL,(SP)
Bldlb           POP HL

                CALL Load-file
                CAll Off
                JP (IY)                 ; Forth return.





; *********************************************************
; ***                                                   ***
; ***               RESAVE                              ***
; ***                                                   ***
; *********************************************************

; * Forth word to save a dictionary file under a name which
; * already exists.

; * No arguments or results.

; * Calls; Load-cat,Delete,Save.

                CALL Word
                CALL Load-cat
                CALL Delete-file
                CALL Save-cat
                CALL Store
                JP (IY)


 
; *********************************************************
; ***                                                   ***
; ***               Word                                ***
; ***                                                   ***
; *********************************************************

; * Transfers a word from the input buffer to the pad.

; * No arguments or results.
; * All registers corrupted.

; * Calls: The forth word WORD.

                LD DE,$20               ; Put a space on top,
                RST 16                  ; of the parameter stack.
                                        ; WORD uses this character
                                        ; as its termination mark.
                CALL Enter-forth
                WORD
                End-forth

                RST 24                  ; Discard the top e.,f the stack
                                        ; which is the address of the pad.
                RET




  
; *********************************************************
; ***                                                   ***
; ***               MAP                                 ***
; ***                                                   ***
; *********************************************************

; * Prints the file number for each track as a  single
; * hexadecimal digit. "-" for not used.
; * It is a Forth word.

; * Calls: Hex-char, Load-cat and Off.

                CALL Load-cat
                CALL Off
                LD HL,(RAMTOP)
                INC HL
                LD B, (HL)                  ; Number of tracks,
                DEC B                       ; Two tracks uses cat.
                DEC B
                INC HL                      ; Skip block size.
                INC HL

Catmap          INC HL
                LD A, (HL)
                OR A                        ; Use space not 0 for an
                JR Z,Mapl                   ; empty track. (0 for 0 mod 16) .
                CALL Hex-char
                JR Map2
Mapl            LD A,$2D                    : "-".
                RST 8                       ; Wrch
Map2            DJNZ Catmap                 ; Print all tracks
                JP (IY)                     ; Forth return.



; *********************************************************
; ***                                                   ***
; ***               DLOAD                               ***
; ***                                                   ***
; *********************************************************

; * Loads a dict or bytes (At stored address) file from
; * disk to RAM.
; * It is a Forth word.

; * No args or results.

; * Calls: Word, Load-cat, Lookup-word, Load-file, Off
; *        and the Forth ROM for LOAD.

                CALL Fill-length
                CALL Word
                CALL Load-cat
                CALL Lookup-word            ; HL := start address,
                                            ; DE := length and
                                            ; B := file number.
                LD A,H                      ; Test start address = 0
                OR L                        ; Which indicates a dict.
                JR Z,Dloadl1                ; Jump if dict.

                CALL Load-file              ; Load bytes file at address
                CALL Off                    ; Read from cat.
                JP (IY)

Dloadl1         LD ($2325),SP               ; Transfer SP to HL.
                LD HL,($2325)

                PUSH DE                     ; Save length to be loaded.
                LD DE,$40                   ; There must be some room
                OR A                        ; after loading.
                SBC HL,DE
                POP DE

                PUSH HL                     ; Save top of usable RAM.
                LD HL,(STKBOT)              ; Start point of loading.
                ADD HL,DE                   ; End point of loading.
                EX HL,DE
                EX HL, (SP)

                ; At this point, HL = highest point which can be used,
                                 DE = highest point which will be used,
                ; and the length of load is on the stack.

                OR A                        ; Clear carry.
                SBC HL,DE                   ; Compare.

                POP DE
                LD A,$F                     ; "Not enough RAM".
                CALL C,Error-?              ; Error if DE was > HL.

                LD HL,(STKBOT)              ; First free byte after dict.
                PUSH DE
                PUSH HL
                CALL Load-file
                CALL Off

                POP HL
                POP DE
                DEC DE                      ; Two bytes were added
                DEC DE                      ; for vocab pointer,
                LD ($2325),DE               ; Will be read as length
                                            ; added to diet.
                ADD HL,DE
                LD E, (HL)                  ; Read vocab pointer.
                INC HL
                LD D, (HL)
                LD ($2329),DE               ; Will be read as newest
                                            ; word.
                JP $19AA                    ; Enter LOAD adjust section.





; *********************************************************
; ***                                                   ***
; ***               SCRATCH                             ***
; ***                                                   ***
; *********************************************************

; * Forth word to remove all words from dictionary,
; * Similar to FORGET <Oldest word>.

; * Calls: None.

                LD HL,$3C4C                 ; Forth.
                LD ($3C31),HL               ; CURRENT.
                LD ($3C33),HL               ; CONTEXT.
                LD L,$4F
                LD ($3C35),HL               ; VOCLINK.
                LD L,$51
                LD ($3C37),HL               ; STKBOT.
                LD L,$45
                LD ($3C39),HL               ; DICT.
                LD L,$5D
                LD ($3C3B),HL               ; SPARE.
                LD L,$49
                LD ($3C49),HL               ; Forth link.
                JP (IY)

 
; *********************************************************
; ***                                                   ***
; ***               Fill-length                         ***
; ***                                                   ***
; *********************************************************

; * Fills in the length field of the newest word in the
; * dictionary if it is not already filled and
; * then sets DICT to 0 to show that it is now filled.

; * Calls: None.

; * Called by: Store and DLOAD.

                LD HL,(STKBOT)              ; HERE.
                LD DE,(DICT)                ; Address of length field or zero.
                LD A,D                      ; Test for zero for already
                OR E                        ; Filled.
                RET Z
                SBC HL,DE                   ; Carry cleared by previous
                OR E.
                EX HL,DE                    ; HL is the address of the length
                                            ; field, DE is the length.
                LD (HL),E                   ; Store length.
                INC HL
                LD (HL),D

                LD HL,0                     ; (DICT) := 0
                LD (DICT),HL
                RET