PDS download source code
From CPCWiki - THE Amstrad CPC encyclopedia!
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