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