MDFS::Info.Comp.Spectrum.ProgTips.linerun/htm | Search |
USR address
calls the code and returns the value in the Z80's
BC register. However, it can often be useful to be able to call a piece of
BASIC code from machine code.
LINE_RUN at &1B8A executes a line of BASIC in the editing area pointed to by E_LINE, such as a line entered directly. If you point E_LINE to your own BASIC you can call LINE_RUN to execute it. Slightly different code has to be used for 48K Basic commands and Interface 1 commands as Interface 1 commands always return via ERR_SP rather than via a RET.
; Execute a Interface 1 command at E_LINE ; --------------------------------------- ; NB! Interface 1 commands *ALWAYS* return via (ERR_SP), even when OK ; NB! Must ALWAYS be CALLed, cannot be JPed to as stack fiddled with ; .MDCommand SET 7,(IY+1) ; Set 'Not syntax checking' SET 2,(IY+124) ; Ensure ERR_SP used for errors LD (IY+10),1 ; Set ZXBasic statement 1 LD HL,(ERR_SP):PUSH HL ; Save ERR_SP LD HL,&FFFE:ADD HL,SP ; Point to where return address will be LD (ERR_SP),HL ; Set up new ERR_SP CALL &1B8A ; Execute command at E_LINE, will always return to here BIT 7,(IY+0):JR NZ,MDNoError ; No error occured RES 1,(IY+124) ; Ensure autoload trap avoided LD HL,&0046:LD (&5CED),HL ; Point to part of error handler RST &08:DEFB &32 ; Reclaim channels and turn off drives .MDNoError POP HL:LD (ERR_SP),HL ; Restore ERR_SP RET ; On exit, ; ERR_NR=&FF - ok ; ERR_NR=&14 - BREAK ; ERR_NR=&0B - Interface 1 error ; Could be Invalid name/Missing name/Drive write protected/Microdrive full/Microdrive not present ; File not found/Wrong file type/Writing to a 'read' fileWith this code you can then execute an Interface 1 command from machine code. The following loads a piece of code by executing a
LOAD
*&quit;m"
command.
; Load code from microdrive ; ------------------------- RST &08:DEFB &31 ; Wake up Interface 1, ensure E_LINE in correct place LD DE,(E_LINE):LD HL,MDLoad LD BC,31:LDIR ; Copy LOAD*"m";VAL"1";"filename"CODE0<0e><0><0><80><0><0>Note that the file is loaded to &8000 by specifying the address in the embedded number. The literal number is ignored. This procedure can be used to load an arbitary file by copying the filename to E_LINE seperately, and to load to an arbitary address by setting the embedded number after copying, and from an arbitary drive by overwriting the drive number.<80> EX DE,HL:CALL &16B9 ; Point WORKSP to end of line CALL MDCommand ; Execute LOAD command BIT 7,(IY+0) ; Did error occur? ... .MDLoad DEFB &EF:DEFM "*":DEFB &22:DEFM "m":DEFB &22:DEFM ";" ; LOAD*"m"; DEFB &B0:DEFB &22:DEFM "1":DEFB &22:DEFM ";":DEFB &22 ; VAL"1";" DEFM "filename" ; filename DEFB &22:DEFB &AF:DEFM "0":DEFB &0E:DEFB &00:DEFB &00 ; "CODE0<0e><00><00> DEFB &00:DEFB &80:DEFB &00:DEFB &0D:DEFB &80 ; <00><80><00> <80>
; Load code from microdrive ; ------------------------- ; A=drive number ; HL=>filename ; BC=length of filename ; DE=load address .MDLoadFile PUSH DE:PUSH HL:PUSH BC:PUSH AF ; Wake-up trashes all registers RST &08:DEFB &31 ; Wake up Interface 1, ensure E_LINE in correct place LD DE,(E_LINE):LD HL,MDLoad1 PUSH DE:POP IX ; IX=>start of command LD BC,12:LDIR ; Copy LOAD*"m";VAL"1";" POP AF:OR 48:LD (IX+8),A ; Overwrite drive number POP BC:POP HL:LDIR ; Copy filename PUSH DE:POP IX ; IX=>end of filename LD HL,MDLoad2:LD BC,11:LDIR ; Copy "CODE0<0e><00><00><00><00><00><0d><80> POP DE:LD (IX+6),E:LD (IX+7),D ; Insert load address EX DE,HL:CALL &16B9 ; Point WORKSP to end of line CALL MDCommand ; Execute LOAD command BIT 7,(IY+0) ; Did error occur? RET ; .MDLoad1 DEFB &EF:DEFM "*":DEFB &22:DEFM "m":DEFB &22:DEFM ";" ; LOAD*"m"; DEFB &B0:DEFB &22:DEFM "1":DEFB &22:DEFM ";":DEFB &22 ; VAL"1";" .MDLoad2 DEFB &22:DEFB &AF:DEFM "0":DEFB &0E:DEFB &00:DEFB &00 ; "CODE0<0e><00><00> DEFB &00:DEFB &80:DEFB &00:DEFB &0D:DEFB &80 ; <00><80><00><80>