> SJCCP139/SRC + SJ Research CCP as supplied with ZNOS 1 Source recreated and tweeked by J.G.Harston (: :2start%=&D800 : Start address, ZNOS=&D800, Acorn=&D400 7<jsc% = : Original JSC 'John Spencer Cox' version 5Fznos% = : Allowed to use workspace within ZNOS +Pbbc% = : BBC entry points available Zver$ ="1.39" dfn$ ="SJCCP/SYS" n: Dxstart%=&D400:jsc%=:znos%=:bbc%=:ver$="1.39" : Non-BBC SJCCP Hstart%=&D800:jsc%= :znos%= :bbc%= :ver$="1.39rz": Original SJCCP Fstart%=&D400:jsc%=:znos%=:bbc%= :ver$="1.39" : Non-ZNOS SJCCP : CDRIVE=4:BDOS=5:OSBYTE=&FFF4:OS_CLI=&FFF7:BRKV=&FFFA:FAULT=&FF82 : *ݤif(A%):A%:z%=-1:=opt% z%=P%:=opt% ;ݤendif:z%=-1:=opt% z%=P%-z%:P%=P%-z%:O%=O%-z%:=opt% Fݤelse:z%=-1:z%=P%:=opt% z%=P%-z%:P%=P%-z%:O%=O%-z%:z%=-1:=opt% : p%=3: mcode% &900  P=0 1:opt%=P*p%+4 O%=mcode%:P%=start% [OPT opt% CJP ColdReset :\ Execute any command in InputBuffer @JP WarmEntry :\ Clear InputBuffer and start CCP OPT if(jsc%) F"JP ResetCCP :\ Standard CCP must have only two entries >,OPT endif :\ Remove if not original version 86.InputBuffer:B &7F :\ Input buffer maximum size ;@.InputLength:B &00 :\ Input buffer length, 0=empty (J.InputText :M 16," "):B 13:B 10 %TOPT if( jsc%):M "S":OPT endif *^M "JCCP version ":M ver$:B 13:B 10 hOPT if(jsc%) OrM "Another quality product from JSC wundersystems":B 13:B 10:B 13:B 10 |OPT endif M "$" ,OPT if(jsc%):M "(C) SJ Research 1984." +OPT else :M "(C)SJ Research 1984." OPT endif : OPT if(jsc%) 9W &122B:W &0413:W &C20D:W &2B3A:W &E621:W &703B 9W &6E22:W &0E3A:W &CD02:W &1A48:W &DACD:W &2124 9W &4B95:W &9E22:W &CD3C:W &0CC6:W &92DA:W &222B 9W &3A6E:W &E67E:W &777F:W &7E23:W &40E6:W &B4C2 9W &7E2C:W &04E6:W &6BCA:W &232B:W &235E:W &0156 9W &0005:W &48CD:W &C31A:W &2B6B:W &072A:W &EB3B .W &0A01:W &CD00:W &1A48:W &0D01:B &01 OPT else M start%+&CB-P%,0) OPT endif &: 60.CCPstack :\ Top of internal stack :OPT if(jsc%) #D.LD8CB:W &052A :\ unused NOPT endif 8X.LD8CD :B &04 :\ Number of columns for DIR Ob.SEARCH:B &01 :\ Default command search drive if object not found @l.LD8CF :B &00 :\ Bad Filename flag in ReadFilename -v.ESCFLG:B &01 :\ Escape enabled 0.ADDR :W &00 :\ Address workspace 9.CCPDRV:B &00 :\ CCP's current search drive : $\ ------------------------------ $\ Restart CCP with current drive $\ ------------------------------ 1.ResetCCP:.entry% :\ Enter here if * 7LD A,(DRIVE):LD C,A :\ Get current drive/user .ColdReset =LD E,&FF:JR ColdEntry :\ E=&FF check embedded command : !\ --------------------------- \ C=drive to start with !\ No startup command executed ! \ --------------------------- .WarmEntry 9 SUB A:LD E,A :\ E=0, no embedded command 3*LD (InputLength),A :\ Clear input buffer 4: ,>\ -------------------------------------- H\ C=user+drive to start with +R\ E=0 no command, E<>0 embedded command ,\\ Input buffer contains embedded command ,f\ -------------------------------------- p.ColdEntry @zLD SP,CCPstack:PUSH DE :\ Set up stack, save startup flag OPT if(bbc%) LD HL,ErrorHandler 3LD (BRKV),HL :\ Set up error handler OPT endif 6LD HL,DRIVE:LD (HL),C :\ Save entry user/drive CLD C,&D: callBDOS :\ Reset disk system and select drive A: .SUB A:RLD:LD E,A:RRD :\ Get user to E )LD C,&20: BDOS :\ Select user <POP DE:LD A,(BATCH) :\ Get startup and batch flags G E:JR NZ,LD92B :\ Embedded command or batch, execute line =LD HL,(LF204):LD (ADDR),HL:\ Save BIOS warm start address 9LD HL,LD922:LD (LF204),HL :\ Redirect BIOS warm start LD C,&0F:LD DE,SUBFCB 8 BDOS :\ Try to open '$$$.SUB' file EINC A:JR Z,LD922 :\ Not there, jump to use console input 6LD A,&FF:LD (BATCH),A :\ Set batch file active $: ".\ Redirected WARM returns here 8.LD922 0BLD SP,CCPstack :\ Reset CCP stack @LLD HL,(ADDR):LD (LF204),HL:\ Restore BIOS warm start address V.LD92B H` add_CR:JP ExecInput :\ Execute any command and enter command loop j: t.commands ~M "DIR" :NOP:W dir M "TYPE" :NOP:W type M "ERA" :NOP:W era M "REN" :NOP:W ren M "SAVE" :NOP:W save M "USER" :NOP:W user M "LOAD" :NOP:W load M "GO" :NOP:W go M "VDU" :NOP:W vdu M "PRINT":NOP:W print M "OLD" :NOP:W old M "RUN" :NOP:W run M "RESET":NOP:W ResetCCP M "VERS" :NOP:W vers  NOP : .\ ---------------------------------------- .(\ VERS - Print CCP and ZNOS version string .2\ ---------------------------------------- <.title FB 13:B 10 %POPT if( jsc%):M "S":OPT endif *ZM "JCCP version ":M ver$:B 13:B 10 dM "$" n: x.vers LD DE,title )LD C,&09: BDOS :\ Print title 5LD C,&4A: BDOS :\ Get ZNOS version string -LD A,H: L:RET Z :\ HL=0, no ZNOS 8EX DE,HL:LD C,&09 :\ DE=>ZNOS version string 1 BDOS:JP CRLF :\ Print it and return : \ ------------- \ Error handler \ ------------- .ErrorHandler OPT if(bbc%) 9LD SP,CCPstack: CRLF:\ Reset stack and print newline 9LD HL,(FAULT) :\ Get address of error block .err_lp >INC HL:LD A,(HL) :\ Get character from error string ," A: NZ,PrChar :\ Print if not zero 6,JR NZ,err_lp: CRLF :\ Loop until zero terminator 6OPT endif @: J.LD9D3 TOPT if(bbc%) ;^LD A,&7E: OSBYTE :\ Acknowledge any pending Escapes hLD HL,(ESCFLG):LD H,0 1rLD A,&E5: OSBYTE :\ Restore Escape action 5|JP MainLoop :\ Return to command loop OPT endif : .LD9E5  CRLF .LD9E8 7 LDAA9 :\ Delete any '$$$.SUB' file # abort:M "* Aborted *":M "$" : @.abort :\ Print in-line message and abort CPOP DE: CRLF :\ Get address of message, print newline 7 PrMessage :\ Print message and newline : \ ------------------------ \ Main command prompt loop \ ------------------------ .MainLoop ;&LD SP,CCPstack: CRLF :\ Set up stack, print newline <0SUB A:LD (LD8CF),A :\ Clear 'Bad filename' flag :OPT if(bbc%) DLD HL,&FF00:LD A,&E5 /N OSBYTE:LD (ESCFLG),HL:\ Read escape state XOPT endif /bLD C,&20:LD E,&FF: BDOS :\ Get user number 4l A: NZ,PrDec :\ If non-zero, print it 2vLD A,(DRIVE): 15:LD E,A :\ Get current drive 1LD C,&0E: callBDOS :\ Select this drive 7INC A:LD (CCPDRV),A :\ Set CCP drive number 2ADD A,&40: PrChar :\ Print drive letter 7LD C,&4A: BDOS :\ Get ZNOS version string LD A,L: H OPT if(jsc%):LD A,")" =OPT else :LD A,">" :\ If no version string, use '>' OPT endif @JR Z,prompt:LD A,"]" :\ Version string present, use ']' .prompt B PrChar :\ If ZNOS, print A], if not print A> : LDA5D :\ Read a line to InputBuffer : .ExecInput ; SUB A:LD (InputLength),A :\ Set InputBuffer as empty LD C,&1A:LD DE,&80 0  BDOS :\ Set DMA to &0080 :* ExecLine :\ Execute line and loop back 4OPT if(jsc%):JP MainLoop >OPT else :JR MainLoop HOPT endif R: -\\ --------------------------------------- -f\ Delete $$$.SUB and read a line of input -p\ --------------------------------------- z.LDA5A 7 LDAA9 :\ Delete any '$$$.SUB' file : 5\ ----------------------------------------------- 5\ Read a line of input from console or batch file 5\ ----------------------------------------------- C\ Returns DE=>start of input line (expected by ERA and $$$.SUB) )\ HL=>end of input line, =>CR .LDA5D >LD A,(BATCH) :\ Is there a batch file active? E A:JR NZ,LDA78 :\ Jump to read a record from batch file LD DE,InputBuffer ?LD C,&0A: BDOS :\ Read a line of input from console :  .add_CR  LD A,(InputLength) 5 LD L,A:LD H,0 :\ HL=input line length 8$ LD DE,InputLength+1 :\ DE=>start of input line 6. ADD HL,DE :\ HL=>end of input line 68 LD (HL),13:RET :\ Put CR at end of text B : -L \ --------------------------------------- -V \ Read a record from '$$$.SUB' batch file -` \ --------------------------------------- j .LDA78 t LD C,&1A:LD DE,InputLength <~ BDOS :\ Set DMA address to InputBuffer 0 LD A,(SUBFCB+15) :\ Get RecordCount K DEC A:JP M,LDA5A :\ No more, delete $$$.SUB, read from console : PUSH AF:LD (SUBFCB+32),A :\ Set record number to read  LD C,&14:LD DE,SUBFCB ) BDOS :\ Read record B add_CR:LD H,D:LD L,E :\ Add CR and point HL to start of text .LDA98 > LD A,(HL) :\ Get character from input line 5 CP 13: NZ,PrChar :\ Display text to console 0 INC HL:JR NZ,LDA98 :\ Loop until 9 LDE19 :\ Check for keypress to abort 0 POP AF:LD (SUBFCB+15),A :\ Set RecordCount 5 RET NZ :\ Return if not at end  :  .LDAA9 : LD A,(BATCH): A:RET Z :\ No batch file, just return ( PUSH DE:LD C,&13 .2 LD DE,SUBFCB: BDOS :\ Delete '$$$.SUB' ;< SUB A:LD (BATCH),A :\ Set 'no batch file active' F POP DE:RET P : )Z \ ----------------------------------- )d \ Execute command line in InputBuffer )n \ ----------------------------------- x .ExecLine A LD DE,InputText :\ Point to start of input text : SkipSpace:LD (ADDR),DE :\ Save start of input text 0 CP ";":RET Z :\ Comment, exit  OPT if(bbc%) : CP "*":JR NZ,NotOscli :\ Jump past if not *command < LD HL,0:LD A,&E5: OSBYTE:\ Escape key sets Escape state CRLF , LD HL,InputText: OS_CLI :\ Do *command, N JP LD9D3 :\ Restore Escape, and go back to command loop  OPT endif  : \ -------------------------- \ Check for built-in command  \ --------------------------  .NotOscli 7 LD HL,commands :\ Point to command table " .comm_lp I, LD DE,(ADDR):LD A,(HL) :\ Get pointer to text, get byte from table H6 A:JR Z,comm_end :\ If at end of table, try to run from disk @ .comm_lp2 FJ GetCharNxt :\ Get upper case character from input line CT LD C,A:JR NZ,not_end :\ C=char, Z if end marker ( = ,) '^ SUB A :\ at end h .not_end @r CP (HL):JR NZ,no_match :\ Doesn't match, try next command 7| INC HL: A:JR NZ,comm_lp2:\ Check another character 4 LD A,(HL):INC HL:LD H,(HL):\ Get command address 7 LD L,A:LD A,C:JP (HL) :\ Enter with A=character .no_match 8 LD A,(HL): A:INC HL :\ Find end of command text 5 JR NZ,no_match :\ Loop until zero byte I INC HL:INC HL:JR comm_lp :\ Step past address and check next command  : " \ ---------------------------- " \ Try to run command from disk " \ ---------------------------- .comm_end 4 read_filename :\ Parse filename to FCB1 ; PUSH DE:LD DE,&65 :\ Point to extension in FCB1 : LD HL,com_txt:LD BC,3:LDIR:\ Force extension to '.COM' @ POP DE:LD A,(&5D) :\ Get first character of filename 7 CP " ":JP NZ,run_comm :\ If command there, run it & : /0 \ ----------------------------------------- /: \ No filename, see if drive specifier given /D \ ----------------------------------------- 8N LD A,(&5C):DEC A:RET M :\ No drive given, exit X .ResetDrive *b LD E,A:LD C,&E: callBDOS :\ Set drive 7l LD HL,DRIVE:LD A,(HL) :\ Get user from DRIVE .PrDecLp H INC B:SUB 10:JR NC,PrDecLp R LD C,A:LD A,B \ A: NZ,PrDigit f LD A,C:ADD A,10 p .PrDigit z ADD A,"0"  : * \ Print character in A, preserving all * \ ------------------------------------ .PrChar ' OPT if( znos%):PUSH AF:OPT endif  PUSH BC:PUSH DE:LD E,A 2 LD C,2: callBDOS :\ ZNOS preserves flags ; POP DE:POP BC :\ non-ZNOS needs to preserve & OPT if( znos%):POP AF:OPT endif  RET  : " \ Parse and check for filename " \ ---------------------------- .LDB64 )LD HL,&5C :\ HL=>FCB1 .LDB67 $PUSH HL: read_filename2 ;.LD C,A:POP HL:INC HL :\ HL=>first character of FCB 38LD A,(HL):CP " " :\ Check if no filename 7BLD A,C:RET NZ :\ Ok if filename present L.LDB73 $V abort:M "Syntax error":M "$" `: "j\ Parse filename at DE to FCB1 "t\ ---------------------------- ~.read_filename )LD HL,&5C :\ HL=>FCB1 : \ Parse filename at DE to HL \ -------------------------- \ On entry, DE=>text to scan \ HL=>FCB to fill )\ On exit, DE=>terminating character )\ A = terminating character "\ Z = valid filename \ NZ= bad filename 4\ Filename terminated with ',' or '=' .read_filename2 (PUSH HL:POP IX :\ IX=>FCB 1 LD (IX+0),0:LD (IX+&20),0 :\ Drive=0, default LD B,11 .LDB93 9(LD (IX+1)," " :\ Set filename+ext to spaces 2INC IX:DJNZ LDB93 <LD B,4 F.LDB9D 8PLD (IX+1),0 :\ Set rest of FCB to zero ZINC IX:DJNZ LDB9D 2dPUSH DE :\ Save line pointer 8n GetCharNxt:JR C,LDBD5:\ Error if control character :xLD C,A: GetUpChar :\ Save in C in case drive char 2CP ":":JR NZ,LDBBA :\ Not drive specifier DLD A,&3F: C:LD (HL),A :\ Convert to drive num or '?' and store 8INC SP:INC SP :\ Drop saved line pointer >PUSH DE :\ Replace with new line pointer .LDBBA ;POP DE:INC HL:PUSH HL :\ DE=>line, HL=>FCB filename FLD B,9 :\ Scan 9 characters (should this be 8?) .LDBBF 8 GetCharNxt:JR C,LDBD5:\ Error if control character 3JR NZ,LDBC8 :\ Skip if not at end >POP HL:RET :\ Drop saved pointer and return .LDBC8 8CP ".":JR Z,LDBD8 :\ Jump if '.' for extension 7CP "*": Z,LDC07 :\ If '*', fill rest with '?'s 0LD (HL),A :\ Store character -INC HL:DJNZ LDBBF :\ Step to next ".LDBD5 B,POP HL:JR LDBEE :\ Too many characters, bad filename 6.LDBD8 ,@POP HL :\ Get HL=>FCB 3JLD BC,8:ADD HL,BC :\ Point to extension FTLD B,4 :\ Scan 4 characters (should this be 3?) ^.LDBDF 8h GetCharNxt:JR C,LDBEE:\ Error if illegal character .rRET Z :\ End character 7|CP "*": Z,LDC07 :\ If '*', fill rest with '?'s 0LD (HL),A :\ Store character -INC HL:DJNZ LDBDF :\ Step to next .LDBEE 8LD A,(LD8CF): A:RET NZ :\ Return with bad filename .LDBF3 ( abort:M "Illegal filename":M "$" : .LDC07 ,LD A,"?" :\ Fill with '?' ?DEC B:JR Z,LDC12 :\ Only one to do, exit to caller .LDC0C ;LD (HL),A:INC HL :\ Fill rest of FCB with '?'s DJNZ LDC0C 8DEC HL:INC B :\ Point to last character .LDC12 3INC B:RET :\ Returns B=1 or B=2 &: $0\ Get character and step to next $:\ ------------------------------ %D\ On entry, DE=>current character 'N\ On exit, A =upper case character .X\ DE=>next character if not b.GetUpChar lLD A,(DE):CP 13:RET Z v &5F:CP "A" JR C,LDC22 6CP "[":JR C,LDC23 :\ 'a'-'z' becomes 'A'-'Z' .LDC22 LD A,(DE) .LDC23 INC DE:RET : $\ Get next character and test it $\ ------------------------------ %\ On entry, DE=>current character '\ On exit, A =upper case character .\ DE=>next character if not )\ Z = terminator , = spc cr %\ C = control character  .GetCharNxt 6 GetUpChar :\ Get upper case character @ CP 13:RET Z :\ Exit with terminating character *CP ",":RET Z 4CP "=":RET Z 7>CP " ":RET NZ :\ Exit with non-terminator .HPUSH AF: SkipSpace :\ Step past spaces >RPOP AF:RET :\ And return with Z= found \: f.SkipSpace pLD A,(DE) zCP " ":RET NZ INC DE:JR SkipSpace : 1\ Perform action if filename has no wildcards 1\ ------------------------------------------- .LDC41 @PUSH BC:LD HL,&5C :\ Save call number, point to FCB1 6LD BC,12:LD A,"?" :\ Search 12 bytes for '?' ECPIR:POP BC:JP Z,LDBF3 :\ If found, jump to 'Illegal filename' .LDC50 DLD DE,&5C:JP BDOS :\ Point to FCB1, call BDOS and return : %\ Call BDOS, preserving registers %\ ------------------------------- .callBDOS PUSH AF:PUSH DE:PUSH HL  BDOS $POP HL:POP DE:POP AF .RET 8: %B\ ------------------------------- %L\ DIR - List objects in catalogue %V\ ------------------------------- `.dir 4j read_filename :\ Parse filename to FCB1 :tSUB A:LD (LDD06),A :\ Set 'drive not specified' >~LD HL,&5D:LD A,(HL) :\ Get first character from FCB1 =CP " ":JR NZ,LDC76 :\ Jump as contains file to match 6LD B,11 :\ 11 characters to fill .LDC71 =LD (HL),"?" :\ Set filename to '????????.???' INC HL:DJNZ LDC71 .LDC76 ;LD A,(&5C) :\ Get drive number from FCB1 >CP "?":JR Z,LDC80 :\ If drive '?', use current drive @ A:JR NZ,LDC86 :\ If drive<>0, use specified drive .LDC80 ?LD (LDD06),A :\ Set drive to use to &00 or '?' 2LD A,(CCPDRV) :\ Get current drive .LDC86 6 ADD A,"@":LD (LDD05),A :\ Convert to drive letter .LD C,&11: LDC50 :\ Search for first 9INC A:JP Z,CRLF :\ If nothing found, return (LD C,1 2: <.LDC96  A:JR Z,LDCDD :\ If not '?', ignore user number ELD A,(HL):CP 10 :\ Get user number from directory entry 9 C,PrSpace: PrDec :\ Print space padded user number ".LDCDD <, PrSpace:LD B,11 :\ Prepare to print 11 characters 6.LDCE2 <@INC HL:LD A,(HL) :\ Get character from filename =J &7F: PrChar :\ Mask out bit7 and print character :TLD A,B:CP 4: Z,PrSpace:\ Print space before extension 7^DJNZ LDCE2 :\ Loop for 11 characters h: =r.LDCF1 :\ Step to next directory entry -|LD C,&12: BDOS :\ Search for next 9INC A:POP BC:JR NZ,LDC96 :\ Loop back if entry found 6JP CRLF :\ Finish with a newline : .PrSpace PUSH AF:LD A," " ; PrChar:POP AF:RET :\ Print space, saving registers : +.LDD05:B &2B :\ Drive letter =.LDD06:B &CD :\ Drive 0=current, <>0=specified : \ -------------------------- \ ǚ - Save memory to disk \ -------------------------- .LDD07 & abort:M "Catalogue full":M "$" : &.save <0 ScanDec:PUSH BC :\ Scan number of 256-byte blocks 4: LDB64 :\ Parse filename to FCB1 AD ScanHex:PUSH HL :\ Scan start address, default to &100 6NLD C,&13: LDC41 :\ Delete any existing file )XLD C,&16: LDC50 :\ Create file )bINC A:JR Z,LDD07 :\ Cat full 4lPOP DE:POP HL :\ DE=start, HL=length 0vSUB A:LD H,A :\ Ensure HL=&00nn >CP L:JR Z,LDD60 :\ Zero length, close and finish :ADD HL,HL :\ HL=num of 128-byte blocks OPT if(znos%) ?LD A,(&5C) :\ Check returned drive from Create @CP &10:JR Z,LDD65 :\ If &10, direct ZNOS ǚs available OPT endif : .LDD40 6PUSH HL:LD C,&1A :\ Save number of blocks FLD (LDD82),DE: BDOS :\ Save current address and set DMA address >LD C,&15: LDC50 :\ Write 128 bytes from current DMA ) A:JR NZ,LDD75 :\ Disk full @LD HL,(LDD82):LD DE,128 :\ Update to next 128-byte address ADD HL,DE:EX DE,HL C POP HL:DEC HL :\ Decrement number of blocks to save 9LD A,H: L:JR NZ,LDD40 :\ Loop back if more to save  : *.LDD60 64LD C,&10:JP LDC50 :\ Close file and return >: HOPT if(znos%) R.LDD65 =\PUSH HL :\ Save number of 128-byte blocks 4fLD C,&1A: BDOS :\ Set DMA address to start 1pPOP IX :\ Get save size back ?zLD C,&59: LDC50 :\ Save whole file, DMA=start, IX=size ? A:JR Z,LDD60 :\ Save ok, jump to close and return OPT endif : .LDD75 ! abort:M "Disc full":M "$" : 8.LDD82:W &AF30 :\ File save current address : \ ----------------------- \ USER - Select user area \ ----------------------- .user 0 ScanDec:LD A,C :\ Read decimal value .CP &20:JR NC,BadNumber :\ If >31, error /LD HL,DRIVE :\ Point to DRIVE .SetUser1 ;$RLD:LD A,C:RRD:LD E,C :\ Swap user into DRIVE b4-b7 ..GetSetUser 58LD C,&20:JP BDOS :\ Set BDOS user number B: (L\ ---------------------------------- $V\ - Send characters to printer (`\ ---------------------------------- j.print +tLD L,5:JR vdu2 :\ LST output ~: &\ -------------------------------- $\ - Send characters to console &\ -------------------------------- .vdu 2LD L,6 :\ Direct CON output .vdu2 0 ScanDec:PUSH DE :\ Read decimal value LD E,C:LD C,L 0 callBDOS :\ Send to LST or CON 7POP DE:CP 13:JR NZ,vdu2 :\ Loop until end of line RET : "\ Scan an 8-bit decimal number " \ ---------------------------- #\ On entry, DE=>first character \ On exit, A = number -(\ DE=>first non-digit character 2.ScanDec .<SUB A :\ Accumulator=0 F.ScanDecLp .PLD C,A :\ C=accumulator 0Z GetCharNxt:RET Z :\ Exit if terminator /dCP ":":JR NC,BadNumber :\ Non-digit, error /nSUB "0":JR C,BadNumber :\ Non-digit, error .xLD B,10 :\ Multipy by 10 .ScanDecAdd 3ADD A,C:JR C,BadNumber :\ Add 10*accumulator DJNZ ScanDecAdd 9JR ScanDecLp :\ Loop back for next digit .BadNumber " abort:M "Bad number":M "$" : !\ --------------------------- !\ TYPE - Type file to console !\ --------------------------- .type 4 LDB64 :\ Parse filename to FCB1 LD C,&0F >LD HL,&62:SET 7,(HL) :\ Set F6 flag to open Read-Only 1 LDC50 :\ Open file for input /INC A:JP Z,LDFCF :\ File not found " CRLF ,.LDDE8 ,6LD C,&14: LDC50 :\ Read 128 bytes =@ A:JR NZ,LDE14 :\ End of file, close and return EJLD B,128:LD HL,&80 :\ Prepare to type 128 bytes from &0080 T.type_lp 0^LD A,(HL) :\ Get a character >hCP &1A:JR Z,LDE14 :\ If character, jump to close rCP 13: Z,CRLF |CP 10: NZ,PrChar 0 LDE22 :\ Check for keypress 7PUSH AF: NZ,LDE14 :\ Close file if key pressed 5POP AF:JP NZ,LD9E5 :\ Abort if key pressed FINC HL:DJNZ type_lp :\ Point to next character and loop back ;JR LDDE8 :\ Loop for another 128 bytes : .LDE14 +LD C,&10:JP LDC50 :\ Close file : \ Abort if key pressed \ -------------------- .LDE19 0PUSH AF: LDE22 :\ Check for keypress GJP NZ,LD9E5 :\ If pressed, close batch file and abort POP AF:RET : &\ Check for keypress 0\ ------------------ ,:\ On exit, Z=no keypress, NZ=key pressed D.LDE22 /NPUSH BC:PUSH DE:PUSH HL :\ Save registers 0XLD C,&0B: BDOS :\ Get Console Status 5b A:JR Z,LDE37 :\ Nothing pending, exit /lLD C,1: BDOS :\ Get Console Input 4v LDAA9 :\ Delete any SUBMIT file 2SUB A:DEC A :\ A=&FF for aborted .LDE37 2POP HL:POP DE:POP BC :\ Restore registers RET : \ ----------------- \ ERA - Erase files \ ----------------- .txtERA B 13:B 10 OPT if(jsc%) (M "Erase all files (Y/N) ? ":M "$" OPT else 'M "Erase all files? (Y/N) ":M "$"  OPT endif .era 4  LDB64 :\ Parse filename to FCB1 ,*LD A,"?":LD B,11 :\ Check for *.* 4LD HL,&5C >.LDE60 7HINC HL:CP (HL) :\ Check character in FCB z LDA5D: GetUpChar :\ Get first character from input line -CP "Y":JP NZ,LD9E8 :\ Not 'Y', abort : .LDE79 /LD C,&13: LDC50 :\ Erase the file(s) /INC A:JP Z,LDFCF :\ File not found RET : \ ----------------- \ REN - Rename file \ ----------------- .ren 2LD HL,&6C: LDB67 :\ Parse first filename CP "=":JP NZ,LDB73  LDB64 .ren2 LD C,&11:LD DE,&6C 2$ BDOS :\ See if newname exits @.INC A:JR Z,LDEB3 :\ newname doesn't exist, go ahead +8 abort:M "File already exists":M "$" B.LDEB3 +LLD C,&17: LDC41 :\ Do the rename :VINC A:JP Z,LDFCF:RET :\ Error if source not found `: j.txtNF tM " not found":M "$" ~: \ ----------------------- \ - Run arbitary file \ ----------------------- .run 3 read_filename :\ Read filename to FCB1 @LD A,(&5D) :\ Get first character of filename ACP " ":JR Z,old :\ No filename, enter current program : ,\ -------------------------------------- ,\ Run a command file from command prompt ,\ -------------------------------------- .run_comm PUSH DE:LD HL,&100 7  LDF3D:POP DE :\ Load file in FCB1 to &100 : 5\ ----------------------------------------------- 4(\ ǘ - Enter current program with new parameters 52\ ----------------------------------------------- <.old 2FPUSH DE: LDF16 :\ Close any batch file P CRLF ZLD C,&1A:LD DE,&80 .d BDOS:POP DE :\ Set DMA to &0080 n.LDEEA CxPUSH DE :\ Save address of command parameters ALD A,&FF:LD (LD8CF),A :\ Prevent errors from ReadFilename 9 read_filename :\ Read first filename to FCB1 .LD HL,&6C :\ Point to FCB2 : read_filename2 :\ Read second filename to FCB2 BPOP DE :\ Get address of command parameters :LD HL,&80:PUSH HL :\ Point to parameter buffer >LD B,&FF:LD A,(DE) :\ Get character from input text ACP 13:JR Z,LDF06:DEC DE :\ Step back to prepare for GetChar .LDF06 = GetUpChar :\ Get a character from input line HINC HL:LD (HL),A:INC B :\ Store in parameter buffer and inc count 0SUB &0D:JR NZ,LDF06 :\ Loop until @LD (HL),A:POP HL :\ Store <00> at end of parameters KLD (HL),B:JP &100 :\ Store parameter length and execute program : \ Close any batch file "\ -------------------- ,.LDF16 <6LD A,(BATCH): A:RET Z :\ No batch file active, return /@PUSH DE:PUSH HL :\ Save registers JLD C,&10:LD DE,SUBFCB /TLD HL,SUBFCB+14:RES 7,(HL):\ Reset b7 of S2 (^ BDOS :\ Close file =hPOP HL:POP DE:RET :\ Restore registers and return r: |\ --------------- \ GO - Enter code \ -------------- .go = ScanHex :\ Scan hex value, default to &100 2 LDF16 :\ Close any batch file ( CRLF:JP (HL) :\ Enter code : $\ ------------------------------ "\ Ǖ - Load a file into memory $\ ------------------------------ .load 4 LDB64 :\ Parse filename to FCB1 @ ScanHex :\ Scan load address, default to &100  :  \ Load a file  \ ----------- & \ On entry, FCB1=filename "0 \ HL =start address : .LDF3D D PUSH HL:EX DE,HL -N LD C,&1A: BDOS :\ Set DMA address >X LD HL,&62:SET 7,(HL) :\ Set F6 flag to open Read-Only b .LDF49 l OPT if(znos%) 4v LD C,&5A: LDC50 :\ Attempt ZNOS direct load ; A:JR Z,LDF59 :\ Not supported, do manual load 7 INC A: Z,LDFB8 :\ Not found, try search drive 5 JR Z,LDF49 :\ Jump back to try again  POP HL:RET  OPT endif  : .LDF59 / LD C,&0F: LDC50 :\ Open file in FCB1 > INC A: Z,LDFB8 :\ If not found, try changing drive F JR Z,LDF49:POP DE :\ Another drive found, jump back to try .LDF65 5 LD C,&1A:LD (LDFFD),DE :\ Save current address 1 BDOS :\ And set DMA address ;!LD C,&14: LDC50 :\ Read 128 bytes to DMA address B ! A:JR NZ,LDF80 :\ Jump to finish when at End Of File 4!LD HL,(LDFFD) :\ Get current address @ !LD DE,&80:ADD HL,DE :\ Update to next 128-byte address :*!EX DE,HL:JR LDF65 :\ Loop back for next record 4!.LDF80 +>!LD C,&10:JP LDC50 :\ Close file H!: 1R!\ Scan an 16-bit hex address, default to &100 1\!\ ------------------------------------------- #f!\ On entry, DE=>first character p!\ On exit, A = number -z!\ DE=>first non-digit character !.ScanHex .!LD HL,&100 :\ Default value 6!LD A,(DE) :\ Get current character 7!CP 13: NZ,LDF94 :\ Not , scan hex number 4!CP 13:RET Z :\ Nothing after, exit 8!JP LDB73 :\ Abort with Syntax error !: !\ Scan an 16-bit hex address !\ -------------------------- !.LDF94 .!LD HL,0 :\ Accumulator=0 !.LDF97 0! GetCharNxt:RET Z :\ Exit if terminator 0"SUB "0" :\ Reduce to 0+digit ".LDF9D ,"JP C,BadNumber :\ <'0', error <$"CP 10:JR C,LDFAB :\ '0'-'9', add to accumulator 8."SUB 7 :\ Reduce 'A'-'F' to 10-15 ,8"CP &10:JP NC,BadNumber :\ >'F', error B".LDFAB =L"PUSH BC:LD B,4 :\ Prepare to move up four bits V".LDFAE <`"ADD HL,HL:JR C,LDF9D :\ Multiply by two, four times j"DJNZ LDFAE 8t"POP BC: L:LD L,A :\ Add digit to accumulator 4~"JR LDF97 :\ Loop for next digit ": "\ Try changing search drive "\ ------------------------- ".LDFB8 4"LD HL,&5C:LD A,(HL) :\ Get drive from FCB1 O" A:JR NZ,FileNotFound :\ If drive specified, print 'not found' and abort 6"LD A,(CCPDRV):LD B,A :\ Get CCP current drive 8"LD A,(SEARCH): A :\ Get command search drive G"JR Z,FileNotFound :\ No search drive, 'not found' and abort ="CP B:JR Z,FileNotFound :\ Same as current drive, abort 4"LD (HL),A :\ Store drive in FCB1 2"CP A:RET :\ Return with Z set #:  #.FileNotFound #.LDFCF 1# CRLF: LDFDE :\ Print filename in FCB1 /(#LD DE,txtNF: PrMessage:\ Print 'not found' 72#JP MainLoop :\ Return to command loop <#: F#\ Print filename in FCB1 P#\ ---------------------- Z#.LDFDE ?d#LD B,8 :\ Print up to first 8 characters n#LD HL,&5D: LDFF0 6x#LD A,".": PrChar :\ Print dot before extension C#LD B,3:LD HL,&65 :\ Print up to remaining 3 characters #: #\ Print B characters #\ ------------------ #.LDFF0 ?#LD A,(HL): &7F :\ Get character and mask out bit 7 :#CP &20:RET Z :\ Unprintable, return early 1# PrChar :\ Print the character :#INC HL:DJNZ LDFF0 :\ Loop to do all characters #RET #: 8#.LDFFD:W &26EE :\ File load current address #OPT if(jsc%) #$B &E5 :\ unused $OPT endif $: "$OPT if( znos%) ?,$.BATCH :B &00 :\ Batch file active flag ;6$.SUBFCB:B &01:M "$$$ SUB" :\ 'A $$$.SUB' filename +@$\ F240 :B &00 :\ EX +J$\ F241 :B &00 :\ S1 +T$\ F242 :B &00 :\ S2 +^$\ F243 :B &00 :\ RC /h$W 0:W 0:W 0:W 0 :\ Alloc Vector r$W 0:W 0:W 0:W 0 +|$\ F254 :B &00 :\ CR ,$\ F255 :W &0000:B &00 :\ R0-R2 $OPT endif $: $.end% $OPT if(P%&800:"WARNING: Code too long by: ";11;A%-&800 N%: ?X%A$="**SAVE "+fn$+" "+~mcode%+"+800 "+~entry%+" "+~start% b%A$;: A$: l% v%*Quit