Detecting Interface 1 Presence |
MDFS::Info.Comp.Spectrum.ProgTips.Interface1.detect/htm | Search |
It's useful to be able to detect if the Interface 1 is present.
Then a program can chose to use Interface 1 facilities,
such as saving to microdrive, and avoid using them if absent.
The original Spectrum ROM has a bug in the CLOSE# routine
that causes a crash with an attempt to close an
unopened stream higher than stream 3. Consequently, the
Interface 1 hooks into the CLOSE routine to fix the bug
and to close Interface 1 channels. So, using CLOSE# will
create the extended system variables if the Interface 1
is present.
Stream 0 defaults to the "K"
eyboard channel
and is re-attached to it at various times during program execution.
So doing CLOSE#0
is effectively a null operation, with
the side effect that the Interface 1 is woken up.
Location 23734 is the first byte of the CHANS area on an
unexpanded Spectrum, and will contain 244, the low
byte of the PRINT_OUT routine at &09F4. With the
Interface 1 woken up, location 23734 is FLAGS3. As the
top four bits only ever have one set at a time it can never contain
&F4. So, the following code will set int1
to
non-zero if the Interface 1 is present, and sets it to zero on an
unexpanded Spectrum.
CLOSE#0:LET int1=(PEEK 23734<>244)The program can then do things like:
IF int1 THEN CLEAR#:OPEN #9,"b"
W CI\*]\k
. (The
JGHROM traps this error andUnknown command
.) In machine code,
though, you can trap this error and continue. This canXOR A:LD (INT1OK),A ; Assume unexpanded Spectrum LD HL,(ERR_SP):PUSH HL ; Save current ERR_SP CALL CheckInt1 ; Call the check code, stacking a return to here POP HL:LD (ERR_SP),HL ; Restore ERR_SP ; program continues... .CheckInt1 LD (ERR_SP),SP ; Point ERR_SP to the return from here RST &08:DEFB &31 ; Attempt to initialise Interface 1 LD A,&FF:LD (INT1OK),A ; Set flag to non-zero to show Interface 1 present RETAn alternative method is as follows:
XOR A:LD (INT1OK),A ; Assume unexpanded Spectrum LD HL,(ERR_SP):PUSH HL ; Save current ERR_SP LD HL,CheckRet:PUSH HL ; Fake a return address to CheckRet LD (ERR_SP),SP ; Point ERR_SP to return address RST &08:DEFB &31 ; Attempt to initialise Interface 1 LD A,&FF:LD (INT1OK),A ; Set flag to non-zero to show Interface 1 present POP HL ; Lose CheckRet from stack .CheckRet ; An error returns to here POP HL:LD (ERR_SP),HL ; Restore ERR_SP ; program continues...