0010 OPT FNorg(&0010) 0010 .PRNTA1 0010 C3 F1 15 JP &15F1 0013 .PRHEX0 0013 16 30 LD D,ASC"0" ; Print B with leading zero 0015 .PRHEX 0015 C3 02 3A JP PrHexByte ; Print B with D=lead 0025 OPT FNorg(&0025) 0025 .SCANHEX 0025 C3 FF 0E JP ScanHexDE ; Convert (CHADD) to hex in DE 002B OPT FNorg(&002B) 002B .PR2HEX0 002B 16 30 LD D,ASC"0" ; Print BC with leading zeros 002D .PR2HEX 002D C3 FB 39 JP PrHexWord ; Print BC with D=lead 003A OPT FNorg(&003A) 003A 21 78 5C LD HL,FRAMES 003D 34 INC (HL) ; Update FRAMES without depending on IY 003E 20 08 JR NZ,KEYINT 0040 23 INC HL 0041 34 INC (HL) 0042 20 04 JR NZ,KEYINT 0044 23 INC HL 0045 34 INC (HL) 0046 00 NOP 0047 00 NOP 0048 .KEYINT 0048 ; 005F OPT FNorg(&005F) 0060 OPT FNorg(&0060) 0060 .SEARCH_TABLE 0060 C3 2C 02 JP SearchTable ; Search table at DE for string at HL 0063 .TKNISE 0063 C3 EC 38 JP Tokenise ; Tokenise line at HL to DE 0066 ; 0066 .NMI 0066 F5 PUSH AF 0067 E5 PUSH HL ; Fix bug in NMI routine 0068 2A 80 5C LD HL,(NMIADD) ; Old NMIADD at &5CB0 now used by Interface1 006B 7C LD A,H 006C B5 OR L ; &5C80 used to be PR_CC 006D 28 01 JR Z,&0070 ; Return if zero 006F ; 006F ; 006F ; Shorten token strings 006F ; ===================== 006F ; Remove spaces from tokens, allows tokeniser to work more effectively. 006F ; 0119 OPT FNorg(&0119) 0119 44 45 46 46 CE DEFM FNm("DEFFN") 011E 43 41 D4 DEFM FNm("CAT") 0121 46 4F 52 4D 41 D4 DEFM FNm("FORMAT") 0127 4D 4F 56 C5 DEFM FNm("MOVE") 012B 45 52 41 53 C5 DEFM FNm("ERASE") 0130 4F 50 45 4E A3 DEFM FNm("OPEN#") 0135 43 4C 4F 53 45 A3 DEFM FNm("CLOSE#") 013B 4D 45 52 47 C5 DEFM FNm("MERGE") 0140 ; Remove spaces from DEFFN, INPUT# and CLOSE# 0140 56 45 52 49 46 D9 DEFM FNm("VERIFY") 0146 42 45 45 D0 DEFM FNm("BEEP") 014A 43 49 52 43 4C C5 DEFM FNm("CIRCLE") 0150 49 4E CB DEFM FNm("INK") 0153 50 41 50 45 D2 DEFM FNm("PAPER") 0158 46 4C 41 53 C8 DEFM FNm("FLASH") 015D 42 52 49 47 48 D4 DEFM FNm("BRIGHT") 0163 49 4E 56 45 52 53 C5 DEFM FNm("INVERSE") 016A 4F 56 45 D2 DEFM FNm("OVER") 016E 4F 55 D4 DEFM FNm("OUT") 0171 4C 50 52 49 4E D4 DEFM FNm("LPRINT") 0177 4C 4C 49 53 D4 DEFM FNm("LLIST") 017C 53 54 4F D0 DEFM FNm("STOP") 0180 52 45 41 C4 DEFM FNm("READ") 0184 44 41 54 C1 DEFM FNm("DATA") 0188 52 45 53 54 4F 52 C5 DEFM FNm("RESTORE") 018F 4E 45 D7 DEFM FNm("NEW") 0192 42 4F 52 44 45 D2 DEFM FNm("BORDER") 0198 43 4F 4E 54 49 4E 55 C5 DEFM FNm("CONTINUE") 01A0 44 49 CD DEFM FNm("DIM") 01A3 52 45 CD DEFM FNm("REM") 01A6 46 4F D2 DEFM FNm("FOR") 01A9 47 4F 54 CF DEFM FNm("GOTO") 01AD 47 4F 53 55 C2 DEFM FNm("GOSUB") 01B2 ; Remove spaces from GOTO and GOSUB 01B2 49 4E 50 55 D4 DEFM FNm("INPUT") 01B7 4C 4F 41 C4 DEFM FNm("LOAD") 01BB 4C 49 53 D4 DEFM FNm("LIST") 01BF 4C 45 D4 DEFM FNm("LET") 01C2 50 41 55 53 C5 DEFM FNm("PAUSE") 01C7 4E 45 58 D4 DEFM FNm("NEXT") 01CB 50 4F 4B C5 DEFM FNm("POKE") 01CF 50 52 49 4E D4 DEFM FNm("PRINT") 01D4 50 4C 4F D4 DEFM FNm("PLOT") 01D8 52 55 CE DEFM FNm("RUN") 01DB 53 41 56 C5 DEFM FNm("SAVE") 01DF 52 41 4E 44 4F 4D 49 5A C5 DEFM FNm("RANDOMIZE") 01E8 49 C6 DEFM FNm("IF") 01EA 43 4C D3 DEFM FNm("CLS") 01ED 44 52 41 D7 DEFM FNm("DRAW") 01F1 43 4C 45 41 D2 DEFM FNm("CLEAR") 01F6 52 45 54 55 52 CE DEFM FNm("RETURN") 01FC 43 41 4C CC DEFM FNm("CALL") 0200 ; Replace 'COPY' with 'CALL' 0200 ; 0200 ; 0200 ; Part of new keyboard routines 0200 OPT FNorg(&0200) ; Space after Token table 0200 .KeyScanAscii 0200 5F LD E,A 0201 16 80 LD D,&80 ; E=key, D=Ascii 0203 BF CP A 0204 C9 RET ; Set Z and return 0205 ; 0205 ; 0205 ; Search a token table 0205 ; ==================== 0205 ; DE=table start (no prefix byte) 0205 ; HL=string to decode 0205 ; C=token value to start with. Stops when C=0 0205 ; B=flags, IgnoreCase/NoAbbrs/Termination/ 0205 ; 022C OPT FNorg(&022C) ; This was extended mode table 022C .SearchTable 022C E5 PUSH HL ; Save pointer to input string 022D .SearchLoop 022D 1A LD A,(DE) ; Get character from table 022E E6 7F AND &7F 0230 BE CP (HL) ; Lose terminator bit 0231 28 22 JR Z,SearchMatch ; Jump if characters match 0233 CB 78 BIT 7,B ; Ignore case 0235 28 05 JR Z,SearchTryDot ; Case must match 0237 EE 20 XOR &20 0239 BE CP (HL) ; Change case and try again 023A 28 19 JR Z,SearchMatch ; Jump if characters match 023C .SearchTryDot 023C CB 70 BIT 6,B ; Abbreviations allowed? 023E 20 06 JR NZ,SearchNext ; Not allowed 0240 7E LD A,(HL) 0241 FE 2E CP ASC"." ; Abbreviation? 0243 23 INC HL 0244 28 40 JR Z,SearchDot 0246 ; 0246 .SearchNext ; No match 0246 1A LD A,(DE) 0247 13 INC DE ; Look for token terminator 0248 87 ADD A,A 0249 30 FB JR NC,SearchNext ; Loop until b7 set 024B E1 POP HL ; Retrieve input pointer 024C 1A LD A,(DE) 024D 3C INC A ; Test current byte 024E 28 03 JR Z,SearchQuit ; &00 is a terminator 0250 0C INC C ; Step to next token value 0251 20 D9 JR NZ,SearchTable ; Loop if not come to end 0253 .SearchQuit ; Will always have Cy=set by here 0253 7E LD A,(HL) ; Run out of tokens, so fetch current byte 0254 C9 RET ; Return, signalling no match 0255 ; 0255 .SearchMatch ; Current bytes match 0255 1A LD A,(DE) ; Get current byte 0256 13 INC DE 0257 23 INC HL ; Point to next src & dst chars 0258 87 ADD A,A ; Was it a terminating char? 0259 30 D2 JR NC,SearchLoop ; Look at more characters 025B CD FC 0A CALL SearchCheck ; Correctly teminated? 025E 18 24 JR SearchContinue 0260 ; 0260 ; 0260 ; New symbol-shift table 0260 ; ---------------------- 026A OPT FNorg(&026A) 026A 7E 2A 3F 5C C8 DEFM "~*?\"+CHR$&C8 ; ABCDE 026F 7B 7D 5E 7F DEFM "{}^"+CHR$&7F ; FGHI 0273 2D 2B 3D 2E 2C 3B 22 DEFM "-+=.,;""" ; JKLMNOP 027A C7 3C 7C 3E 5D 2F DEFM CHR$&C7+"<|>]/"; QRSTUV 0280 C9 60 5B 3A DEFM CHR$&C9+"`[:" ; WXYZ 0284 ; 0284 ; 0284 OPT FNorg(&0284) 0284 .SearchContinue 0284 30 C0 JR NC,SearchNext ; No, try for next token 0286 .SearchDot 0286 D1 POP DE ; Drop original input pointer 0287 2B DEC HL ; Point to last char 0288 79 LD A,C ; Pass token to A 0289 A7 AND A 028A C9 RET ; Return, signalling token found 028B ; 3 spare bytes at &028B-&028D 028B ; 028B ; 028B ; Replaced and extended keyboard routines 028B ; ======================================= 028B ; There is no longer an 'E' mode. System will also 028B ; take keypresses from an Ascii keyboard. Port 253 028B ; should return the Ascii data and port 249 should 028B ; return keyboard status, b0=shift, b1=control, 028B ; b4=control codes need translating 028B ; 028B ; Scan Spectrum keyboard, then Ascii keyboard 028B ; ------------------------------------------- 028E OPT FNorg(&028E) ; KEY_SCAN 028E 2E 2F LD L,&2F 0290 C3 8E 03 JP KeyScanNew 0293 .KeyScan2 0293 ; 0293 ; Test if keypress is valid 0293 ; ------------------------- 031E OPT FNorg(&031E) ; K_TEST 031E CD 9E 03 CALL KeyTestNew ; Test the keypress 0321 C8 RET Z ; Return if Ascii keypress 0322 ; 0322 ; Decode keypress 0322 ; --------------- 0333 OPT FNorg(&0333) ; K_DECODE 0333 ; D=FLAGS, C=MODE, 0=KLC, 1=E, 2=G 0333 ; B=Shift/etc, E=(keycode)AND 127 0333 ; =%00xxxxxxx - Spectrum key, with shift key 0333 ; =%111111111 - Spectrum key, no shifts pressed 0333 ; =%1b0000000 - Ascii key, b=original bit7 0333 ; 0333 CD AC 0E CALL KeyDecodeAscii; Try to decode if Ascii 0336 D0 RET NC ; Return if Ascii 0337 0D DEC C 0338 7B LD A,E 0339 FE 3A CP &3A; PreDEC C 033B 38 1F JR C,KeyDigit 033D 0D DEC C ; Graphics mode? 033E 20 03 JR NZ,KeyLetter ; MODE<>2, jump forward 0340 C6 4F ADD A,&4F 0342 C9 RET ; Return graphics code 0343 .KeyLetter 0343 21 29 02 LD HL,&0229 ; Symbol Shift table 0346 CB 40 BIT 0,B 0348 20 05 JR NZ,KeyNoSymbol 034A .KeyLookup 034A 16 00 LD D,0 034C 19 ADD HL,DE 034D 7E LD A,(HL) 034E C9 RET ; Fetch code and return 034F .KeyNoSymbol 034F FD CB 30 5E BIT 3,(IY+48) 0353 28 02 JR Z,KeyNoCaps 0355 EE 20 XOR &20 ; Make lower case if no CAPSLOCK 0357 .KeyNoCaps 0357 04 INC B 0358 C0 RET NZ ; Return if CAPS not pressed 0359 EE 20 XOR &20 ; Change case, flip CAPSLOCK effect 035B C9 RET 035C .KeyDigit 035C FE 30 CP ASC"0" 035E D8 RET C ; Return with Enter, Extend, Space 035F 0D DEC C 0360 28 18 JR Z,KeyDigitGraph 0362 04 INC B 0363 C8 RET Z ; No SHIFT pressed, return '0'-'9' 0364 CB 68 BIT 5,B 0366 21 30 02 LD HL,&0230 0369 20 DF JR NZ,KeyLookup ; CAPS -> use Shift table 036B D6 10 SUB &10 ; Convert '0'-'9' to ' ' to ')' 036D FE 22 CP &22 036F 28 06 JR Z,KeyAtChar 0371 FE 20 CP &20 0373 C0 RET NZ ; Return with '1','#'-')' 0374 3E 5F LD A,&5F 0376 C9 RET ; '0'->'_' 0377 .KeyAtChar 0377 3E 40 LD A,&40 0379 C9 RET ; '2'->'@' 037A .KeyDigitGraph 037A 21 30 02 LD HL,&0230 037D FE 39 CP &39 037F 28 C9 JR Z,KeyLookup ; Graph-'9' 0381 FE 30 CP &30 0383 28 C5 JR Z,KeyLookup ; Graph-'0' 0385 E6 07 AND 7 0387 C6 80 ADD A,&80 ; &80-&87 0389 04 INC B 038A C8 RET Z ; Shift not pressed 038B EE 0F XOR &0F 038D C9 RET ; &8F-&88 038E ; 038E .KeyScanNew 038E 11 FF FF LD DE,&FFFF 0391 CD 93 02 CALL KeyScan2 0394 C8 RET Z ; Return if Spectrum key pressed 0395 DB FD IN A,(253) 0397 FE FF CP 255 ; Fetch from Ascii keyboard 0399 C2 00 02 JP NZ,KeyScanAscii ; Jump if key pressed 039C A7 AND A 039D C9 RET ; NZ=No key pressed 039E ; 039E .KeyTestNew 039E 42 LD B,D 039F 16 00 LD D,0 ; B=shift/flag, preload D with 0 for lookup 03A1 ; SpecNoShift SpecShift Ascii 03A1 78 LD A,B ; A=%11111111, %00xxxxxx, %10000000 03A2 3C INC A ; A=%00000000, %00xxxxxx, %10000001 03A3 FE 80 CP &80 03A5 7B LD A,E ; A=key value 03A6 D8 RET C ; Return if Spectrum key, with NZ set 03A7 E6 7F AND 127 03A9 37 SCF ; Ensure b7=0, Cy=1 03AA CB 7B BIT 7,E 03AC C8 RET Z ; Return if Ascii<&80, Z set 03AD CB F0 SET 6,B 03AF BF CP A 03B0 C9 RET ; Remember old b7 and return, Z set 03B1 00 NOP ; 4 spare bytes 03B2 00 NOP 03B3 00 NOP 03B4 00 NOP 03B5 ; 03B5 ; 04AA OPT FNorg(&04AA) ; 24 spare bytes at &04AA-&04C1 04AA .Cat ; Catalogue from tape 04AA CD 30 25 CALL SYNTAX_Z 04AD C4 17 0B CALL NZ,OpenS ; Open 'S' 04B0 CD 76 39 CALL CatRoutine ; Should first do if needed 04B3 CD EE 1B CALL &1BEE ; This MUST be a CALL, otherwise crashes! 04B6 C9 RET 04B7 .KeyNull 04B8 87 ADD A,A 04B9 E6 80 AND &80 04BB B3 OR E ; Retrieve bit7 04BC 5F LD E,A 04BD 3E 7F LD A,&7F 04CE C9 RET ; A=Ascii key, Z=Copyright 04BF 00 NOP 04C0 00 NOP 04C1 ; 04C1 ; 04C1 ; Allow SAVE s$ CODE s,l,e,r,t 04C1 ; ============================ 06F6 OPT FNorg(&06F6) 06F6 CD 6E 38 CALL SaCodeExtra ; Fetch length, look for extra, reload, type 06F9 ; 0981 OPT FNorg(&0981) ; Fix WaitKey bug 0981 CD 45 15 CALL WaitKey 0984 ; 0984 ; 0984 ; Fix PRINTOUT bugs, and prevent colour errors 0984 ; ============================================ 0A11 OPT FNorg(&0A11) 0A11 51 DEFB &51 ; CHR$6 skips superflous CALL 0A12 ; 0A15 OPT FNorg(&0A15) 0A15 43 DEFB &43 ; CHR$10 does down 0A16 42 DEFB &42 ; CHR$11 does up 0A17 53 DEFB &53 ; CHR$12 does CLS 0A18 ; 0A32 OPT FNorg(&0A32) ; Fix CHR$8 bug 0A32 3E 19 LD A,&19 0A34 ; 0A45 OPT FNorg(&0A45) ; Fix CHR$9 bug 0A45 3E 80 LD A,&80 0A47 CD D9 0A CALL PO_ABLE ; Print char, then PO_STORE 0A4A ; 0A69 OPT FNorg(&0A69) 0A69 C9 RET ; Unprintable codes ignored 0A6A C3 AF 0D JP &0DAF ; CHR$12->CLS 0A6D ; 0AAC OPT FNorg(&0AAC) 0AAC D8 RET C 0AAD 00 NOP 0AAE 00 NOP ; Ignore AT out of range 0ABC OPT FNorg(&0ABC) 0ABC D8 RET C 0ABD 00 NOP 0ABE 00 NOP ; Ignore AT out of range 0ABF ; 0ABF ; 0ABF ; Remove all references to ZX printer routines 0ABF ; ============================================ 0A4F OPT FNorg(&0A4F) ; PO_ENTER 0A4F 0E 21 LD C,&21 0A51 CD 55 0C CALL &0C55 0A54 05 DEC B 0A55 C3 D9 0D JP &0DD9 0A58 C3 64 3A JP PO_UPDOWN ; CHR$10,CHR$11 0A5B 00 NOP ; 7 spare bytes 0A5C 00 NOP 0A5D 00 NOP 0A5E 00 NOP 0A5F 00 NOP ; Could use for CHR$14,15 0A60 00 NOP 0A61 00 NOP 0A62 ; 0AA3 OPT FNorg(&0AA3) 0AA3 18 04 JR &0AA9 ; BIT 1,(FLAGS) 0AA5 .Cls2 ; 4 spare bytes 0AA5 3E 0C LD A,12 0AA7 D7 RST &10 0AA8 C9 RET ; JR NZ,PO_AT_SET 0AA9 ; 0ADC OPT FNorg(&0ADC) ; PO_STORE 0ADC FD CB 02 46 BIT 0,(IY+oTVFLAG) 0AE0 20 08 JR NZ,PO_ST_E ; Jump for lower screen 0AE2 ED 43 88 5C LD (SPOSN),BC 0AE6 22 84 5C LD (DFCC),HL 0AE9 C9 RET 0AEA .PO_ST_E 0AEA ED 43 8A 5C LD (SPOSNL),BC 0AEE ED 43 82 5C LD (ECHOE),BC 0AF2 22 86 5C LD (DFCCL),HL 0AF5 C9 RET 0AF6 ; 0AF6 .Cls 0AF6 CD 17 0B CALL OpenS 0AF9 18 AA JR Cls2 0AFB ; 0AFB .SearchCheck 0AFB CB 68 BIT 5,B 0AFD C8 RET Z ; Return if freely terminatable 0AFE 7E LD A,(HL) 0AFF FE 41 CP ASC"A" ; Check following char 0B01 C9 RET ; C=terminated ok 0B02 00 NOP 0B03 ; 0B03 OPT FNorg(&0B03) ; PO_FETCH 0B03 ED 4B 88 5C LD BC,(SPOSN) 0B07 2A 84 5C LD HL,(DFCC) 0B0A FD CB 02 46 BIT 0,(IY+oTVFLAG) 0B0E C8 RET Z 0B0F ED 4B 8A 5C LD BC,(SPOSNL) 0B13 2A 86 5C LD HL,(DFCCL) 0B16 C9 RET 0B17 .OpenS ; Six spare bytes 0B17 3E 02 LD A,2 0B19 C3 01 16 JP &1601 ; BIT 1,(FLAGS) 0B1C 00 NOP ; JR NZ,PO_F_PR 0B1D ; 0B1D OPT FNorg(&0B1D) 0B1D .HexAlphanum 0B1D FE 26 CP ASC"&" 0B1F 37 SCF 0B20 C8 RET Z ; Return if "&" 0B21 C3 88 2C JP &2C88 ; Continue into ALPHANUM 0B24 ; 0B87 OPT FNorg(&0B87) 0B87 18 0A JR &0B93 0B89 ; 0B89 OPT FNorg(&0B89) ; Finish Tape catalogue 0B89 .CatKeypress ; Key pressed, quit catalogue 0B89 E1 POP HL ; Lose error trap address 0B8A .CatError ; BREAK pressed, quit catalogue 0B8A E1 POP HL 0B8B 22 3D 5C LD (ERR_SP),HL ; Restore error handler 0B8E FD 36 00 FF LD (IY+0),&FF ; Clear any error 0B92 C9 RET ; Exit, workspace reclaimed by STMT_LOOP 0B93 ; 0BAB OPT FNorg(&0BAB) 0BAB 18 09 JR &0BB6 0BAD ; 0BAD .PrinterWait ; Wait for Centronics ready 0BAD CD DB 0D CALL BreakCheck 0BB0 DB FB IN A,(251) 0BB2 87 ADD A,A 0BB3 30 F8 JR NC,PrinterWait 0BB5 C9 RET 0BB6 ; 0BBE OPT FNorg(&0BBE) 0BBE 00 NOP 0BBF 00 NOP 0BC0 ; 0BD3 OPT FNorg(&0BD3) ; Send to Centronics when ready 0BD3 .PrinterRaw 0BD3 F5 PUSH AF 0BD4 CD AD 0B CALL PrinterWait 0BD7 F1 POP AF 0BD8 D3 FB OUT (251),A 0BDA C9 RET 0BDB ; 0C55 OPT FNorg(&0C55) ; PO_SCR 0C55 00 NOP 0C56 00 NOP 0C57 00 NOP 0C58 00 NOP 0C59 00 NOP ; No ZX printer 0C5A ; 0C93 OPT FNorg(&0C93) 0C93 CD 49 16 CALL PrintSave ; Save ATTR/MASK/PFLAG 0C96 3E FD LD A,&FD 0C98 CD 01 16 CALL &1601 0C9B AF XOR A 0C9C 11 F8 0C LD DE,&0CF8 0C9F CD 0A 0C CALL &0C0A 0CA2 FD CB 02 EE SET 5,(IY+oTVFLAG) 0CA6 21 3B 5C LD HL,&5C3B 0CA9 CB DE SET 3,(HL) 0CAB CB AE RES 5,(HL) 0CAD CD 45 15 CALL WaitKey ; Fix 'scroll?' bug 0CB0 FE 20 CP &20 0CB2 28 4C JR Z,&0D00 0CB4 FE E2 CP &E2 0CB6 28 48 JR Z,&0D00 0CB8 F6 20 OR &20 0CBA FE 6E CP &6E 0CBC 28 42 JR Z,&0D00 0CBE CD 17 0B CALL OpenS 0CC1 CD 43 0D CALL PrintRest 0CC4 18 0C JR &0CD2 0CC6 .StrFix ; Use 12 spare bytes here 0CC6 EB EX DE,HL 0CC7 CD 49 16 CALL PrintSave 0CCA EB EX DE,HL 0CCB CD 15 16 CALL &1615 0CCE CD 43 0D CALL PrintRest 0CD1 C9 RET 0CD2 ; 0D10 OPT FNorg(&0D10) 0D10 CD 49 16 CALL PrintSave ; Save ATTR/MASK/PFLAG 0D13 CD 4D 0D CALL &0D4D 0D16 78 LD A,B 0D17 .POSCR4A 0D17 F5 PUSH AF 0D18 21 6B 5C LD HL,DFSZ 0D1B 46 LD B,(HL) 0D1C 78 LD A,B 0D1D 3C INC A 0D1E 77 LD (HL),A 0D1F 21 89 5C LD HL,SPOSN+1 0D22 BE CP (HL) 0D23 38 03 JR C,POSCR4B 0D25 34 INC (HL) 0D26 06 17 LD B,&17 ; Don't scroll into ROM 0D28 .POSCR4B 0D28 CD 00 0E CALL &0E00 0D2B F1 POP AF 0D2C 3D DEC A 0D2D 20 E8 JR NZ,POSCR4A 0D2F CD 43 0D CALL PrintRest 0D32 ED 4B 88 5C LD BC,(SPOSN) 0D36 FD CB 02 86 RES 0,(IY+oTVFLAG) 0D3A CD D9 0D CALL &0DD9 0D3D FD CB 02 C6 SET 0,(IY+oTVFLAG) 0D41 C1 POP BC 0D42 C9 RET 0D43 .PrintRest 0D43 E1 POP HL 0D44 F1 POP AF 0D45 32 91 5C LD (P_FLAG),A 0D48 E3 EX (SP),HL 0D49 22 8F 5C LD (ATTR_T),HL 0D4C C9 RET 0D4D ; 0DD9 OPT FNorg(&0DD9) ; CL_SET 0DD9 18 07 JR &0DE2 0DDB .BreakCheck 0DDB CD 54 1F CALL BREAK_KEY ; Check BREAK key 0DDE D2 7B 1B JP NC,&1B7B 0DE1 C9 RET ; Generate error if pressed 0DE2 ; 0EAC OPT FNorg(&0EAC) 0EAC .KeyDecodeAscii 0EAC 78 LD A,B 0EAD 3C INC A 0EAE FE 80 CP &80 0EB0 D8 RET C ; Return if Spectrum key 0EB1 DB F9 IN A,(249) 0EB3 57 LD D,A ; Get keyboard status 0EB4 78 LD A,B 0EB5 CD B9 04 CALL KeyNull ; E=A=Ascii key 0EB8 C8 RET Z 0EB9 7B LD A,E ; &00->&7F Copyright 0EBA FE 7F CP &7F 0EBC 30 19 JR NC,KeyFunc ; &7F+function keys 0EBE FE 20 CP &20 0EC0 D0 RET NC ; Printable character 0EC1 C6 8F ADD A,143 ; Convert to graphics char 0EC3 CB 4A BIT 1,D 0EC5 C0 RET NZ ; Return if Ctrl pressed 0EC6 7B LD A,E ; Retrieve key 0EC7 CB 62 BIT 4,D 0EC9 C8 RET Z ; No translation required 0ECA FE 15 CP &15 0ECC 38 02 JR C,KeyCtrl 0ECE D6 07 SUB 7 0ED0 .KeyCtrl 0ED0 21 DF 0E LD HL,AsciiCodes-8 ; Index into control key translation 0ED3 5F LD E,A 0ED4 C3 4A 03 JP KeyLookup 0ED7 .KeyFunc 0ED7 3E 0C LD A,12 0ED9 C8 RET Z ; 127->12 Delete 0EDA 7B LD A,E 0EDB E6 8F AND &8F 0EDD 5F LD E,A ; E=&80+key offset 0EDE 7A LD A,D 0EDF 87 ADD A,A 0EE0 87 ADD A,A 0EE1 87 ADD A,A 0EE2 87 ADD A,A ; Move Ctrl/Shift into position 0EE3 E6 30 AND &30 0EE5 B3 OR E 0EE6 C9 RET ; Form ascii value 0EE7 .AsciiCodes 0EE7 0F DEFB &0F 0EE8 0E DEFB &0E 0EE9 06 DEFB &06 0EEA 09 DEFB &09 ; BS TAB LF -> 0EEB 1E DEFB &1E 0EEC 0D DEFB &0D 0EED 08 DEFB &08 0EEE 00 DEFB &00 ; HOME RETURN <- * 0EEF 00 DEFB &00 0EF0 07 DEFB &07 0EF1 0A DEFB &0A 0EF2 0B DEFB &0B ; * CLEAR Dn Up 0EF3 1B DEFB &1B ; ESCAPE 0EF4 ; 0EF4 ; 0EF4 ; Hexadecimal input 0EF4 ; ================= 0EF4 .ScanHexDE 0EF4 ED 53 5D 5C LD (CH_ADD),DE ; Point to input string 0EF8 .ScanHex ; Put ScanHex routine here 0EF8 11 00 00 LD DE,&0000 ; Initialise DE for BIN and hex 0EFB FE C4 CP &C4 0EFD 37 SCF 0EFE C8 RET Z ; Ret with BIN, Cy=1, Z=1 0EFF FE 26 CP ASC"&" ; Ret if not "&", Cy=1, Z=0 0F01 37 SCF 0F02 C0 RET NZ ; Ret if not "&", Cy=1, Z=0 0F03 .ScanHexLoop 0F03 CD 74 00 CALL &74 0F06 CD 1B 2D CALL &2D1B 0F09 30 0B JR NC,ScanHexDigit ; '0'-'9' 0F0B FE 41 CP ASC"A" 0F0D 3F CCF 0F0E D0 RET NC ; Cy=0 - Done 0F0F E6 DF AND &DF ; Force to upper case 0F11 FE 47 CP ASC"F"+1 0F13 D0 RET NC 0F14 D6 07 SUB 7 ; "A" -> "9"+1 0F16 .ScanHexDigit 0F16 D6 30 SUB ASC"0" ; "0".."F" -> &00..&0F 0F18 CB 23 SLA E 0F1A CB 12 RL D 0F1C CB 23 SLA E 0F1E CB 12 RL D 0F20 CB 23 SLA E 0F22 CB 12 RL D 0F24 CB 23 SLA E 0F26 CB 12 RL D ; DE=DE*16 0F28 B3 OR E 0F29 5F LD E,A ; Put bottom digit in 0F2A 18 D6 JR ScanHexLoop ; NB No overflow check! 0F2C ; 0F2C ; 0FA7 OPT FNorg(&0FA7) 0FA7 4B DEFB &4B ; Ignore Shift-Symbol in editing 0FA8 ; 0FDB OPT FNorg(&0FDB) ; Wearmouth current line cursor bugfix 0FDB FD 35 10 DEC (IY+16) 0FDE CD 55 18 CALL &1855 0FE1 FD 34 10 INC (IY+16) 0FE4 ; 10CB OPT FNorg(&10CB) 10CB 30 4E JR NC,&111B 10D1 OPT FNorg(&10D1) 10D1 18 48 JR &111B 10D3 ; 10D3 ; Fix CLOSE# bug and restore #4 to "C" on closing 10D3 OPT FNorg(&10D3) 10D3 .CloseC2 10D3 EE 43 XOR ASC"C" 10D5 C2 0C 17 JP NZ,CloseC3 ; If not "C", return with zero 10D8 0E 15 LD C,21 10DA C9 RET ; Default entry for #4 10DA ; 10E6 OPT FNorg(&10E6) 10E6 FE 0F CP 15 ; Don't go into E mode 10E8 ; 10E8 ; 10E8 ; Silently search for a tape file 10E8 ; =============================== 10FA OPT FNorg(&10FA) ; 33 spare bytes at &10FA-&111A 10FA .TapeFind 10FA 11 11 00 LD DE,17 10FD DD 19 ADD IX,DE 10FF .TapeLp1 10FF CD DB 39 CALL WaitHdr 1102 01 00 0B LD BC,&0B00 1105 DD E5 PUSH IX 1107 .TapeLp2 1107 DD 7E 00 LD A,(IX+0) 110A DD AE EF XOR (IX-17) 110D B1 OR C 110E 4F LD C,A 110F DD 23 INC IX 1111 10 F4 DJNZ TapeLp2 1113 DD E1 POP IX 1115 79 LD A,C 1116 B7 OR A 1117 20 E6 JR NZ,TapeLp1 1119 C9 RET 111A ; 1 spare byte at &111A 111A ; 111A ; 111A ; Change startup and main command loop 111A ; ==================================== 11CC OPT FNorg(&11CC) 11CC AF XOR A 11CD D3 FE OUT (&FE),A ; Black border 11CF 3E 3F LD A,&3F 11D1 ED 47 LD I,A ; Initialise I 11D3 62 LD H,D 11D4 6B LD L,E ; HL=top of memory to clear 11D5 .RamFill 11D5 36 00 LD (HL),0 11D7 2B DEC HL 11D8 BC CP H 11D9 20 FA JR NZ,RamFill 11DB EB EX DE,HL 11DC D9 EXX 11DD ED 43 B4 5C LD (P_RAMT),BC 11E1 ED 53 38 5C LD (RASP),DE 11E5 22 7B 5C LD (UDC),HL 11E8 D9 EXX ; Saved values from NEW 11E9 04 INC B 11EA 28 2D JR Z,&1219 11EC 22 B4 5C LD (P_RAMT),HL ; Set top of accessible memory 11EF 11 AF 3E LD DE,&3EAF 11F2 01 A8 00 LD BC,&00A8 11F5 EB EX DE,HL 11F6 ED B8 LDDR ; Copy default UDC definitions 11F8 EB EX DE,HL 11F9 23 INC HL 11FA 22 7B 5C LD (UDC),HL 11FD 2B DEC HL ; Set UDC address 11FE 01 40 00 LD BC,&40 1201 ED 43 38 5C LD (RASP),BC ; Set default keyclicks 1205 3E 7F LD A,&7F 1207 DB FE IN A,(&FE) ; Check SYMBOL key 1209 EE 02 XOR 2 120B 0F RRCA 120C 0F RRCA 120D 38 0A JR C,&1219 120F 47 LD B,A ; Claim all memory if SYMBOL pressed 1210 7C LD A,H 1211 FE F8 CP &F8 1213 78 LD A,B 1214 38 03 JR C,&1219 ; If RAMTOP<&F800, use it 1216 21 FF F7 LD HL,&F7FF ; Otherwise, set RAMTOP=&F7FF 1219 ; 1244 OPT FNorg(&1244) ; Add "C" channel 1244 87 ADD A,A 1245 38 0C JR C,NoChanC ; SYMBOL not pressed 1247 21 86 17 LD HL,ChannelC 124A 0E 0C LD C,12 124C 1B DEC DE 124D ED B0 LDIR ; Copy to CHANS area 124F FD 36 E4 15 LD (IY-28),21 ; Attach stream 4 to "C" 1253 .NoChanC 1253 EB EX DE,HL 1254 2B DEC HL 1255 22 57 5C LD (&5C57),HL ; Set DATADD, PROG, VARS 1258 23 INC HL 1259 22 53 5C LD (&5C53),HL 125C 22 4B 5C LD (&5C4B),HL 125F 36 80 LD (HL),&80 1261 23 INC HL 1262 22 59 5C LD (&5C59),HL 1265 3E 47 LD A,&47 ; White on black 1267 ; 1287 OPT FNorg(&1287) ; Overwrite CALL CLEAR_PRB 1287 FD CB 30 DE SET 3,(IY+48) ; Set CAPS LOCK 128B CD 59 19 CALL FSInit ; Set default drive, etc. 128E ; 12B1 OPT FNorg(&12B1) ; Main command prompt 12B1 CD DA 38 CALL EnterTokens ; Enter line and tokenise it 12B4 ; 1308 OPT FNorg(&1308) 1308 00 NOP 1309 3A 3A 5C LD A,(&5C3A) 130C 3C INC A ; Get ERR_NR 130D FE 1C CP &1C 130F 38 02 JR C,&1313 ; Error in range? 1311 3E 14 LD A,&14 ; Replace with 'Unknown command' 1313 ; 1296 OPT FNorg(&1296) ; New startup message 1296 11 24 15 LD DE,MsgCopyright-1 ; Point to moved startup message 1299 ; 134A OPT FNorg(&134A) 134A 11 22 15 LD DE,MsgComma-1 ; Point to moved ', ' message 134D ; 134D ; 134D ; Alter error messages 134D ; ==================== 140C OPT FNorg(&140C) 140C 53 54 4F D0 DEFM FNm("STOP") ; was "STOP statement" 1410 49 6E 76 61 6C 69 64 20 61 72 67 75 6D 65 6E F4 DEFM FNm("Invalid argument") 1420 49 6E 74 65 67 65 72 20 6F 75 74 20 6F 66 20 72 61 6E 67 E5 DEFM FNm("Integer out of range") 1434 4D 69 73 74 61 6B E5 DEFM FNm("Mistake") ; Was "Nonsense in BASIC" 143B 42 52 45 41 4B 20 2D 20 43 4F 4E 54 20 72 65 70 65 61 74 F3 DEFM FNm("BREAK - CONT repeats") 144F 4F 75 74 20 6F 66 20 44 41 54 C1 DEFM FNm("Out of DATA") 145A 49 6E 76 61 6C 69 64 20 66 69 6C 65 6E 61 6D E5 DEFM FNm("Invalid filename") 146A 4E 6F 20 72 6F 6F 6D 20 66 6F 72 20 6C 69 6E E5 DEFM FNm("No room for line") 147A 53 54 4F 50 20 69 6E 20 49 4E 50 55 D4 DEFM FNm("STOP in INPUT") 1487 46 4F 52 20 77 69 74 68 6F 75 74 20 4E 45 58 D4 DEFM FNm("FOR without NEXT") 1497 49 6E 76 61 6C 69 64 20 49 2F 4F 20 64 65 76 69 63 E5 DEFM FNm("Invalid I/O device") 14A9 55 6E 6B 6E 6F 77 6E 20 63 6F 6D 6D 61 6E E4 DEFM FNm("Unknown command") ; Was "Invalid colour" 14B8 42 52 45 41 4B 20 69 6E 74 6F 20 70 72 6F 67 72 61 ED DEFM FNm("BREAK into program") 14CA 52 41 4D 54 4F 50 20 6E 6F 20 67 6F 6F E4 DEFM FNm("RAMTOP no good") 14D8 53 74 61 74 65 6D 65 6E 74 20 6C 6F 73 F4 DEFM FNm("Statement lost") 14E6 49 6E 76 61 6C 69 64 20 73 74 72 65 61 ED DEFM FNm("Invalid stream") 14F4 46 4E 20 77 69 74 68 6F 75 74 20 44 45 C6 DEFM FNm("FN without DEF") 1502 50 61 72 61 6D 65 74 65 72 20 65 72 72 6F F2 DEFM FNm("Parameter error") 1511 54 61 70 65 20 6C 6F 61 64 69 6E 67 20 65 72 72 6F F2 DEFM FNm("Tape loading error") 1523 .MsgComma 1523 2C A0 DEFM FNm(", ") 1525 .MsgCopyright 1525 7F DEFB 127 1526 31 39 38 32 20 53 69 6E 63 6C 61 69 72 20 52 65 73 65 61 72 63 68 20 4C 74 64 2C 20 4A 47 C8 DEFM FNm("1982 Sinclair Research Ltd, JGH") 1545 ; 1545 ; 1545 ; Wait for and return a keypress 1545 ; ============================== 1545 .WaitKey 1545 FD CB 01 6E BIT 5,(IY+oFLAGS) 1549 28 FA JR Z,WaitKey ; Wait for keypress 154B CD 6E 0D CALL &0D6E ; Clear lower screen 154E .WaitGetKey 154E 3A 08 5C LD A,(&5C08) ; Get keypress 1551 C3 4F 1F JP &1F4F ; Clear keypress 1554 C9 RET 1555 ; 1555 ; 1555 ; New Centronics printer output 1555 ; ============================= 1555 ; Use port &FB directly as a Centronics port. 1555 ; OUT &FB,n writes data and strobes the port 1555 ; IN &FB returns a ready signal in bit 7. 1555 ; If b7=1, printer is ready. If b7=0, not ready. 1555 ; This also releases &5B00-&5BFF for other uses. 1555 ; 1555 ; Channel "P" (connected to stream 3) writes to 1555 ; the centronics port as text. 1555 ; Channel "C" (connected to stream 4) writes to 1555 ; the centronics port as raw data. 1555 ; 15B6 OPT FNorg(&15B6) ; Allow INPUT from channel "S" 15B6 A8 10 DEFW KEY_INPUT ; Needs 'help' in INPUT routine 15B8 ; 15BE OPT FNorg(&15BE) ; Redirect "P" to Centronics printer 15BE 43 3A DEFW PrinterOut ; New printer channel 15C0 ; 15EF OPT FNorg(&15EF) 15EF C6 30 ADD A,ASC"0" 15F1 37 SCF ; Printout called with SCF 15F2 1631 OPT FNorg(&1631) 1631 50 DEFB ASC"P" 1632 31 DEFB &31 ; Point to a RET 1633 ; 1638 OPT FNorg(&1638) ; Open channel 'K' 1638 FD CB 01 DE SET 3,(IY+1) ; Set 'L' mode, also fixes INKEY#0 bug 163C ; 1646 OPT FNorg(&1646) ; Open channel 'S' or 'K' 1646 C3 4D 0D JP &0D4D ; Exit via TEMPS 1649 ; 1649 .PrintSave ; 9 bytes at &1649 1649 2A 8F 5C LD HL,(ATTR_T) 164C E3 EX (SP),HL 164D 3A 91 5C LD A,(P_FLAG) 1650 F5 PUSH AF 1651 E9 JP (HL) 1651 ; 16D4 OPT FNorg(&16D4) ; 7 spare bytes, code never called 16D4 .ExecBasic 16D4 ED 73 3D 5C LD (ERR_SP),SP ; Set new error pointer 16D8 C3 8A 1B JP &1B8A ; Execute BASIC line 16EB OPT FNorg(&16EB) 16EB CD 0B 17 CALL CloseC ; Check for closing #4 16EE ; 1708 OPT FNorg(&1708) 1708 23 INC HL ; Have to start here for Int#1 1709 E1 POP HL 170A C9 RET ; Don't bother even looking in close table 170B .CloseC 170B 7A LD A,D 170C .CloseC3 170C 01 00 00 LD BC,0 170F FE 0E CP 14 1711 C0 RET NZ ; Return with zero if not #4 1712 E5 PUSH HL 1713 2A 4F 5C LD HL,(CHANS) 1716 0E 18 LD C,24 1718 09 ADD HL,BC ; Point to where "C" should be 1719 7E LD A,(HL) 171A E1 POP HL ; Get char from channel 171B C3 49 16 JP CloseC2 171E ; 1733 OPT FNorg(&1733) 1733 C3 39 19 JP CheckStream4 ; Prevent Int#1 from deleting "C" 1736 ; 1736 ; 1736 ; Allow OPEN to select any non-extended channel 1736 ; ============================================= 173C OPT FNorg(&173C) 173C E5 PUSH HL ; Save stream offset 173D 2A 4F 5C LD HL,(CHANS) 1740 E5 PUSH HL ; Save CHANS start 1741 78 LD A,B 1742 B1 OR C 1743 28 05 JR Z,Open2 ; Stream closed, open it 1745 09 ADD HL,BC 1746 7E LD A,(HL) ; Get output high byte 1747 A7 AND A 1748 28 DB JR Z,&1725 ; Invalid stream -> pass to Interface 1 174A .Open2 174A CD F1 2B CALL &2BF1 ; Fetch channel string 174D 78 LD A,B 174E B7 OR A ; Check string length 174F 20 03 JR NZ,Report_F ; String len>255 1751 0D DEC C 1752 28 02 JR Z,Open3 ; String len=1 1754 .Report_F 1754 CF RST &08 1755 0E DEFB &0E ; Invalid filename 1756 .Open3 1756 E1 POP HL 1757 E5 PUSH HL ; Get CHANS back 1758 1A LD A,(DE) ; Get channel character 1759 E6 DF AND &DF 175B 4F LD C,A 175C 06 05 LD B,5 ; First four are short entries 175E .OpenLp 175E 54 LD D,H 175F 5D LD E,L 1760 7E LD A,(HL) 1761 FE 80 CP &80 ; At end of CHANS? 1763 28 EF JR Z,Report_F ; No more channels, error 1765 CD BB 18 CALL &18BB 1768 23 INC HL ; Get channel char 1769 B9 CP C 176A 28 0C JR Z,OpenFound ; Matching character 176C 10 F0 DJNZ OpenLp ; Step on for first four entries 176E 04 INC B ; Ensure loop returns here 176F CD BB 18 CALL &18BB 1772 23 INC HL ; Get length low byte 1773 66 LD H,(HL) 1774 6F LD L,A ; Get channel length to HL 1775 19 ADD HL,DE 1776 18 E6 JR OpenLp ; Point to next channel 1778 .OpenFound 1778 E1 POP HL 1779 13 INC DE ; Get CHANS, point to output high byte 177A 1A LD A,(DE) 177B A7 AND A ; Is this an Interface 1 channel? 177C 28 A7 JR Z,&1725 ; Don't open Interface 1 channel 177E EB EX DE,HL 177F ED 52 SBC HL,DE 1781 EB EX DE,HL ; DE=channel offset 1782 E1 POP HL 1783 C3 83 0A JP &0A83 ; Set stream offset 1786 ; 1786 .ChannelC ; Channel "C" data 1786 D3 0B DEFW PrinterRaw 1788 C4 15 DEFW &15C4 178A 43 DEFB ASC"C" 178B 00 00 DEFW &0000 178D 00 00 DEFW &0000 178F 0B 00 DEFW &000B 1791 80 DEFB &80 1792 ; 1 spare byte at &1792 1792 ; 1792 ; 18F6 OPT FNorg(&18F6) ; Print cursor 18F6 CB DE SET 3,(HL) ; Keep in 'L' mode 18F8 ; 18F8 ; 1937 OPT FNorg(&1937) ; OUT_CHAR no longer needed as 1937 D7 RST &10 1938 C9 RET ; keyword entry removed (Wearmouth) 1939 ; 1939 ; 1939 ; Allow #4 to default to "C" on closing 1939 ; ===================================== 1939 .CheckStream4 ; 53 spare bytes at &1939-&196D 1939 57 LD D,A 193A 46 LD B,(HL) 193B 2B DEC HL 193C FE 0E CP 14 193E C0 RET NZ ; Not #4, return with offset 193F 04 INC B 1940 05 DEC B 1941 C0 RET NZ ; Offset not &00xx, return 1942 79 LD A,C 1943 FE 15 CP 21 ; Offset not &0015, return 1945 3E 0E LD A,14 1947 C0 RET NZ ; B is now &00 1948 E5 PUSH HL 1949 2A 4F 5C LD HL,(CHANS) 194C 09 ADD HL,BC 194D CD BC 18 CALL &18BC ; Get channel char 1950 E1 POP HL 1951 FE 43 CP ASC"C" ; Check if channel "C" 1953 3E 0E LD A,14 1955 C0 RET NZ ; Not "C", return 1956 0E 00 LD C,0 1958 C9 RET ; Return &0000 to stop overwriting 1959 ; 1959 ; 1959 ; Check for Interface 1 and set default drive 1959 ; =========================================== 1959 .FSInit 1959 FD 36 45 54 LD (IY+oCURDRV),ASC"T" ; Default to "T"ape 195D 01 00 FF LD BC,&FF00 ; Loop 255 times 1960 .FSInitLp 1960 DB F7 IN A,(&F7) 1962 B1 OR C 1963 4F LD C,A ; See if Interface 1 responds 1964 10 FA DJNZ FSInitLp 1966 79 LD A,C 1967 B7 OR A 1968 C0 RET NZ ; Return if not zero 1969 FD 36 45 31 LD (IY+oCURDRV),ASC"1" ; Set to drive 1 196D C9 RET 196E ; 196E ; 196E ; Extend Basic to allow more commands 196E ; =================================== 1AAB OPT FNorg(&1AAB) 1AAB 05 DEFB &05 ; Parameters may follow 1AAC 84 3A DEFW Run ; RUN/RUN n/RUN s$ 1AAE ; 1ABE OPT FNorg(&1ABE) 1ABE 00 DEFB &00 ; No parameters 1ABF F6 0A DEFW Cls ; CLS 1AC0 ; 1B14 OPT FNorg(&1B14) 1B14 05 DEFB &05 ; Parameters may follow 1B15 AA 04 DEFW Cat ; Catalogue from tape 1B17 ; 1AD6 OPT FNorg(&1AD6) 1AD6 03 DEFB &03 ; One numeric parameter 1AD7 37 30 DEFW Call ; Was COPY 1AD9 ; 1B46 OPT FNorg(&1B46) 1B46 DA 69 3A JP C,UKCommand ; Was JP C,REPORT_C 1B49 ; 1C9A OPT FNorg(&1C9A) ; Wearmouth colours bugfix 1C9A C4 17 0B CALL NZ,OpenS ; Ensure "S" selected 1C9D 00 NOP 1C9E 00 NOP 1C9F 00 NOP 1CA0 00 NOP 1CC3 OPT FNorg(&1CC3) 1CC3 C4 17 0B CALL NZ,OpenS ; Ensure "S" selected 1CC6 00 NOP 1CC7 00 NOP 1CC8 00 NOP 1CC9 00 NOP 1CCA ; 1F15 OPT FNorg(&1F15) ; Make out of memory use standard error call 1F15 CF RST &08 1F16 03 DEFB &03 ; Should stop Microdrive crashing with drive on 1F17 00 NOP 1F18 00 NOP 1F19 00 NOP 1F1A ; 202C OPT FNorg(&202C) 202C CD EA 39 CALL HexOutput ; Check for PRINT ~ 202F ; 208E OPT FNorg(&208E) ; Wearmouth bugfix for INPUT 208E CD 6E 0D CALL &0D6E 2091 3E 01 LD A,1 2093 CD 01 16 CALL &1601 ; Clear lower screen, then select #1 2096 ; 2203 OPT FNorg(&2203) 2203 CD C3 1F CALL &1FC3 2206 F5 PUSH AF 2207 CD 94 1E CALL &1E94 220A 57 LD D,A 220B F1 POP AF 220C D7 RST &10 220D 7A LD A,D 220E D7 RST &10 220F A7 AND A 2210 C9 RET ; Colour items return with Carry clear 2211 ; 2244 OPT FNorg(&2244) 2244 C9 RET 2245 00 NOP ; Ignore colour out of range 2246 ; 2297 OPT FNorg(&2297) 2297 E6 0F AND 15 2299 EE 08 XOR 8 ; Ignore border colour out of range, ensure bright 229B ; 257D OPT FNorg(&257D) ; Fix SCREEN$ bug 257D C9 RET 257E ; 2 spare bytes 257E ; 257E ; 257E ; Allow &xxxx to enter hexadecimal numbers 257E ; ======================================== 2684 OPT FNorg(&2684) ; Line syntax checking 2684 CD 1D 0B CALL HexAlphanum ; Check if alphanum or "&" 2687 ; 26EF OPT FNorg(&26EF) 26EF DA 0B 3C JP C,UKFunction ; Was JP C,REPORT_C 26F2 ; 2C9B OPT FNorg(&2C9B) 2C9B CD F8 0E CALL ScanHex ; Try to read as hex 2C9E 30 13 JR NC,&2CB3 ; Stack DE if hex 2CA0 20 16 JR NZ,&2CB8 ; Try as decimal if not "BIN" and not "&" 2CA2 ; 2CA2 ; 2CA2 ; Fix truncate, STR$, -65536 and divide_bit34 bugs 2CA2 ; ================================================ 2CE3 OPT FNorg(&2CE3) ; Wearmouth bugfix 2CE3 04 DEFB &04 ; 10 instead of 1/10 2CE4 C0 DEFB &C0 2CE5 05 DEFB &05 ; d/10 instead of d*(1/10) 2CE6 ; 2E14 OPT FNorg(&2E14) ; Fix "x"+STR$y bug 2E14 A7 AND A 2E15 20 06 JR NZ,PF_SAVE ; A already holds D from INT_FETCH 2E17 B3 OR E 2E18 28 09 JR Z,PF_SMALL ; Move following code back one byte 2E1A 53 LD D,E 2E1B 06 08 LD B,8 2E1D .PF_SAVE 2E1D D5 PUSH DE 2E1E D9 EXX 2E1F D1 POP DE 2E20 D9 EXX 2E21 18 58 JR &2E7B ; PF_BITS 2E23 .PF_SMALL 2E23 EF RST &28 2E24 02 DEFB 2 ; Squeeze the extra 'delete' in 2E25 ; 3032 OPT FNorg(&3032) ; Fix -65536 bug in addition 3032 CD 25 32 CALL addCheckSmall 3035 D1 POP DE 3036 C9 RET 3037 ; 3037 ; 3037 ; CALL replaces COPY command 3037 ; ================================= 3037 .Call ; Use these 5 spare locations 3037 CD 99 1E CALL FIND_INT2 ; Get the address 303A C5 PUSH BC 303B C9 RET ; Jump to it 303C ; 303C ; 3223 OPT FNorg(&3223) ; Fix truncate bug 3223 18 1A JR &323F 3225 ; 3225 .addCheckSmall ; This space now available 3225 F5 PUSH AF 3226 3C INC A ; for -65536 bugfix 3227 B3 OR E 3228 B2 OR D 3229 20 08 JR NZ,ADD_STORE 322B F1 POP AF 322C 36 80 LD (HL),&80 322E 2B DEC HL 322F 36 91 LD (HL),&91 3231 F5 PUSH AF 3232 23 INC HL ; This is the error in CSRD 3233 .ADD_STORE 3233 F1 POP AF 3234 77 LD (HL),A 3235 23 INC HL 3236 73 LD (HL),E 3237 23 INC HL 3238 72 LD (HL),D 3239 2B DEC HL 323A 2B DEC HL 323B 2B DEC HL 323C C9 RET 323D ; 2 spare bytes at &323D-&323E 323D ; 31FF OPT FNorg(&31FF) ; Fix bit34 bug in divide 31FF 28 DA JR Z,&31DB 3201 ; 33FB OPT FNorg(&33FB) ; Stop SKIP_CONS from writing to ROM 33FB 00 NOP 33FC 00 NOP 33FD 00 NOP 33FE ; 33FE ; 33FE ; Allow STR$~ for conversion to hexadecimal 33FE ; ========================================= 2707 OPT FNorg(&2707) ; Prepare calculator for STR$ 2707 CD 20 3A CALL StrPreCheck ; Check for STR$~ 270A 30 02 JR NC,S_PUSH_PO2 ; Next char already checked 270C 00 NOP 270D .S_PUSH_PO 270D E7 RST &20 ; Get next char 270E .S_PUSH_PO2 270E C5 PUSH BC 270F ; 334F OPT FNorg(&334F) ; Change calcuator function &3C to STR$~ 334F 1F 36 DEFW &361F ; STR$~ - same as STR$ 3351 ; 362B OPT FNorg(&362B) ; STR$/STR$~ 362B 00 NOP 362C 00 NOP ; Replace LD A,&FF 362D CD 32 3A CALL HexOutputStr ; Replace CALL CHAN_OPEN 3630 CD E3 2D CALL &2DE3 ; PRINT_FP 3633 .StrDContinue 3633 E1 POP HL 3634 CD C6 0C CALL StrFix ; Restore channel and flags 3637 ; 364D OPT FNorg(&364D) 364D CD 49 16 CALL PrintSave ; Save colours 3650 2A 51 5C LD HL,(CURCHN) 3653 E5 PUSH HL 3654 CD 59 3A CALL InkFix 3657 30 03 JR NC,RIStore 3659 0C INC C 365A F7 RST &30 365B 12 LD (DE),A 365C .RIStore 365C CD B2 2A CALL &2AB2 365F E1 POP HL 3660 CD 15 16 CALL &1615 ; CHAN_FLAGS 3663 CD 43 0D CALL PrintRest ; Restore colours 3666 ; &3666 3666 ; 3666 ; 3666 ; Use spare space at end of ROM for extra code 3666 ; ============================================ 386E OPT FNorg(&386E) 386E ; 386E ; Extended LOAD/SAVE CODE 386E ; ======================= 386E .SaCodeExtra 386E CD 82 1C CALL EX_1NUM ; Fetch the 'length' 3871 3A 74 5C LD A,(T_ADDR) ; Get token offset 3874 FE 02 CP 2 3876 D0 RET NC ; Return if not LOAD or SAVE 3877 C1 POP BC ; Lose return address 3878 06 03 LD B,3 ; Maximum of three more parameters 387A .SaCodeLoop 387A DF RST &18 387B FE 2C CP ASC"," 387D 20 07 JR NZ,SaCodeFound ; No more parameters 387F C5 PUSH BC 3880 CD 81 1C CALL EX_1NEXT 3883 C1 POP BC 3884 10 F4 DJNZ SaCodeLoop ; Loop for any more 3886 .SaCodeFound 3886 ; B=0 - CODE s,l,e,r,t 3886 ; B=1 - CODE s,l,e,r 3886 ; B=2 - CODE s,l,e 3886 ; B=3 - CODE s,l 3886 CD EE 1B CALL CHECK_END ; Must be end of statement 3889 DD 36 00 03 LD (IX+0),3 ; Assume 'CODE' - type &03 388D 78 LD A,B 388E F5 PUSH AF 388F A7 AND A 3890 20 06 JR NZ,SaCodeReLoad ; Use preset filetype 3892 CD 99 1E CALL FIND_INT2 ; Get 'filetype' 3895 DD 71 00 LD (IX+0),C ; Store in header 3898 .SaCodeReLoad 3898 F1 POP AF 3899 F5 PUSH AF ; Get parameter count 389A FE 02 CP 2 389C 30 09 JR NC,SaCodeExec 389E CD 99 1E CALL FIND_INT2 ; Get 'reload' into BC 38A1 DD 71 0D LD (IX+13),C 38A4 DD 70 0E LD (IX+14),B ; Store in header 38A7 .SaCodeExec 38A7 F1 POP AF 38A8 F5 PUSH AF ; Get parameter count 38A9 FE 03 CP 3 38AB 30 09 JR NC,SaCodeLen 38AD CD 99 1E CALL FIND_INT2 ; Get 'extra' 38B0 DD 71 0F LD (IX+15),C 38B3 DD 70 10 LD (IX+16),B ; Store in header 38B6 .SaCodeLen 38B6 CD 99 1E CALL FIND_INT2 ; Get 'length' 38B9 DD 71 0B LD (IX+11),C 38BC DD 70 0C LD (IX+12),B ; Store in header 38BF CD 99 1E CALL FIND_INT2 ; Get 'start' 38C2 69 LD L,C 38C3 60 LD H,B ; HL=start address 38C4 F1 POP AF 38C5 FE 02 CP 2 38C7 38 0E JR C,SaCodeDone ; load & exec already set 38C9 28 06 JR Z,SaCodeLoad ; exec already set 38CB DD 71 0F LD (IX+15),C 38CE DD 70 10 LD (IX+16),B ; exec=start 38D1 .SaCodeLoad 38D1 DD 71 0D LD (IX+13),C 38D4 DD 70 0E LD (IX+14),B ; load=start 38D7 .SaCodeDone 38D7 ; HL=start, IX=>header, IX+0=type, IX+11/2=length, IX+13/14=start/reload, IX+15/16=extra 38D7 C3 5A 07 JP &075A ; Continue at SA_ALL 38DA ; 38DA ; 38DA ; Tokenise entered command line 38DA ; ============================= 38DA .EnterTokens 38DA FD 36 00 FF LD (IY+0),&FF ; Clear any errors 38DE CD 2C 0F CALL &0F2C ; Editor 38E1 2A 59 5C LD HL,(E_LINE) ; Point to command line 38E4 54 LD D,H 38E5 5D LD E,L ; src=dest=E_LINE 38E6 3A 6A 5C LD A,(FLAGS2) ; Default flags for tokeniser 38E9 E6 E0 AND &E0 38EB 47 LD B,A ; Pass top three bits into B 38EC ; 38EC .Tokenise 38EC 78 LD A,B 38ED E6 E0 AND &E0 38EF 47 LD B,A ; Clear tokeniser flags 38F0 ; b4=within a statement 38F0 ; b3=inside quotes 38F0 ; b2=|name 38F0 ; b1=REM or *command 38F0 ; b0=spare 38F0 ; 38F0 .TokenLoopZero 38F0 78 LD A,B 38F1 E6 E3 AND &E3 38F3 47 LD B,A ; Clear in-line flags 38F4 .TokenLoop 38F4 D5 PUSH DE ; Save dest pointer 38F5 4E LD C,(HL) ; Get current character 38F6 78 LD A,B ; Get tokeniser flags 38F7 E6 0F AND &0F 38F9 79 LD A,C ; Are any 'skip' flags set? 38FA 20 22 JR NZ,TokenByte ; Put the byte straight in 38FC FE 3C CP ASC"<" ; A character that can start a token? 38FE 38 1E JR C,TokenByte ; Chars<"<" not tokens 3900 ;BIT 4,B ; Within a statement? 3900 ; Need to check for "INKEY$", then commands, then functions 3900 ;JR Z,TokenNotFunction; Look at all tokens 3900 11 99 00 LD DE,&0099 ; Point to 'INKEY$' 3903 0E FF LD C,255 ; Only check one token 3905 CD 2C 02 CALL SearchTable ; Try to decode it 3908 3E A6 LD A,&A6 ; INKEY$ token 390A 30 12 JR NC,TokenByte ; Matched, put it in 390C ;.TokenNotFunction 390C 11 19 01 LD DE,&0119 ; Point to start of command tokens 390F 0E CE LD C,206 ; First token=CHR$206 3911 CD 2C 02 CALL SearchTable ; Try to decode it 3914 30 08 JR NC,TokenByte ; Enter token 3916 .TokenFunction 3916 11 96 00 LD DE,&0096 ; Point to start of function tokens 3919 0E A5 LD C,165 ; First token=CHR$165 391B CD 2C 02 CALL SearchTable ; Try to decode it 391E .TokenByte 391E D1 POP DE 391F 12 LD (DE),A ; Retrieve dest and store char or token 3920 23 INC HL 3921 13 INC DE ; Increment source and dest pointers 3922 ; 3922 FE 0D CP 13 3924 28 3E JR Z,TokenCR ; End of line reached 3926 FE 22 CP ASC"""" ; A quote? 3928 20 06 JR NZ,TokenNotQuote 392A 78 LD A,B 392B EE 08 XOR 8 392D 47 LD B,A ; Flip quotes flag 392E 18 C4 JR TokenLoop ; Go back for more 3930 ; 3930 .TokenNotQuote 3930 CB 58 BIT 3,B ; Inside quotes? 3932 20 C0 JR NZ,TokenLoop ; Don't check if inside quotes 3934 CB 48 BIT 1,B ; Stop tokenising? 3936 20 BC JR NZ,TokenLoop ; Don't check any more characters 3938 ; 3938 FE 3A CP ASC":" ; A colon? 393A 28 B4 JR Z,TokenLoopZero ; Go back for more, resetting in-line flags 393C ; 393C .TokenComma 393C FE 2C CP ASC"," ; A comma? 393E 20 04 JR NZ,TokenRem 3940 CB 90 RES 2,B ; End of RSX name 3942 18 B0 JR TokenLoop ; Go back for more 3944 ; 3944 .TokenRem 3944 FE EA CP 234 ; 'REM'? 3946 20 04 JR NZ,TokenCommand 3948 .TokenRem2 3948 CB C8 SET 1,B ; Flag no more tokenising 394A 18 A8 JR TokenLoop ; Go back for more 394C ; 394C .TokenCommand 394C FE CE CP 206 ; A command token? 394E 38 04 JR C,TokenRSX 3950 CB E0 SET 4,B ; Flag within a statement 3952 18 A0 JR TokenLoop ; Go back for more 3954 ; 3954 .TokenRSX 3954 CB 60 BIT 4,B ; At start of statement? 3956 20 9C JR NZ,TokenLoop ; Loop back if within a statement 3958 FE 2A CP ASC"*" ; *command? 395A 28 EC JR Z,TokenRem2 ; Treat as a REM 395C FE 7C CP ASC"|" ; Start of RSX command? 395E 20 94 JR NZ,TokenLoop ; No, loop back for more 3960 CB D0 SET 2,B ; Set RSX name flag 3962 18 90 JR TokenLoop ; Go back for more 3964 ; 3964 .TokenCR 3964 2A 5B 5C LD HL,(K_CUR) 3967 A7 AND A 3968 ED 52 SBC HL,DE ; Is K_CUR now past end of line? 396A 38 06 JR C,TokenFinished 396C 1B DEC DE 396D ED 53 5B 5C LD (K_CUR),DE ; Move K_CUR back to end of line 3971 13 INC DE 3972 .TokenFinished 3972 EB EX DE,HL ; Put dest pointer in HL 3973 C3 B9 16 JP &16B9 ; Reset pointers 3976 ; 3976 ; 3976 ; Extra commands 3976 ; ============== 3976 .CatRoutine 3976 CD 4D 0D CALL &0D4D ; Set PERM colours 3979 DF RST &18 397A CD 70 20 CALL &2070 ; STR_ALTER 397D CD C3 1F CALL &1FC3 ; Return if checking syntax 3980 DF RST &18 3981 CD 48 20 CALL PR_ST_END 3984 C0 RET NZ ; Return if not end of statement 3985 01 11 00 LD BC,17 3988 F7 RST &30 ; Create 17 bytes in the workspace 3989 D5 PUSH DE 398A DD E1 POP IX ; Pass its address to IX 398C 2A 3D 5C LD HL,(ERR_SP) 398F E5 PUSH HL ; Save old error return 3990 21 8A 0B LD HL,CatError 3993 E5 PUSH HL 3994 ED 73 3D 5C LD (ERR_SP),SP ; Set up error trap 3998 .CatLoop ; Allow error from LD_BYTES to end catalogue 3998 CD DB 39 CALL WaitHdr 399B ;JR Z,CatLoop 399B DD E5 PUSH IX ; Save pointer to header 399D DD 46 00 LD B,(IX+0) 39A0 CD 13 00 CALL PRHEX0 ; Print filetype 39A3 3E 20 LD A,ASC" " 39A5 D7 RST &10 39A6 06 0A LD B,10 39A8 .CatPrName ; Print out filename 39A8 DD 7E 01 LD A,(IX+1) 39AB D7 RST &10 39AC DD 23 INC IX 39AE 10 F8 DJNZ CatPrName 39B0 3E 20 LD A,ASC" " 39B2 D7 RST &10 39B3 DD 4E 03 LD C,(IX+3) 39B6 DD 46 04 LD B,(IX+4) 39B9 CD 2B 00 CALL PR2HEX0 ; Print start address 39BC 3E 2B LD A,ASC"+" 39BE 1E 02 LD E,2 39C0 .CatPrAddrs ; Print out addresses 39C0 D7 RST &10 ; Print '+' or ' ' 39C1 DD 4E 01 LD C,(IX+1) 39C4 DD 46 02 LD B,(IX+2) 39C7 CD 2B 00 CALL PR2HEX0 ; Print length or extra 39CA 01 04 00 LD BC,4 39CD DD 09 ADD IX,BC ; Move from length to extra 39CF 3E 20 LD A,ASC" " ; Print space next time around 39D1 1D DEC E 39D2 20 EC JR NZ,CatPrAddrs 39D4 3E 0D LD A,13 39D6 D7 RST &10 ; Print newline 39D7 DD E1 POP IX 39D9 18 BD JR CatLoop ; Loop back for another 39DB ; 39DB ; Wait for a tape header 39DB ; ---------------------- 39DB .WaitHdr 39DB DD E5 PUSH IX 39DD 11 11 00 LD DE,17 39E0 AF XOR A 39E1 37 SCF 39E2 CD 56 05 CALL &0556 ; Load 17 bytes 39E5 DD E1 POP IX 39E7 30 F2 JR NC,WaitHdr ; Loop until loaded 39E9 C9 RET 39EA ; 39EA ; 39EA ; Print hexadecimal numbers 39EA ; ========================= 39EA .HexOutput 39EA FE 7E CP ASC"~" ; Is current char '~'? 39EC C2 FB 24 JP NZ,SCANNING ; Jump if not to do as decimal 39EF F1 POP AF ; Lose return address 39F0 CD 81 1C CALL EX_1NEXT ; Scan next as numeric 39F3 CD C3 1F CALL UNSTACK_Z ; Return if syntax checking 39F6 .HexOutput2 ; Fetch number and print as hex 39F6 CD 99 1E CALL FIND_INT2 ; Get number to BC 39F9 16 00 LD D,0 ; Print with no leading zeros 39FB ; 39FB ; 39FB ; Print hexadecimal numbers 39FB ; ========================= 39FB .PrHexWord ; BC=value, D=0/48 39FB CD 0A 3A CALL PrHexTop ; Print top nybble 39FE CD 07 3A CALL PrHexByte2 ; Print second nybble 3A01 41 LD B,C ; Copy bottom byte to B 3A02 .PrHexByte ; B=value, D=0/48 3A02 CD 0A 3A CALL PrHexTop ; Print top nybble 3A05 16 30 LD D,ASC"0" ; Ensure zero printed 3A07 .PrHexByte2 3A07 78 LD A,B 3A08 18 05 JR PrHexDigit ; Print bottom nybble 3A0A .PrHexTop 3A0A 78 LD A,B 3A0B 1F RRA 3A0C 1F RRA 3A0D 1F RRA 3A0E 1F RRA 3A0F .PrHexDigit 3A0F E6 0F AND 15 3A11 20 02 JR NZ,PrHexDigitOk 3A13 B2 OR D 3A14 C8 RET Z ; Leading zero 3A15 .PrHexDigitOk 3A15 16 30 LD D,ASC"0" 3A17 B2 OR D 3A18 FE 3A CP ASC"9"+1 3A1A 38 02 JR C,PrHexDigitOk2 3A1C C6 07 ADD A,7 3A1E .PrHexDigitOk2 3A1E D7 RST &10 3A1F C9 RET ; Print digit 3A20 ; 3A20 ; 3A20 ; Conversion to hexadecimal 3A20 ; ========================= 3A20 .StrPreCheck ; Check for STR$/STR$~ 3A20 FE EE CP &EE 3A22 D8 RET C ; Return if <"STR$" 3A23 CB B9 RES 7,C 3A25 37 SCF 3A26 C0 RET NZ ; Set 'returns string', return if not "STR$" 3A27 E7 RST &20 3A28 FE 7E CP ASC"~" ; Followed by '~'? 3A2A 28 02 JR Z,StrPreHex 3A2C A7 AND A 3A2D C9 RET ; Decimal, return with next char fetched 3A2E .StrPreHex 3A2E 0E 7C LD C,&7C 3A30 37 SCF 3A31 C9 RET ; Change function to 'STR$~' and return 3A32 ; 3A32 .HexOutputStr ; Do STR$/STR$~ 3A32 F5 PUSH AF ; A=&2E*2 or &3C*2 for STR$ or STR$~ 3A33 3E FF LD A,&FF 3A35 CD 01 16 CALL &1601 ; Select 'R' stream 3A38 F1 POP AF 3A39 FE 78 CP &78 3A3B D8 RET C ; Return to do decimal if STR$ 3A3C F1 POP AF ; lose return address 3A3D CD F6 39 CALL HexOutput2 ; Fetch and print 3A40 C3 33 36 JP StrDContinue ; Finish STR$ function 3A43 ; 3A43 ; 3A43 ; Scan hexadecimal number in string 3A43 ; ================================= 3A43 .ScanHexInit 3A43 2A 5D 5C LD HL,(CH_ADD) 3A46 E5 PUSH HL ; Save current CH_ADD 3A47 3E 26 LD A,ASC"&" ; Prepare for scanning hex 3A49 1B DEC DE 3A4A CD F4 0E CALL ScanHexDE ; Scan string at DE 3A4D D5 PUSH DE 3A4E E1 POP HL ; HL=result 3A4F ED 5B 5D 5C LD DE,(CH_ADD) ; DE=>after string 3A53 E3 EX (SP),HL 3A54 22 5D 5C LD (CH_ADD),HL ; Restore CH_ADD 3A57 E1 POP HL 3A58 C9 RET 3A59 ; HL=result, DE=>after hex string, A=terminating character 3A58 ; 3A59 ; 3A59 ; Bugfix for INKEY$#n 3A59 ; =================== 3A59 .InkFix 3A59 79 LD A,C 3A5A CD 01 16 CALL &1601 3A5D CD E6 15 CALL &15E6 3A60 01 00 00 LD BC,0 3A63 C9 RET 3A64 ; 3A64 ; 3A64 ; Implement CHR$10, CHR$11 3A64 ; ======================== 3A64 .PO_UPDOWN 3A64 87 ADD A,A 3A65 E6 02 AND 2 3A67 3D DEC A ; Offset to new row 3A68 80 ADD A,B 3A69 FE 19 CP 25 3A6B D0 RET NC ; Off top of screen, ignore 3A6C 47 LD B,A 3A6D C5 PUSH BC 3A6E CD 55 0C CALL &0C55 3A71 C1 POP BC ; Check for scrolling 3A72 FD CB 02 46 BIT 0,(IY+oTVFLAG) 3A76 20 07 JR NZ,PO_UPDOWN2 ; Jump for lower screen 3A78 3A 6B 5C LD A,(DFSZ) 3A7B B8 CP B 3A7C 20 01 JR NZ,PO_UPDOWN2 3A7E 04 INC B ; Adjust if scrolled 3A7F .PO_UPDOWN2 3A7F C3 D9 0D JP &0DD9 ; Calculate DFCC and store 3A82 ; 3A82 ; 3A82 ; Centronics printer text/raw output 3A82 ; ================================== 3A82 .PrinterOut 3A82 FD CB 01 4E BIT 1,(IY+1) 3A86 20 1D JR NZ,PrintOutRaw ; Print raw characters if FLAGS.b1 set 3A88 FE A5 CP &A5 ; Is it a token? 3A8A 38 05 JR C,PrintOutText ; No, print a text character 3A8C D6 A5 SUB &A5 3A8E C3 10 0C JP &0C10 ; Print tokens 3A91 .PrintOutText 3A91 FE 20 CP 32 3A93 20 04 JR NZ,PrintOutChar 3A95 FD CB 01 C6 SET 0,(IY+1) ; Set 'leading space' 3A99 .PrintOutChar 3A99 30 0A JR NC,PrintOutRaw ; Send printable chars 3A9B FE 0D CP 13 3A9D 37 SCF 3A9E 3F CCF ; Ensure Carry clear 3A9F C0 RET NZ ; Ignore all but 3AA0 CD D3 0B CALL PrinterRaw 3AA3 3E 0A LD A,10 ; Add a 3AA5 .PrintOutRaw 3AA5 C3 D3 0B JP PrinterRaw 3AA8 ; 3AA8 ; 3AA8 ; Unrecognised command 3AA8 ; ============================================== 3AA8 ; Check for *command, |command, then UKCmd chain 3AA8 ; 3AA8 .UKCommand 3AA8 FE 5C CP ASC"*"-&CE+256 3AAA C2 0B 3C JP NZ,CheckRSX 3AAD CD 30 25 CALL SYNTAX_Z ; Deal with *command 3AB0 CA B2 1B JP Z,&1BB2 ; During syntax, treat as a REM 3AB3 DF RST &18 3AB4 CD E3 3A CALL Oscli ; GET_CHAR, HL=>command 3AB7 C3 B2 1B JP &1BB2 ; Skip line to adjust CH_ADD 3ABA ; 3ABA ; 3ABA ; Allow RUN s$ to call OSCLI 3ABA ; ========================== 3ABA .RunNull 3ABA CD E6 1C CALL USE_ZERO ; Use zero if no parameters 3ABD .RunNumber 3ABD CD EE 1B CALL CHECK_END ; Exit during syntax check 3AC0 C3 A1 1E JP &1EA1 ; RUN 3AC3 ; 3AC3 .Run 3AC3 CD 48 20 CALL PR_ST_END ; End of statement? 3AC6 28 F2 JR Z,RunNull 3AC8 CD FB 24 CALL SCANNING 3ACB FD CB 01 76 BIT 6,(IY+1) ; FLAGS 3ACF 20 EC JR NZ,RunNumber 3AD1 CD EE 1B CALL CHECK_END ; Exit during syntax check 3AD4 CD F1 2B CALL &2BF1 ; Get string parameters 3AD7 ; DE=string start 3AD7 ; BC=string length 3AD7 D5 PUSH DE ; Save string start 3AD8 03 INC BC 3AD9 F7 RST &30 ; Reserve space for string+CR 3ADA ; DE=reserved space 3ADA ; BC=length reserved 3ADA E1 POP HL 3ADB D5 PUSH DE ; HL=string start, save DE 3ADC ED B0 LDIR 3ADE 3E 0D LD A,13 ; Copy string to space 3AE0 1B DEC DE 3AE1 12 LD (DE),A ; Put terminating CR in place 3AE2 E1 POP HL ; Get start of CR-string 3AE3 ;CALL Oscli 3AE3 ;RET 3AE3 ; 3AE3 ; 3AE3 ; OSCLI - *commands to run code 3AE3 ; ============================= 3AE3 .Oscli ; Skip any '*'s or ' 's 3AE3 7E LD A,(HL) 3AE4 23 INC HL 3AE5 FE 2A CP ASC"*" 3AE7 28 FA JR Z,Oscli 3AE9 FE 20 CP ASC" " 3AEB 28 F6 JR Z,Oscli 3AED FE 2F CP ASC"/" 3AEF 28 01 JR Z,OscSlash 3AF1 2B DEC HL 3AF2 .OscSlash ; HL=>name 3AF2 7E LD A,(HL) 3AF3 FE 7C CP ASC"|" 3AF5 C8 RET Z ; Comment 3AF6 FE 20 CP ASC" " 3AF8 D8 RET C ; Null string 3AF9 ; 3AF9 47 LD B,A ; In case this is a driver spec 3AFA 23 INC HL 3AFB 7E LD A,(HL) 3AFC FE 3A CP ASC":" ; Look for "dxxx..." 3AFE 20 10 JR NZ,OscNotDrive1 ; No drive specifier 3B00 CB 70 BIT 6,B 3B02 28 02 JR Z,OscDrive 3B04 CB A8 RES 5,B ; Ensure upper case 3B06 .OscDrive 3B06 23 INC HL ; Move past drive spec 3B07 7E LD A,(HL) 3B08 FE 21 CP ASC"!" ; *d or *dname ? 3B0A 30 08 JR NC,OscNotDrive2 ; Following filename 3B0C FD 70 45 LD (IY+oCURDRV),B ; Set current drive 3B0F C9 RET 3B10 ; 3B10 .OscNotDrive1 3B10 2B DEC HL ; Point to filename start 3B11 FD 46 45 LD B,(IY+oCURDRV) ; Use current drive 3B14 .OscNotDrive2 3B14 C5 PUSH BC ; Save drive spec 3B15 22 5F 5C LD (X_PTR),HL ; Save pointer, in case RESERVE moves it 3B18 78 LD A,B ; Check drive 3B19 FE 54 CP ASC"T" 3B1B 28 0D JR Z,OscValid ; NC=Tape 3B1D FE 31 CP ASC"1" 3B1F 38 04 JR C,OscInvalid 3B21 FE 39 CP ASC"8"+1 3B23 38 02 JR C,OscMValid 3B25 .OscInvalid 3B25 CF RST &08 3B26 17 DEFB &17 ; Invalid I/O device 3B27 .OscMValid 3B27 CF RST &08 3B28 31 DEFB &31 ; Ensure Int#1 initialised 3B29 37 SCF ; C=MDrive 3B2A .OscValid 3B2A F5 PUSH AF ; Save Tape/MDrive flag 3B2B 01 22 00 LD BC,34 3B2E F7 RST &30 ; Reserve 34 bytes 3B2F 2A 5F 5C LD HL,(X_PTR) ; Get pointer back 3B32 F1 POP AF 3B33 C1 POP BC ; Get flags, drive spec back 3B34 D5 PUSH DE 3B35 DD E1 POP IX ; DE=IX=header area, HL=>command, B=drive 3B37 DA 7D 3B JP C,OscMDrive 3B3A ; 3B3A .OscTape ; Run a command from tape 3B3A 06 0A LD B,10 3B3C 3E 20 LD A,ASC" " ; Blank out ten characters 3B3E .OscHdrBlank1 3B3E 13 INC DE 3B3F 12 LD (DE),A 3B40 10 FC DJNZ OscHdrBlank1 3B42 06 06 LD B,6 3B44 AF XOR A ; Blank out three words 3B45 .OscHdrBlank2 3B45 13 INC DE 3B46 12 LD (DE),A 3B47 10 FC DJNZ OscHdrBlank2 3B49 3C INC A 3B4A 32 74 5C LD (T_ADDR),A ; T_ADDR=1 = LOAD 3B4D DD E5 PUSH IX 3B4F D1 POP DE ; Get header address back 3B50 CD F7 3B CALL OscFilename 3B53 E5 PUSH HL ; Pointer to parameters 3B54 DD 36 00 03 LD (IX+0),3 ; Looking for CODE 3B58 CD FA 10 CALL TapeFind ; Look for the specified file 3B5B CD 17 0B CALL OpenS ; Open 'S' 3B5E C1 POP BC ; Get =>parameters 3B5F 21 00 00 LD HL,0 3B62 39 ADD HL,SP ; Save old SP 3B63 31 B0 5C LD SP,TEMPSP ; Temporary stack in calculator area (15 deep) 3B66 E5 PUSH HL 3B67 C5 PUSH BC ; Save old SP, =>parameters 3B68 DD 6E 0F LD L,(IX+15) 3B6B DD 66 10 LD H,(IX+16) ; Get exec address 3B6E E5 PUSH HL ; If zero, should load to stack (or RST &30 space?) 3B6F 21 00 00 LD HL,0 3B72 CD CB 07 CALL &07CB ; Load the data block 3B75 76 HALT 3B76 F3 DI 3B77 C1 POP BC ; Get entry address 3B78 D1 POP DE ; =>Parameters 3B79 E1 POP HL 3B7A F9 LD SP,HL ; Restore stack, avoiding any writing to stack 3B7B 18 69 JR OscEnter ; BC=entry address 3B7D ; 3B7D .OscMDrive 3B7D E5 PUSH HL 3B7E C5 PUSH BC ; Save filename pointer, drive 3B7F 21 EB 3B LD HL,MDHdr 3B82 01 0C 00 LD BC,12 3B85 ED B0 LDIR 3B87 C1 POP BC 3B88 DD 70 08 LD (IX+8),B ; Set drive 3B8B E1 POP HL 3B8C 1B DEC DE 3B8D CD F7 3B CALL OscFilename 3B90 E5 PUSH HL ; Save parameter pointer 3B91 EB EX DE,HL 3B92 36 22 LD (HL),&22 ; Closing quote 3B94 23 INC HL 3B95 36 AF LD (HL),&AF ; CODE 3B97 23 INC HL 3B98 36 0D LD (HL),&0D ; 3B9A 23 INC HL 3B9B 36 80 LD (HL),&80 ; Terminator 3B9D 23 INC HL 3B9E EB EX DE,HL 3B9F ; 3B9F 2A 55 5C LD HL,(&5C55) 3BA2 E5 PUSH HL ; Save current BASIC context 3BA3 2A 59 5C LD HL,(E_LINE) 3BA6 E5 PUSH HL 3BA7 2A 61 5C LD HL,(WORKSP) 3BAA E5 PUSH HL 3BAB 2A 5D 5C LD HL,(CH_ADD) 3BAE E5 PUSH HL 3BAF 2A 3D 5C LD HL,(ERR_SP) 3BB2 E5 PUSH HL 3BB3 DD 22 59 5C LD (E_LINE),IX ; Point to BASIC command 3BB7 ED 53 61 5C LD (WORKSP),DE ; Move workspace up 3BBB FD 36 0A 01 LD (IY+10),1 ; Set to statement 1 3BBF CD D4 16 CALL ExecBasic ; Execute line 3BC2 E1 POP HL 3BC3 22 3D 5C LD (ERR_SP),HL ; Restore BASIC context 3BC6 E1 POP HL 3BC7 22 5D 5C LD (CH_ADD),HL 3BCA E1 POP HL 3BCB 22 61 5C LD (WORKSP),HL 3BCE E1 POP HL 3BCF 22 59 5C LD (E_LINE),HL 3BD2 E1 POP HL 3BD3 22 55 5C LD (&5C55),HL 3BD6 D1 POP DE ; Get parameter address 3BD7 2A E9 5C LD HL,(&5CE9) ; Get load address 3BDA ED 4B EB 5C LD BC,(&5CEB) ; Get exec address 3BDE 03 INC BC 3BDF 78 LD A,B 3BE0 B1 OR C ; Check if exec=&FFFF 3BE1 0B DEC BC 3BE2 20 02 JR NZ,OscEnter ; exec<>&FFFF - enter here 3BE4 4D LD C,L 3BE5 44 LD B,H ; exec=&FFFF - use load address 3BE6 .OscEnter 3BE6 69 LD L,C 3BE7 60 LD H,B 3BE8 37 SCF 3BE9 FB EI 3BEA E9 JP (HL) ; Enter code, BC=address, DE=>parameters 3BEB ; 3BEB .MDHdr 3BEB EF DEFB &EF 3BEC 2A DEFM "*" 3BED 22 DEFB &22 3BEE 6D DEFM "m" ; LOAD*"m 3BEF 22 DEFB &22 3BF0 3B DEFM ";" 3BF1 B0 DEFB &B0 3BF2 22 DEFB &22 ; ";VAL" 3BF3 31 DEFM "1" 3BF4 22 DEFB &22 3BF5 3B DEFM ";" 3BF6 22 DEFB &22 ; 1";" 3BF7 ; 3BF7 .OscFilename 3BF7 06 0A LD B,10 ; Up to ten characters 3BF9 .OscNameLp 3BF9 13 INC DE 3BFA 7E LD A,(HL) 3BFB FE 21 CP ASC"!" 3BFD 38 04 JR C,OscNameSpc ; End with SPC or CR 3BFF 23 INC HL 3C00 12 LD (DE),A 3C01 10 F6 DJNZ OscNameLp ; Loop for up to ten characters 3C03 .OscNameSpc 3C03 7E LD A,(HL) 3C04 23 INC HL ; Skip spaces 3C05 FE 20 CP ASC" " 3C07 28 FA JR Z,OscNameSpc 3C09 2B DEC HL 3C0A C9 RET 3C0B ; 3C0B ; 3C0B ; Check for resident system extensions 3C0B ; ==================================== 3C0B ; NB, unimplemented 3C0B ; 3C0B .CheckRSX 3C0B ;CP ASC"|"-&CE+256 3C0B ;JR Z,RSXCommand 3C0B .RSXCommand 3C0B .UKFunction 3B0B CF RST &08 3B0C 0B DEFB &0B 3B0D 00 NOP ; 'Mistake' error 3B0E ; 3B0E ; 3B0E ; End of finished code 3B0E ; ==================== 3B0E 76 30 2E 37 35 20 28 30 33 2D 4F 63 74 2D 32 30 30 34 29 DEFM "v"+ver$+" ("+vdate$+")" 3B21 00 DEFB 0 3B22 ; 3B22 ; ROM ends at &3CFF - about 200 bytes left 3B22 ;