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