Last modified on 11 March 2018, at 08:39

PDS download source code

Revision as of 08:39, 11 March 2018 by Arnoldemu (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Here is the original Amstrad CPC source code of the PDS development system download functions. Below DLn files (and other versions for C64, BBC, Spectrum) are also found in Media:PDS source code.zip.

AMSTRAD.DL0 (short version, 114 bytes)

;   Amstrad short download software
;
;
;Only to be used for assembling and downloading, most monitor functions
;will not opperate with this download software. It has been kept as short
;as possible. Note that the interupts are disabled. This is to prevent
;your own interupt routines crashing if they are overwritten.
;The code is 114 bytes long. It may be ORG'ed anywhere.
;
;
        ORG 8000H
;
START   LD A,255
        LD BC,0FBEEH
        OUT (C),A
        OUT (C),A
        INC C
        OUT (C),A       ;Initial port setup
        LD C,0EDH
        OUT (C),A
        LD C,0EFH
        LD A,63
        OUT (C),A
        LD D,64 ;Protocol flags to input from main computer
        DI
;
; Main loop
;
MAINLOOP        CALL GETBYTE    ;Get 'command byte'
        LD A,E
        CP 180  ;Download code into aabb, len=ccdd
        JZ DLOAD
        CP 183
        JZ BANK
        CP 181
        JNZ MAINLOOP    ;If unknown, keep looping
;
; Function 181, Execute code from aabb
;
        CALL GETBYTE
        LD H,E  ;Get address
        CALL GETBYTE
        LD L,E
        LD BC,MAINLOOP  ;CALL it.
        PUSH BC
        JP (HL)
;
; Function 183, Select bank aa
;
BANK    CALL GETBYTE
        LD B,7FH        ;You may write your own routine here.
        LD C,E  ;You may corrupt everything except E
        OUT (C),C       ;This allows you to page in rom and ram
        JR MAINLOOP
;
; Function 180, Download code into aabb, length=ccdd
;
DLOAD   CALL GETBYTE
        LD H,E
        CALL GETBYTE    ;Get start address of code
        LD L,E
        CALL GETBYTE
        LD B,E
        CALL GETBYTE    ;Get length of code
        LD C,E
DLOAD1  CALL GETBYTE
        LD (HL),E       ;Get and store bytes
        INC HL
        DEC BC
        LD A,B
        OR C
        JNZ DLOAD1
        JR MAINLOOP     ;Go back into main download loop
;
; Get a byte from the main computer into E
;
GETBYTE PUSH BC
        LD BC,0FBEDH
$1      IN A,(C)
        XOR D           ;Wait for 'sent the byte'
        RRCA
        JC $1
        DEC C
        IN E,(C)        ;Get the byte
        INC C
        LD A,D
        OUT (C),A       ;Say 'byte received'
        XOR 129
        LD D,A  ;Flip flags ready for next byte
        POP BC
        RET
;
;
; The end of the PDS download software.
;
; Now is a short routine to return to basic from the ASMSTRAD download
; software supplied with the system. Note that to run the download software
; you must use the following :
;
; LOAD "D" : CALL 40000
;
; When you assemble and download this program you will return to basic, to
; save to disk or tape use the following:
;
; SAVE "DLOAD",B,start address,114,start address
;
; Now it will be saved so it will auto run when RUN "DLOAD is typed.
;
;
        ORG START-3
        POP HL  ;Get rid of return to PDS software
        EI
        RET             ;Start interupts and return
;
;
;
        SEND COMPUTER1
        END

AMSTRAD.DL1 (long version, 374 bytes)

;   Amstrad long download software
;
;
;This download software can be used for assembling and download, and will
;work with all the monitor functions, such as trace, upload etc...It will
;not work with the Analyze command, which requires the DL2 software.
;Interupts are disabled. Jump to START the first time, this will setup all
;the ports. If you wish to enter the download software again, jump to
;MONITOR. The length of the code is 374 bytes.
;
;
        ORG 8000H
;
;
; Initial setup code
;
START   PUSH AF
        LD A,255
        LD BC,0FBEEH
        OUT (C),A
        OUT (C),A
        INC C
        OUT (C),A       ;Initial port setup
        LD C,0EDH
        OUT (C),A
        LD C,0EFH
        LD A,63
        OUT (C),A
        INC A
        LD (FLAGIO),A   ;Initial flags 0 - Input
        POP AF
;
; Now main part of download software
;
MONITOR DI              ;Interupts would corrupt the stack
        LD (ZHL),HL     ;Save HL
        LD (ZSP),SP     ;Save SP
        POP HL  ;Get 'return' address
        LD (ZPC),HL     ;Where I was called from
        LD SP,ZHL       ;Top of register block
        PUSH DE
        PUSH BC
        EXX
        PUSH HL
        PUSH DE
        PUSH BC ;All registers are saved for PDS
        PUSH IX
        PUSH IY
        PUSH AF
        LD A,I
        LD H,A
        LD A,R
        LD L,A
        PUSH HL
        EX AF,AF'
        PUSH AF
        LD D,0  ;D is the download flag
FLAGIO  EQU $-1
;
; Mainloop
;
MAINLOOP        CALL GETBYTE
        LD A,E
        CP 180  ;Download code into aabb, len=ccdd
        JZ DLOAD
        CP 186  ;Run code aa,bb,cc,dd
        JP Z,EXECUTE
        CP 184  ;Send register block to Apricot
        JP Z,SENDREG
        CP 185  ;Get register block from Apricot
        JP Z,GETREG
        CP 183  ;Select bank aa
        JZ SBANK
        CP 182  ;Upload code from aabb len=ccdd
        JZ UPLOAD
        CP 181  ;Execute code from aabb?
        JNZ MAINLOOP    ;Not recognised - keep looping.
;
; Function 181, Execute code from aabb
;
        CALL GETBYTE
        LD H,E
        CALL GETBYTE    ;Notice that the address is downloaded H then L
        LD L,E
        LD (EXEC+2),HL  ;Put NOP, CALL <xxxx> into execution buffer
        LD HL,0CD00H
        LD (EXEC),HL
        JP RUNIT
;
; Function 180, Download code into aabb, length=ccdd
;
DLOAD   CALL GETBYTE
        LD H,E
        CALL GETBYTE    ;Get start address of code
        LD L,E
        CALL GETBYTE
        LD B,E
        CALL GETBYTE    ;Get length of code
        LD C,E
DLOAD1  CALL GETBYTE
        LD (HL),E       ;Get and store bytes
        INC HL
        DEC BC
        LD A,B
        OR C
        JNZ DLOAD1
        JR MAINLOOP     ;Go back into main download loop
;
; Function 183, select bank aa
;
SBANK   CALL GETBYTE
        LD B,7FH        ;You may write your own routine here.
        LD C,E  ;You may corrupt everything except E
        OUT (C),C       ;This allows you to page in rom and ram
        JR MAINLOOP
;
; Function 184, upload register block to the main computer.
;
SENDREG LD HL,REGISTERS
        LD BC,26
        JR UPLOAD1      ;Upload the register block
;
; Function 185, download register block from the main computer.
;
GETREG  LD HL,REGISTERS
        LD BC,26
        JR DLOAD1       ;Download the register block
;
; Upload code, from aabb, length ccdd
;
UPLOAD  CALL GETBYTE
        LD H,E
        CALL GETBYTE    ;Get start address of code
        LD L,E
        CALL GETBYTE
        LD B,E
        CALL GETBYTE    ;Get length of code
        LD C,E
;
UPLOAD1 PUSH BC
        LD BC,0FBEDH
$0      IN A,(C)
        XOR D
        RRCA
        JC $0
        INC C
        LD A,255
        OUT (C),A       ;This swaps the PDS interface direction around
        INC A
        OUT (C),A       ;The Amstrad now transmitts to the Apricot
        LD A,D
        XOR 65
        LD D,A
        POP BC
;
$1      LD A,(HL)
        CALL SENDBYTE
        INC HL  ;Send the area of memory
        DEC BC
        LD A,B
        OR C
        JNZ $1
;
        DEC A
        LD BC,0FBEEH
        OUT (C),A
        OUT (C),A
        DEC C
        LD A,D
        XOR 64  ;Swap the ports back to normal
        OUT (C),A
        XOR 128
        LD D,A
;
        JP MAINLOOP
;
; Function 186, execute the next 4 bytes, and reenter monitor
;
EXECUTE CALL GETBYTE
        LD L,E
        CALL GETBYTE
        LD H,E
        LD (EXEC),HL
        CALL GETBYTE    ;Get the 4 bytes to be run
        LD L,E
        CALL GETBYTE    ;Store in execution buffer
        LD H,E
        LD (EXEC+2),HL
RUNIT   LD A,D
        LD (FLAGIO),A
        POP AF
        EX AF,AF'
        POP HL
        LD A,H
        LD I,A
        LD A,L
        LD R,A
        POP AF
        POP IY
        POP IX  ;Get all registers off stack
        POP BC
        POP DE
        POP HL
        EXX
        POP BC
        POP DE
        POP HL
        LD SP,(ZSP)
EXEC    DS 4            ;All code to be run is placed here
        JP MONITOR
;
; Get a byte from the main computer into E
;
GETBYTE PUSH BC
        LD BC,0FBEDH
$1      IN A,(C)
        XOR D           ;Wait for 'sent byte'
        RRCA
        JC $1
        DEC C
        IN E,(C)        ;Get the byte
        INC C
        LD A,D
        OUT (C),A       ;Set 'byte received'
        XOR 129
        LD D,A  ;Flip flags for next byte
        POP BC
        RET
;
; Send A to the main computer
;
SENDBYTE        PUSH BC
        LD BC,0FBECH
        OUT (C),A       ;Send the byte
        INC C
        LD A,D
        OUT (C),A       ;Set 'sent the byte'
        XOR 129
        LD D,A
$1      IN A,(C)
        XOR D           ;Wait for 'byte received'
        RRCA
        JNC $1
        POP BC
        RET
;
        DW 0,0  ;Uses two levels of stack
REGISTERS       DS 20           ;Other registers stored here
ZHL     DW 0            ;HL stored here
ZPC     DW 0            ;PC stored here
ZSP     DW 0            ;SP stored here
;
;
;
; The end of the PDS download software.
;
; Now is a short routine to return to basic from the ASMSTRAD download
; software supplied with the system. Note that to run the download software
; you must use the following :
;
; LOAD "D" : CALL 40000
;
; When you assemble and download this program you will return to basic, to
; save to disk or tape use the following:
;
; SAVE "DLOAD",B,start address,374,start address
;
; Now it will be saved so it will auto run when RUN "DLOAD is typed.
;
;
        ORG START-3
        EXEC $
        EI
        POP HL
        RET
;
;
;
        SEND COMPUTER1
        END

AMSTRAD.DL2 (interrupt driven)

;   This is the interupt driven download software for the Amstrad
;
; To use this software, insert a CALL to the routine PDSSETUP in the
; 'cold start' or 'once only' part of your program. Also insert a CALL
; to the routine MONITOR in your interupt routine. PDS corrupts HL,DE,BC
; and AF. The call to monitor must have HL containing the address where
; the interupt occured.
; You will now be able to use most of the monitor functions while your
; program is running and interupts enabled. Note that you cannot alter
; the registers or trace as this would not make sense under the interupts.
; The analyze command will also opperate now.
;
; Note that if you try and download programs, containing the PDS download
; software, chances are that you will crash the system as the download
; software contains self modifiying code that would get overwritten.
; To download programs just make sure you never download over the
; download software currently running.
;
; Below is the PDS download software and a short program that sets up the
; amstrad and returns you to basic, so you may modify memory while you
; are running basic programs.
; To run this, use the download software disk supplied and type :
;
; LOAD "D
; CALL 40000
;
; If you had used RUN"D you would not have been able to return to basic
; Now you can download the program
;
;
;
        ORG 39000
        EXEC $
;
; Setup interupts and return to basic
;
        CALL PDSSETUP   ;Initialize PDS software
        DI
        LD HL,(39H)
        LD (INTEND+1),HL        ;Redirect interupt vector
        LD HL,INTR
        LD (39H),HL
        EI
        POP HL  ;Remove PDS return to download software address
        RET
;
; End of example program
;
;
;
;
; Now the main PDS download software routines
;
;
; Initial setup code - only called once.
;
PDSSETUP        LD A,255
        LD BC,0FBEEH
        OUT (C),A
        OUT (C),A
        INC C
        OUT (C),A       ;Initial port setup
        LD C,0EDH
        OUT (C),A
        LD C,0EFH
        LD A,63
        OUT (C),A
        INC A
        LD (FLAGIO),A   ;Initial protocol flags, input
        RET
;
; An example interupt routine
;
INTR    LD (STKSTO+1),SP
        PUSH HL
        PUSH DE
STKSTO  LD HL,1
        LD E,(HL)
        INC HL  ;Get HL=old PC address
        LD D,(HL)
        EX DE,HL
        CALL MONITOR    ;Do download software
        POP DE
        POP HL  ;Now go back into AMSTRAD routines
INTEND  JP 1
;
;
; Call this address from your interupt routine
;
MONITOR PUSH AF
        PUSH BC ;Save all regs from your program
        PUSH DE
        PUSH HL
        LD D,0  ;D is the download flag
FLAGIO  EQU $-1
;
        LD BC,0FBEDH
        IN A,(C)
        XOR D           ;WAIT UNTIL GOT=I
        RRCA
        JC EXIT
        DEC C
        IN E,(C)        ;GET BYTE
        INC C
        LD A,D
        OUT (C),A       ;SET SEND=I
        XOR 129
        LD D,A  ;I=1-I (ready for next byte)
;
        LD A,E
        SUB 180
        JZ DLOAD
        DEC A
        JZ EXECUTE
        DEC A
        JZ UPLOAD
        DEC A
        JZ SBANK
        CP 4
        JZ ANALYZE
;
EXIT    LD A,D
        LD (FLAGIO),A
        POP HL
        POP DE  ;Return to your program
        POP BC
        POP AF
        RET
;
; Send PC address back to main computer
;
ANALYZE CALL PORTOUT
        LD A,L
        CALL SENDA
        LD A,H
        CALL SENDA
        CALL PORTIN
        JR EXIT
;
; Execute code from aaaa - does a jump note! (call would be silly from ints)
;
EXECUTE CALL GETA
        LD H,E
        CALL GETA       ;Notice that the address is downloaded H then L
        LD L,E
        JP (HL)
;
; Download code into aaaa, length=bbbb
;
DLOAD   CALL GETA
        LD H,E
        CALL GETA       ;Get start address
        LD L,E
        CALL GETA
        LD B,E
        CALL GETA       ;Get length of code
        LD C,E
DLOAD1  CALL GETA
        LD (HL),E       ;Get and store code
        INC HL
        DEC BC
        LD A,B
        OR C
        JNZ DLOAD1
        JR EXIT
;
; Upload code, from aaaa, length bbbb
;
UPLOAD  CALL GETA
        LD H,E
        CALL GETA       ;Get start address
        LD L,E
        CALL GETA
        LD B,E
        CALL GETA       ;Get length of code
        LD C,E
        CALL PORTOUT
$1      LD A,(HL)
        CALL SENDA
        INC HL  ;Send the area of memory
        DEC BC
        LD A,B
        OR C
        JNZ $1
        CALL PORTIN
        JP EXIT
;
; Function 183, select bank xx (This is different for each computer)
;
SBANK   CALL GETA
;
; HL, BC and A may be corrupted here
; Please write your own bank changing routine, for example it could just
; be LD BC,nnnn  then  OUT (C),A. Note that A contains the number of the
; bank, sent from the PDS BANK n command in the assembler
;
        JP EXIT
;
; Turn port direction TO main computer
;
PORTOUT PUSH BC
        LD BC,0FBEDH
$R      IN A,(C)
        XOR D
        RRCA
        JC $R
        INC C
        LD A,255
        OUT (C),A       ;This swaps the PDS interface direction around
        INC A
        OUT (C),A       ;The Spectrum now transmitts to the Apricot
        LD A,D
        XOR 65
        LD D,A
        POP BC
        RET
;
; Turn port direction FROM main computer
;
PORTIN  LD A,255
        LD BC,0FBEEH
        OUT (C),A
        OUT (C),A
        DEC C
        LD A,D
        XOR 64  ;Swap the ports round again
        OUT (C),A
        XOR 128
        LD D,A
        RET
;
; Get a byte from the APRICOT in E
;
GETA    PUSH BC
        LD BC,0FBEDH
$1      IN A,(C)
        XOR D           ;WAIT UNTIL GOT=I
        RRCA
        JC $1
        DEC C
        IN E,(C)        ;GET BYTE
        INC C
        LD A,D
        OUT (C),A       ;SET SEND=I
        XOR 129
        LD D,A  ;I=1-I (ready for next byte)
        POP BC
        RET
;
; Send A to the APRICOT
;
SENDA   PUSH BC
        LD BC,0FBECH
        OUT (C),A
        INC C
        LD A,D
        OUT (C),A
        XOR 129
        LD D,A
$1      IN A,(C)
        XOR D
        RRCA
        JNC $1
        POP BC
        RET
;
;
;
        SEND COMPUTER1
        END