;MasterDOS diassembled on 2000-11-15 by Jarek Adamski ;do not modify this file - write comments separate with proper label ;Labels: L-global, w-local (once used), n-unknown calls, x-dummy ; o-org, e-end area, m-system B, d-data, t-table, f-functions ;A1.Z80 ;61C9, 762A - no jump to up EQU #4000 ;shift dchan EQU #3C00+up L3FDF EQU #3FDF ;selurpg L3FEB EQU #3FEB ;incurpgde L3FEF EQU #3FEF ;chkhlr L3FF2 EQU #3FF2 ;incurpage LA280 EQU #A280 ;ftadd L3F8C EQU #3F8C ;unstlen L400F EQU #400F ;SAM L40D0 EQU #40D0 ;pthrd, #40D2 in 4.3 o4BA0 EQU #4BA0 o5896 EQU #5896 L7C00 EQU #7C00 ;DCHAN L7C02 EQU #7C02 ;SVDE, RFDH L7C05 EQU #7C05 ;SVHL L7C07 EQU #7C07 ;SVIX L7C09 EQU #7C09 ;REG1 L7C0B EQU #7C0B ;DRIVE L7C0C EQU #7C0C ;FLAG3 L7C0D EQU #7C0D ;RPT L7C0F EQU #7C0F ;BUF ;L7C11 EQU #7C11 ;NSR, no L7C13 EQU #7C13 ;FSA d7D13 EQU #7D13 ;DRAM L7F13 EQU #7F13 ;PTH1 L7F39 EQU #7F39 ;PTH2, to about #7F60 L7F90 EQU #7F90 ;register store and stack ;uses #7F68-#7F91 (COPY) or stack use+22 regs (SNAP) L7FF0 EQU #7FF0 ;SYSP, syntax stack L7FFA EQU #7FFA ;??? stack L7FFC EQU #7FFC ;??? stack L7FFF EQU #7FFF ;??? DEFK MACRO @x,@y DEFB @x DEFW @y ENDM ;B1.Z80 ORG #4000 DEFB #03 ;CODE header DEFW end-start,#8009,#FFFF,#FFFF ;boot code start LD HL,#81FF LD E,(HL) DEC HL LD D,(HL) ;t/s of rest of file w800F XOR A LD (start+up),A LD (start+up+1),HL ;use as variable LD A,E OUT (#E2),A L8019 IN A,(#E0) BIT 0,A JR NZ,L8019 IN A,(#E1) CP D JR Z,w8032 LD A,#7B ;step out JR NC,w802A LD A,#5B ;step in w802A OUT (#E0),A LD B,#14 w802E DJNZ w802E JR L8019 w8032 DI LD A,#80 ;read sector OUT (#E0),A LD B,#14 w8039 DJNZ w8039 LD HL,(start+1+up) LD BC,#00E3 JR L8045 w8043 INI L8045 IN A,(#E0) BIT 1,A JR NZ,w8043 RRCA JR C,L8045 AND #0D JR Z,w806D LD A,(start+up) ;check disc err count INC A LD (start+up),A PUSH AF AND #02 JR Z,w8066 LD A,#09 ;track 0 OUT (#E0),A LD B,#14 w8064 DJNZ w8064 w8066 POP AF CP #0A JR C,L8019 RST #08 ;error DEFB #13 w806D DEC HL LD E,(HL) DEC HL LD D,(HL) LD A,D OR E JR NZ,w800F LD HL,L410A+up ;clear sys vars for consistent results LD B,L41E4-L410A w407A LD (HL),A INC HL DJNZ w407A LD A,(#5CB4) ;last page variable LD (L412F+up),A DEC A LD (L4108+up),A IN A,(#FB) AND #1F LD (#5BC2),A ;DOSFLG variable = dos page LD H,#51 LD L,A LD (HL),#60 ;page allocation table marked "disk use" LD HL,#0100+"D" LD (#5A06),HL ;SLDEV+SLNUM = "D1" XOR A LD (dvar+20+up),A ;no opened files LD (#5BC3),A ;"dos not in control" variable LD BC,#00F3 w80A4 OUT (C),B LD A,#14 w80A8 DEC A JR NZ,w80A8 ;wait 50 usec IN A,(C) CP B LD A,#00 ;"no second drive" JR NZ,w80BC ;JR if no second disc chip DJNZ w80A4 LD A,(dvar+2+up) AND A JR NZ,w80BF LD A,128+80 w80BC LD (dvar+2+up),A w80BF POP HL ;return to ROM1 if "BOOT", next stat if "BOOT 1" POP DE ;next stat if "BOOT", err handler if "BOOT 1" POP BC ;err hand if BOOT PUSH BC PUSH DE PUSH HL BIT 7,H JR Z,w80CC ;JR if HL=next stat (BOOT 1) EX DE,HL LD D,B LD E,C w80CC LD (#821E),HL ;keep a record to use in some syntax handling LD (#5A69),DE ;unknown variable CALL w7C68+up LD HL,w7D06+up ;copy code to sys page at #4BA0 LD DE,o4BA0 LD BC,e4BA0-o4BA0 LDIR LD HL,m4BB0 LD (#5ADE),HL ;PRintTOKenVector LD HL,m58B4 LD (#5AFA),HL ;MmoveTOKeywordVector LD HL,m4BBA LD (#5AF6),HL ;EVALueVector LD HL,m4BC4 LD (#5AF4),HL ;CoMmanDVector JP w7BFB+up DEFS #4100-$ ;4 bajty L4100 DEFM "BO" L4102 DEFB "O","T"+128 L4104 DEFW 0 L4106 DEFW #021F L4108 DEFW 0 ;snprt2 L410A DEFW 0 ;svhdr L410C DEFW 0 ;cchad L410E DEFW 0 ;cnt L4110 DEFB 0 ;dsc L4111 DEFB 0 ;dct L4112 DEFS 11 ;dst L411D DEFB 0 ;sva L411E DEFB 0 ;svc L411F DEFS 3 ;nrflg L4122 DEFW 0 ;svdpt L4124 DEFW 0,0 ;svtrs L4128 DEFW 0,0 ;svcnt L412C DEFW 0 ;ptrscr L412E DEFB 0 ;port1 L412F DEFB 0 ;port2 L4130 DEFB 0 ;port3 L4131 DEFB 0 ;svcst L4132 DEFB 0,0,0 ;tstr1 L4135 DEFB 0 ;hstr1 L4136 DEFB 0 ;dstr1 L4137 DEFB 0 ;fstr1 L4138 DEFB 0 ;sstr1 L4139 DEFB 0 ;lstr1 L413A DEFS 15 ;nstr1 L4149 DEFB 0 ;hd001 L414A DEFW 0 ;hd0b1 L414C DEFW 0,0 ;hd0d1 L4150 DEFB 0 ;pges1 L4151 DEFB 0 ;page1 L4152 DEFS 4 ;dstr2 ;L4153 DEFB 0 ;fstr2 ;L4154 DEFB 0 ;sstr2 ;L4155 DEFB 0 ;lstr2 L4156 DEFB 0 ;nstr2 L4157 DEFS 14 L4165 DEFB 0 ;hd002 L4166 DEFW 0 L4168 DEFB 0 ;hd0b2 L4169 DEFW 0 ;hd0d2 DEFB 0 L416C DEFB 0 ;pges2 OK L416D DEFB 0 ;??? L416E DEFB 0 ;nstr3 L416F DEFS 14 ;page2 L417D DEFS 48 ;uifa L41AD DEFS 48 ;difa L41DD DEFB 0 ;hka L41DE DEFW 0 ;hkhl L41E0 DEFW 0 ;hkde L41E2 DEFW 0 ;hkbc L41E4 DEFB #13 DEFM 'SNAP ' ;10 spaces DEFB #13 L41F4 DEFW #C000 L41F6 DEFW #4000,0,#FFFF L41FC DEFW 0 ;sect/trk of free dir slot, or 00?? if none L41FE DEFW 0 ;0 or 1 for dir entry in sector L4200 JP w4386 JP w42F5 JP L5214 L4209 DEFB 0 ;tempb1 L420A DEFB 0 ;dtksx L420B DEFW 0 ;hksp L420D DEFB 0 ;rdat L420E DEFW #0000 ;samdr DEFW d50DF+up L4212 DEFW 0 ;tempw1 L4214 DEFW 0 ;tempw2 L4216 DEFW 0 ;tempw3 L4218 DEFW 0 ;tempw4 L421A DEFW 0 ;tcnt ;dir's 'total files on disc' counter L421C DEFW 0 ;fcnt ;dir's 'files in cur. directory' counter L421E DEFW 0 ;nextst dvar EQU $ ;#4220 DEFB #00 ;0 flashing while loading, 0-no DEFB 80+128 ;1 tracks & sides (+128) D1: DEFB 0 ;2 tracks & sides (+128) D2: DEFB 0 ;3 step D1: 0-fastest DEFB 0 ;4 step D1: 0-fastest DEFB #20 ;5 "space" in DIR display DEFB #01 ;6 reserved DEFB 42 ;7 system version DEFB 0 ;8 columns in DIR 0-full DEFB 1 ;9 autosort 0-off DEFB #0D ;10 POINT OVER character DEFB "." ;11 extention separator DEFM '\/' ;12 directory symbols DEFB #FF ;14 track to track skip factor DEFB #01 ;15 internal drive number DEFB #04 ;16 directory tracks on recently used disk DEFB #00 ;17 current subdirectory DEFB #00 ;18 another subdirectory DEFB #00 ;19 DIR DATE flag 0-off DEFB #00 ;20 opened files DEFB #00 ;21 last subdirectory DEFW d43F3 ;22 hook code table DEFB #00 ;24 MOVE TO #2 flag 0-convert, 1-all DEFB "." ;25 MOVE TO #2 undisplayable characters repleacer DEFB #04 ;-26 page of Spectrum emulator DEFW #0004 ;-27 call of Spectrum emulator DEFB #00 ;-29 time before SAVE CALL L7BB4 ;30 jump to reserved DEFW #0000 ;33 ON ERROR jump RET ;35 reserved DEFB #00 ;36 ON ERROR page DEFW #0200 ;37 READ AT sector increment DEFB #00,#00,#00,#00,#00 ;39 ramdisks' in tracks DEFB #00,#00,#00,#00,#00 ;44 ramdisks' first page DEFB 0,0,0,0,0,0,0 ;49 disks' current subdirectory DEFB 2,2,2,2,2,2,2 ;56 disks' path length DEFW 0,0,0,0,0,0,0 ;63 disks' random DEFW 0 ;77 open file random DEFW #0000 ;79 clock variable DEFM '00/00/00' ;81 date DEFB #0D DEFW #011F,#010C,#0063 ;90 date range DEFM '00:00:00' ;96 time DEFB #0D DEFW #0017,#003B,#003B ;105 time range DEFB 1,2,3,4,5,6,7 ;111 drive remaping DEFW 0,0,0,0,0,0,0,0 ;118 external memory DEFW 0,0,0,0,0,0,0,0 DEFB #EF ;150 clock port DEFW #0085 ;151 beep time DEFW #0000 ;153 xptr store DEFB (e42BC-d42BC)/3 d42BC DEFK #86,k644A ;WRITE DEFK #90,k59E3 ;DIR DEFK #91,k5F16 ;FORMAT DEFK #92,k5BFD ;ERASE DEFK #93,k6590 ;MOVE DEFK #95,k5E4B ;LOAD DEFK #98,k6893 ;OPEN DEFK #99,k6AC8 ;CLOSE DEFK #B3,k6AE2 ;CLEAR DEFK #B8,k644F ;READ DEFK #CF,k58BE ;COPY DEFK #E3,k5C7B ;RENAME DEFK #E4,k5863 ;CALL DEFK #F1,k5D13 ;PROTECT DEFK #F2,k5D16 ;HIDE DEFK #F7,k67AE ;BACKUP DEFK #F8,k6F45 ;TIME DEFK #F9,k6F41 ;DATE DEFK #00,k434A ;not found e42BC w42F5 DI CP #35 ;no dos JR Z,L42FE CP #1D ;not understood JR NZ,w4308 L42FE LD (L4131),A ;error number LD HL,L411F ;no recurse flag INC (HL) DEC (HL) LD (HL),#01 ;"no recurse now" w4308 JP NZ,L437F ;JP if e.g. dos called EXPT1NUM and got VAL"#!" ;giving nonsense error - do not recursively call DOS! CALL L43C0 ;setstk LD BC,L4ED4 ;address PUSH BC CALL L43DA CALL L43E4 ;zero FLAG3 and HKSP CALL L4CCF CALL L4F17 ;get CHADD and save it DEFW #5A97 LD (L410C),BC CALL L4F17 ;get start of statement DEFW #5A7B CALL L4F2D DEFW #5A97 CALL L4F06 CP ":" ;skip any colon CALL Z,L4F00 ;CSTAT points to ":" if e.g. "ON X: DIR: PRINT..." EX DE,HL LD HL,d42BC-1 LD B,(HL) ;no. of cmds DEC HL w433C INC HL INC HL CP (HL) INC HL JR Z,w4344 DJNZ w433C ;if not found, end on "CNF" routine w4344 LD C,(HL) INC HL LD B,(HL) EX DE,HL ;HL=CHAD PUSH BC RET k434A INC A ;no match in table JR NZ,w4355 ;point is #FF #3D CALL L4F00 CP #3D JP Z,w6DAC w4355 POP BC ;check external syntax vector EX (SP),HL ;CHAD to stack, get ENTSP LD (L4104),HL ;orig LD BC,(L410C) CALL L4F2D DEFW #5A97 POP BC ;CHAD ptr to cmd or after #FF LD HL,(dvar+33) ;onerr LD A,H OR L LD A,(L4131) JR Z,L437F BIT 7,H JP Z,dvar+30 IN A,(#FB) LD D,A ;orig LD A,(dvar+36) OUT (#FB),A LD A,(L4131) JP (HL) L437F LD E,#00 ;no action LD HL,L411F ;recurse OK LD (HL),E ;A=error no. RET w4386 DI ;SAMDOS hook code routine ADD A,A ;junk bit 7, make word offset LD (L4131),A ;hook code offset EX AF,AF' LD (L41DD),A CALL L43C0 LD (L410A),IX EXX LD (L41DE),HL LD (L41E0),DE LD (L41E2),BC EXX CALL L43DA CALL L4F38 ;A=0 DEFW #5AA3+1 ;no error in case PRINT LD HL,(L4131) ;H=JUNK LD A,(L41DD) LD DE,d43F3 CALL w7804 ;indexed JP using L CALL L501C ;return from hook code OK EXX ;pass HL,DE,BC out via alt regs XOR A ;"no error" LD E,A ;"no action" JP w4EE9 ;restore orig ENTSP L43C0 POP IY ;ret addr CALL L4F17 DEFW #5C59 ;DOSSTK, READ - set to #7FF0 by BASIC at each cmd LD H,B LD L,C POP AF ;get all 3 values from stack at #8000 POP DE POP BC LD SP,HL ;new stack so that DOS ->CALL ROM->HOOKS can avoid PUSH BC ;overwriting main DOS stack PUSH DE PUSH AF LD HL,(L4104) PUSH HL ;old value restored on exit LD (L4104),SP JP (IY) L43DA XOR A ;zero FLAG3, HKSP LD (L7C0C),A LD H,A LD L,A LD (L420B),HL RET L43E4 LD HL,L4132 ;reset all registers LD B,L417D-L4132 LD A,#FF w43EB LD (HL),A INC HL DJNZ w43EB LD (L420D),A RET ;hook code table d43F3 DEFW t6415,t6275,t460B,t62FD DEFW t632A,t4617,t6851,t6B03 DEFW t63EC,t4632,t64CA,t636F DEFW t6398,t6395,t7A87,t4609 DEFW t62FB,t70DC,t4C08,t641B DEFW t6CB5,t645D,t4829,t6AA2 DEFW t4D03,t5B76,t64CA,t64CA DEFW t64CA,t64CA,t6428,t6D34 DEFW t6454,t4756,t6457,t6460 DEFW t4692,t5A56,t6439,t6C68 DEFW t6C26,t76CD,t771B,t7785 DEFW t77CE,t7A9B,t7B4D L4451 PUSH AF ;C11 LD A,(L4110) LD C,A POP AF RET L4458 CALL L4451 INC C RET L445D PUSH BC CALL L4451 IN A,(C) POP BC RET ;C11.Z80 L4465 LD A,D ;return Z if PGES1/DE is zero OR E RET NZ LD A,(L4150) AND A RET Z DEC A LD (L4150),A LD DE,#4000 JR L4465 L4476 LD C,#A2 ;precompensation calculator w4478 CALL L49DB ;get tracks on disc RRA AND #3F ;** mask top bit (sidedness), halve trk/side LD B,A ;usually 40d LD A,D ;e.g. track 0-40=CY, so JR leaving bit 1 set AND #7F ;(precomp=disabled) SUB B ;e.g. track 70-40=NC, no JR, RES 1=enable JR C,L4487 ;JR if current trk in D is an inner track RES 1,C ;else turn *on* precmp L4487 CALL L449E ;send a disc command w448A LD A,C CALL L4451 OUT (C),A LD B,#14 w4492 DJNZ w4492 RET L4495 CALL L5FDB ;/read address cmd code RET NC ;/spin up disc in case it is off LD C,#C0 ;(or step in/out will start drive, then wsad will CALL L4487 ;write too soon 'cos "drive running") ;wait till finished cmd (alters sect reg) L449E CALL L445D ;test for chip busy BIT 0,A RET Z CALL w4EEE JR L449E L44A9 CALL L4E97 ;write sector if altered w44AC BIT 3,(IX+#0C) ;\get DE=cur sector RET Z ;RET if sector has not been written to w44B1 CALL L4495 ;write sector at DE L44B4 CALL L5FD7 JP NC,w734E DI w44BB CALL L4629 CALL L4476 ;write sector cmd LD A,(L4110) LD (L44DD+1),A ;self-mod status port ADD A,#03 LD C,A ;data port CALL L4E78 CALL L44DD RLCA BIT 6,A JP NZ,L5041 ;error if write-protected CALL L45AC JR w44BB w44DB OUTI L44DD IN A,(#00) RRCA RET NC ;RET if done RRCA JR C,w44DB ;JR if disk ready for byte JR L44DD L44E6 LD DE,(L7C02) ;read sector at DE L44EA CALL L5FD7 JP NC,L73BD w44F0 CALL L4E6F CALL L44FC RLCA CALL L45AC JR w44F0 L44FC LD A,(L4110) ;status port LD (L450D+1),A ADD A,#03 LD (L4509+1),A JR L450D L4509 IN A,(#00) LD (HL),A INC HL L450D IN A,(#00) RRCA RET NC ;RET if read sector cmd finished RRA JR NC,L450D ;JR if no byte is ready to read JR L4509 L4516 BIT 5,(IX+#04) ;optional RSAD or NRSAD (if SAM wanted) JR Z,L44EA CALL L5FD7 ;read sector at DE JP NC,w73A0 w4522 CALL L4E6F EXX LD L,#FF LD D,#40 ;NSAM/256 EXX PUSH DE CALL w4536 POP DE RLCA CALL L45AC JR w4522 w4536 LD A,(L4110) ;status port LD (w454E+1),A LD (L455E+1),A ADD A,#03 LD (L4553+1),A LD B,#02 ;mask for bit 1 JR L455E w4548 LD H,D ;NSAM msb AND A ;Z if DIR entry is erased or unused JR NZ,w454D LD H,A ;dump data to ROM w454D EXX w454E IN A,(#00) AND B JR Z,L455E ;JR if no byte is ready to read L4553 IN A,(#00) LD (HL),A INC HL EXX INC L JR Z,w4548 ;JR if start of DIR entry OR (HL) LD (HL),A EXX L455E IN A,(#00) RRCA RET NC ;RET if read sector cmd finished RRA JR NC,L455E ;JR if no byte is ready to read JR L4553 ;search version of RSAD ;entry: DE=t/s, (TEMPW1)=delim count, (DELIM)=delim ;exit: TEMPW3 holds new delim count, TEMPW2=LOCN w4567 CALL L5FD7 JP NC,w7377 w456D CALL L4E6F LD A,(L4110) ;status port LD (L4599+1),A ADD A,#03 LD (L4592+1),A PUSH DE LD DE,(L4212) ;delim count LD A,(dvar+10) LD B,A CALL L4599 LD (L4216),DE ;new count POP DE RLCA CALL L45AC JR w456D L4592 IN A,(#00) LD (HL),A INC HL CP B JR Z,w45A2 L4599 IN A,(#00) RRCA RET NC ;RET if read sector cmd finished RRA JR NC,L4599 ;JR if no byte is ready to read JR L4592 w45A2 DEC DE LD A,D OR E JR NZ,L4599 LD (L4214),HL JR L4599 L45AC AND #1C ;check disc err count JR NZ,L45B7 ;JR if an error was detected CALL L4CD9 POP HL ;junk ret addr JP L4E78 L45B7 PUSH AF LD A,(L4111) INC A LD (L4111),A CP #0A JP NC,L5026 POP AF BIT 4,A JR NZ,L45D5 ;JR if record not found CALL L4670 CALL L466C CALL L466C JP L4670 L45D5 LD C,#C0 ;confirm track/sector location CALL L4487 LD HL,L4112 CALL L44FC AND #1C JR NZ,w45ED ;JR if error CALL L4458 LD A,(L4112) OUT (C),A RET w45ED LD A,(L4111) INC A LD (L4111),A CP #08 JP NC,w5029 AND #02 JR Z,w4604 PUSH DE CALL t4692 POP DE JR L45D5 w4604 CALL L4670 JR L45D5 t4609 OUT (#FB),A ;AHL=start, CDE=len t460B LD BC,m4BE2 ;load file already opened by HGTHD. HL=start, CDE=len, paged in. CALL L62EF CALL L62D1 CALL L475A ;seek last track in directory, or track 3 if last track is 4 (avoid 1st file!) ;used to leave head somewhere more safe in case of reset t4617 CALL L5FDB RET NC LD A,(dvar+16) DEC A LD D,A LD E,#01 ;prob not needed!!! CP #04 JR NZ,L4633 DEC D JR L4633 L4629 LD A,D ;confirm track and seek OR E ; JR NZ,CTA1 ;remarked in original code ; CALL bitf2 JP Z,L504A ; LD SP,(ENTSP) ; XOR A ; LD E,A ; RET CALL w5010 ;BORDER colour change EXX t4632 EXX L4633 CALL L4718 ;seek track D. used by FORMAT, SKSAFE INC A INC A LD C,A ;sector port OUT (C),E w463B LD A,D AND #7F LD B,A CALL L449E CALL L4458 IN A,(C) CP B RET Z PUSH AF ;check if page over #C000 every time track alters CALL L5004 JR Z,L4663 ;JR if not load/save block LD A,(L7C05+1) CP #C0 JR C,L4663 RES 6,A LD (L7C05+1),A IN A,(#FB) INC A LD (L412E),A OUT (#FB),A L4663 POP AF CALL NC,L466C ;outstp CALL C,L4670 ;instp JR w463B L466C LD C,#7B JR w4672 L4670 LD C,#5B w4672 CALL L4487 PUSH HL ;STEP delay routine LD HL,dvar+3 LD A,(L4110) BIT 4,A JR Z,w4681 INC HL w4681 LD A,(HL) POP HL AND A w4684 RET Z w4685 PUSH AF LD BC,150 w4689 DEC BC LD A,B OR C JR NZ,w4689 POP AF DEC A JR w4684 t4692 LD DE,#0001 ;restore disc drive CALL L5FDB RET NC CALL L46AC ;test for index hole JP Z,w502C ;"check disc in drive" if no hole w469F CALL L445D ;test for track 00 BIT 2,A JP NZ,L449E CALL L466C ;step out one track JR w469F L46AC CALL L4718 ;test for index hole LD C,#D0 ;exit: NZ=OK, Z=timed out, no hole CALL w448A ;reset disc chip LD B,#00 w46B6 DJNZ w46B6 LD H,#80 ;loops before time-out w46BA CALL L445D BIT 1,A JR Z,L46C7 DEC HL LD A,H OR L JR NZ,w46BA RET L46C7 CALL L445D BIT 1,A RET NZ DEC HL LD A,H OR L JR NZ,L46C7 RET L46D3 CALL L5FDB ;FORMAT...TO... SR JP C,L60C4 L46D9 CALL L5097 DEFB 91 ;invalid device if ram disc L46DD LD A,(L41DD) ;drive CALL L6020 ;convert JR L46EF L46E5 LD A,(L4139) ;check valid specifier disc CP "D" JR NZ,L46D9 ;"invalid device" L46EC LD A,(L4136) ;check drive number L46EF CP #01 JR Z,L470A CP #02 JR Z,w4700 DEC A CP 8-1 ;rdlim-1=#07 JP NC,L503E INC A ;allows 3 to rdlim-1 JR L470A w4700 LD A,(dvar+2) CP #00 JP Z,L503E ;"no such drive" LD A,#02 L470A LD (L7C0B),A RET L470E LD A,(L7C0B) ;serial set drive, return current one in C LD C,A LD A,(IX+#0B) L4715 LD (L7C0B),A ;select disc and side - get port base addr (224/228/240/244 for disc 1 side 1/2, ;disc 2 side 1/2) in A and DSC var (L4110) L4718 CALL L5FDB ;test if ram disk RET NC ;RET if it is CP #02 LD B,#E0 JR NZ,w4724 LD B,#F0 w4724 LD A,D AND #80 JR Z,w472B LD A,#04 w472B OR B LD (L4110),A RET L4730 PUSH HL LD H,#00 LD L,D ;HL=trk LD B,H LD C,L ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,BC ;*5 ADD HL,HL ;*10 LD C,E DEC C ;0-9 LD A,D CP #04 ;NC if on track 4 or more ADC HL,BC ;HL=sector (1 or more, sub 1 if t4 or more) ADD HL,HL ;file number div 2+1 DEC HL ;file number DIV 2 LD C,(IX+#0E) ;dir entry 0/1 ADD HL,BC ;file number LD B,H LD C,L LD A,C POP HL RET L474C CALL L4E89 ;test for buffer full LD A,C CP #FE RET NZ LD A,B DEC A RET t4756 LD (L4150),A ;load data block from disk to HL EXX L475A CALL L4FD4 ;PGES1/DE=count JR w4769 w475F LD A,(HL) CALL L6CF9 LD HL,(L7C05) LD (HL),A INC HL DEC DE w4769 LD (L7C05),HL CALL L4465 RET Z w4770 CALL L474C JR NZ,w475F LD (L7C02),DE LD D,(HL) INC HL LD E,(HL) DI L477D CALL L47F2 JP C,w47E8 INC HL LD (L7C02),HL CALL L5FDB JR C,w4791 CALL w75D6 ;ram disc JR L477D ;DE=t/s, SVHL=OK w4791 XOR A LD (L4111),A CALL L6EF7 w4798 CALL L4629 LD C,#80 CALL L4487 EXX LD DE,#0002 CALL L4E78 LD A,(L4110) LD (#47C4+1),A ;status port ADD A,#03 LD (#47BB+1),A ;data port EXX LD DE,#01FE ;510 LD HL,(L7C05) JR L47C4 w47BB IN A,(#00) LD (HL),A INC HL DEC DE LD A,D OR E JR Z,w47D9 L47C4 IN A,(#00) BIT 1,A JR NZ,w47BB RRCA JR C,L47C4 AND #0D JR Z,w47DC CALL L4E97 CALL L45B7 JR w4798 w47D9 EXX JR L47C4 w47DC LD (L7C05),HL CALL L4E78 LD D,(HL) INC HL LD E,(HL) JP L477D w47E8 EQU $ ; CALL LDINT ;remarked in original CALL L44EA LD DE,(L7C02) JP w4770 ;calculate count L47F2 LD HL,(L7C02) ;bytes left in this 16kB block LD BC,#01FE SCF SBC HL,BC RET NC ;RET if 511 or more left LD A,(L4150) AND A SCF ;signal "last sector now" RET Z ;RET if it's true DEC A LD (L4150),A ;DEC pages to do LD HL,(L7C02) LD BC,#4000 ADD HL,BC LD (L7C02),HL ;adjust remainder JR L47F2 L4812 IN A,(#FB) ;get screen memory and pointer LD (L412E),A LD A,(L412F) OUT (#FB),A LD HL,(L412C) RET L4820 LD (L412C),HL ;put screen memory and pointer LD A,(L412E) OUT (#FB),A RET t4829 LD (L4150),A ;real hook EXX ;save data block on disc. leave last sector in buffer, padded with ;spaces, but with RPT pting past last real datum ;save PGES1/DE bytes from HL w482D CALL L635D ;delay 0.25 sec in case OFSM too fast w4830 CALL L4856 RET C ;RET if single sector in buffer, padded CALL L6EF7 ;save DE to next t/s variables LD DE,(L7C02) ;bytes left to do LD HL,(L7C05) JR w4830 ;delay, save block L4840 CALL L635D ;delay about 0.25 sec if not ramdisc ;save data block on disc ;save PGES1/DE bytes from HL, padding last sector with spaces CALL L4856 JP C,L44B4 ;write single sector JP w48D3 ;or last sector of block (HL=0) w484C LD (HL),D CALL L6CF9 ;INC IX+RPTL/H LD HL,(L7C05) INC HL POP DE DEC DE ;DEC bytes-to-save L4856 CALL L4FD4 ;test for zero block count CALL L4465 JP Z,w494B ;JP if all bytes now in buffer - pad buffer and save it PUSH DE ;save char in register D LD D,(HL) LD (L7C05),HL ;\ CALL L474C JR NZ,w484C POP DE LD (L7C02),DE ; | removed in 4.3 CALL L496A LD (HL),D INC HL LD (HL),E EX DE,HL CALL L6CAB CALL L5FDB JP NC,w746E ;/ PUSH DE CALL L4812 ;screen paged in LD HL,LA280 ; LD (HL),D ;remarked in original LD BC,#0000 ;sect count=0 JR w48A3 w488A PUSH HL ;scrn ptr CALL L47F2 ;check bytes remaining, sub 511 EX DE,HL POP HL ;scrn ptr JR C,w48A9 ;JR if 510 or less bytes to go - start saving sectors INC DE ;correct for sub 511 ->sub 510 now LD (L7C02),DE ; LD D,(HL) ;remarked in original CALL L495F ;find next free sect in sam LD (HL),D INC HL LD (HL),E ;store in screen table INC HL ; LD (HL),D ;remarked in original LD BC,(L4128) INC BC ;inc sector count w48A3 LD (L4128),BC JR w488A w48A9 XOR A LD (HL),A LD D,H LD E,L INC DE LD BC,#01FF ;allow up to 512 bytes of zeros for last sector LDIR LD HL,LA280 CALL L4820 ;set ptr var to start of list of t/s, switch screen off POP DE CALL L44B4 ;write first sector, setup DSC DI XOR A LD (L4111),A ;zero errors CALL L4E97 ;get T/S in D/E EXX LD HL,(L412C) ;source of last 2 bytes (or more, if last sect) EXX L48CA LD HL,(L4128) ;loop here for each sector in SVCNT LD A,H OR L RET Z ;RET if last to do next. NC BIT 7,H RET NZ ;RET if negative (final sector just done) w48D3 DEC HL LD (L4128),HL PUSH DE ;T/S CALL L4629 ;confirm track CALL L4476 ;send "write sector" cmd LD A,(L412F) ;screen port EX AF,AF' ;stored in A' for speed LD A,(L4110) ;status port LD (L490F+1),A ;self-mod code ADD A,#03 LD C,A ;data port EXX LD C,A ;C'=data port too LD DE,#0300 ;DE is a large number so exx happens just once EXX LD DE,#02FE ;510 byte counter LD HL,(L4128) INC HL LD A,H OR L JR NZ,L4905 ;JR if not last sect LD DE,(L7C02) ;remaining bytes LD A,E AND A JR Z,L4905 ;no INC if E=0 so counter OK INC D L4905 LD HL,(L7C05) ;src JR L490F w490A OUTI DEC E ;LSB of byte count JR Z,w4942 L490F IN A,(#00) ;self-mod status port BIT 1,A JR NZ,w490A ;JR if disk ready for byte RRCA JR C,L490F ;JR if busy - data still to be sent EXX ;HL=main ptr POP DE ;T/S AND #0D JR NZ,w4933 ;JR if error ;screen is still in LD (L7C05),HL ;update src ptr (in 510 byte steps) EXX DEC HL LD E,(HL) DEC HL LD D,(HL) ;D/E=bytes just saved (next t/s) INC HL INC HL LD A,(L412E) OUT (#FB),A ;non-screen PUSH DE EXX POP DE ;T/S JP L48CA ;loop for all sectors w4933 LD A,(L412E) ;entered when an error occurred during save OUT (#FB),A ;non-screen CALL L45B7 ;check/set t/s EXX DEC HL DEC HL EXX JP L48CA ;try again - max 10 errors in entire block ;entered when E counts to 0 w4942 DEC D ;dec MSB of count (pre-inced) JR NZ,L490F EXX ;switch to HL' - pts to t/s or zeros EX AF,AF' OUT (#FB),A ;screen on JR L490F w494B CALL L4E89 ;pad a single sector for a small block L494E LD A,B SUB #02 OR C JR Z,w495A LD (HL),#00 ;pad with zeros INC HL ;no change of rpt INC BC JR L494E w495A CALL L4E97 ;get t/s SCF ;"single sector" RET ;C12.Z80 L495F LD DE,(L4102) ;fast find next sct if FNFS used before PUSH HL PUSH BC LD HL,(L4100) JR w4973 ;find next free sector L496A LD DE,#0401 ;trk 4,sct 1 PUSH HL PUSH BC LD HL,L400F-1 ;SAM-1 L4972 INC HL w4973 LD A,(HL) INC A JR NZ,w4986 ;JR if not #FF (=all used) LD A,E ADD A,#08 LD E,A SUB #0B INC A ;equiv. of sub 10, but CY if zero or less JR C,L4972 ;JR if sector was OK before sub 10 LD E,A CALL L499D ;next track JR L4972 w4986 LD B,#01 ;mask for bit 0 LD (L4102),DE LD (L4100),HL w498F LD A,(HL) AND B JR Z,w49C2 ;JR if fnd free CALL L5521 CALL Z,L499D ;next trk if needed RLC B JR w498F ;called by point sr "FITS" L499D INC D CALL L49DB ;get trk limit LD C,A LD A,(dvar+16) SUB #04 JR NC,w49AD ;JR if normal disc NEG ADD A,C ;fiddle limit to allow e.g. trk 42 on 40 trk, 1 dtk LD C,A ;ram disc so tks 4-42 OK. w49AD LD A,C ;limit CP D ;CP limit, trk JP Z,w5044 ;not enough space CALL L5FDB JR C,w49BA ;JR if not ram disc LD A,#50 ;side 1 on ram disc=80 trk DEFB #FE ;dummy CP #79 ("JR+1") w49BA LD A,C AND #7F CP D RET NZ LD D,#80 RET w49C2 LD A,(HL) ;found free sect OR B LD (HL),A ;set bit in SAM LD C,L ;L=disp from start of SAM,+#0F LD A,B LD B,#00 PUSH IX ADD IX,BC OR (IX+#13) ;IX+fsam-#0F LD (IX+#13),A ;IX+fsam-#0F POP IX CALL L6EFE ;inc sects used count POP BC POP HL RET L49DB PUSH HL ;test tracks on disc LD HL,dvar+1 CALL L5FDB JR C,w49E9 CALL L72CA ;ramdisc POP HL RET w49E9 DEC A JR Z,w49ED INC HL w49ED LD A,(HL) POP HL RET L49F0 LD B,#01 ;print file name CALL L4E86 L49F5 PUSH HL ;print file name from HL. uses HL,A,B LD BC,#0A0A ;advances HL by 10 w49F9 LD A,(dvar+11) ;file name separator - usually "." CP (HL) LD A,(HL) JR NZ,w4A08 LD A,B CP #05 JR NC,w4A0D ;print pad space if "." and chars still to print >=5 LD A,(dvar+11) w4A08 INC HL CP #20 JR NZ,w4A10 w4A0D LD A,(dvar+5) w4A10 CALL L567D DJNZ w49F9 POP HL ADD HL,BC ;BC=10 RET L4A18 DI ;file dir hand/rout. PUSH AF CALL L4CCF POP AF LD (L7C00+4),A XOR A LD (L41FC),A ;no free slot LD (dvar+21),A ;max tag=0 CALL t4692 CALL L4516 CALL L72F0 ;set dir tks, check rand no, get HL=point PUSH HL BIT 2,(IX+#04) CALL NZ,L5AF7 ;print dir hdr now that PATH$ checked, if complex dir wanted LD A,(dvar+16) SUB #05 JR C,L4A69 ;JR if SAM OK (4 dir tracks or less) INC A LD B,A ;B=extra dtks (1-35) ADD A,A ADD A,A ADD A,B ;A=5-175 (extra dir sects/2) LD C,A RRA RRA ;extra dir sects/8=bytes AND #3F ;A=bytes to mark #FF in SAM (1-43) LD B,A LD HL,L400F LD A,(HL) OR #FE LD (HL),A ;t4,s1 not reserved - but keep current status! DEC B JR Z,w4A5A w4A55 INC HL LD (HL),#FF DJNZ w4A55 w4A5A LD A,C ADD A,A AND #07 ;extra bits (0,2,4 OR 6) JR Z,L4A69 LD B,A XOR A w4A62 SCF RLA DJNZ w4A62 INC HL OR (HL) LD (HL),A L4A69 POP HL JR w4A72 L4A6C CALL L4516 w4A6F CALL L4E84 w4A72 LD A,(HL) AND A JP Z,w4BA7 ;JP if free slot LD A,(L7C00+4) ;test for 'P' number RRA JR NC,w4A8E ;JR if not e.g. LOAD 3 CALL L4730 ;convert t/s to P number in BC LD A,(L4137) ;LSB CP C w4A84 JP NZ,L4B82 LD A,(L4218+1) ;MSB CP B JR NZ,w4A84 RET w4A8E AND #03 ;get track and sector count JP Z,w4B53 ;JP if neither type of directory LD A,(HL) ;type EX AF,AF' LD B,H LD C,L INC H DEC HL DEC HL LD A,(HL) ;directory tag - byte #FE LD HL,#000B ADD HL,BC LD B,(HL) INC HL LD C,(HL) LD (L7C00),BC ;sectors used by file LD HL,(L410E) ADD HL,BC LD (L410E),HL ;total used sectors so far on disc LD HL,(L421A) INC HL LD (L421A),HL ;total files so far on disc LD B,A LD A,(dvar+17) ;cur dir CP #FF JR Z,w4AC0 ;JR if "all" CP B JP NZ,L4B82 ;JP if not file from current dir w4AC0 LD HL,(L421C) INC HL LD (L421C),HL ;total files so far in this dir EX AF,AF' ;test if we should print name RLA ;bit 7 of file type=1 if "hidden" JR C,L4AF5 ;JR if hidden LD A,(L413A+2) ;#FF if no name asked for INC A JR Z,w4AD6 CALL L4BC8 JR NZ,L4AF5 ;JR if not a dir of this name type w4AD6 BIT 1,(IX+#04) JR Z,w4AF8 ;JR if complex dir, continue if simple PUSH DE ;copy file name from sect buffer to special buffer of names LD A,(dchan+#0E) ;get dir entry (0 or 1) LD B,A LD C,#01 LD HL,(dchan+#0F) ;get sect buffer addr in HL ADD HL,BC ;pt to file name in dir entry LD DE,(L412C) LD BC,#000A LDIR LD (L412C),DE POP DE L4AF5 JP L4B82 w4AF8 CALL L4E84 LD A,(HL) BIT 6,A JR Z,w4B0D ;JR if file not protected - print file number CALL L567B LD A,"*" ;else print " * " CALL L567D CALL L567B JR w4B28 ;JR to print file name ;print file number as 2 or 3 digits e.g. "12 " or "123" w4B0D CALL L4730 ;get file number in BC PUSH DE LD HL,#0063 AND A SBC HL,BC LD H,B LD L,C LD A,#20 JR C,w4B24 ;JR if >99 CALL L564C CALL L567B AND A ;NC w4B24 CALL C,L5646 POP DE w4B28 CALL L49F0 ;print file name for dir 1/2 PUSH DE ;print sector count as e.g. " 20 " CALL L4E9E JR Z,w4B4D ;JR if dir PUSH AF LD A,#20 LD BC,(L7C00) ;sectors used LD HL,999 AND A SBC HL,BC ;CY if >999 sects used LD H,B LD L,C JR C,w4B49 CALL L5646 CALL L567B AND A w4B49 CALL C,L5640 ;use 4 digits, butting onto type, if needed e.g. 1234OPENTYPE POP AF ;print type of file e.g. "BASIC ","C " w4B4D CALL w5529 POP DE JR L4B82 w4B53 LD A,(dchan+4) ;test for specific file name AND #18 JR Z,L4B82 ;JR if neither bit 3 nor 4 are set LD A,(HL) AND #1F CP #15 ;dir JR NZ,w4B72 LD BC,#00FA ADD HL,BC ;pt to dir tag LD A,(dvar+21) ;current max CP (HL) ;CP tag of this dir JR NC,w4B70 ;JR if no new max tag LD A,(HL) LD (dvar+21),A AND A w4B70 SBC HL,BC ;pt to dir tag for file w4B72 INC H DEC HL DEC HL LD A,(dvar+17) CP (HL) JR Z,w4B7E ;JR if right dir INC A JR NZ,L4B82 ;JR unless #FF "any" dir w4B7E CALL L4BC8 RET Z L4B82 LD A,(dchan+#0E) ;calculate next directory entry DEC A JR Z,w4B91 ;JR if we have just done second dir entry in sect CALL L4CD9 INC (IX+#0E) ;next entry JP w4A6F w4B91 CALL L5521 ;next sector JP NZ,L4A6C ;JP if not last sect in track INC D ;inc track LD A,D CP #04 JR NZ,w4B9E INC E ;sect=2 if track=4 (skip dos) w4B9E LD A,(dvar+16) CP D JP NZ,L4A6C AND A ;NZ RET w4BA7 CALL L4BB8 ;found free directory space - see if that is what is wanted LD A,(IX+#04) CPL BIT 6,A RET Z ;RET if got what we wanted INC HL LD A,(HL) AND A ;** JR NZ,L4B82 ;JR if dir entry has been used at some time (name start not CHR$ 0) INC A ;NZ RET ;used part of dir dealt with L4BB8 LD A,(L41FC) AND A RET NZ ;JR if we have already noted a "first free slot" LD (L41FC),DE LD A,(L7C0D+1) LD (L41FE),A ;record 0 or 1 for which entry in sector is free RET L4BC8 PUSH DE ;check file name in dir, exit: Z if matched CALL L4E84 LD B,#0B LD DE,L413A BIT 3,(IX+#04) JR Z,L4BE5 ;JR if type irrel - skip type w4BD7 LD A,(DE) CP "*" JR Z,w4BEC ;match any len if "*" CP "?" JR Z,L4BE5 ;match any char if "?" XOR (HL) x4BE2 AND #DF JR NZ,w4BEA L4BE5 INC DE INC HL w4BE7 DJNZ w4BD7 w4BE9 XOR A ;match=Z w4BEA POP DE RET w4BEC INC DE INC HL LD A,(DE) CP "." JR NZ,w4BE9 ;e.g. "*" or "A*" matches anything from "*" on, ;but e.g. "*.Z" looks for matching "." in file name w4BF3 LD A,(HL) CP "." JR Z,L4BE5 ;if matching "." found, check suffix vs requested INC HL DJNZ w4BF3 POP DE RET ;no match L4BFD XOR A ;clear SAM (sector allocation map) LD HL,L400F LD B,195 w4C03 LD (HL),A INC HL DJNZ w4C03 RET t4C08 CALL L4C2A ;rnd/serial open file sector address map - inc SAMCNT of long-term OPEN LD A,(dvar+20) ;files (CHANS BUFFERS) INC A LD (dvar+20),A DEC A JR NZ,w4C25 ;JR if not first file CALL L72D7 ;get cur. rand word addr in HL LD C,(HL) INC HL LD B,(HL) LD (dvar+77),BC ;rnd no. of disc used for SAM LD A,(L7C0B) LD (L420E),A w4C25 XOR A ;NC - OK RET L4C27 CALL L4CCF L4C2A PUSH IX ;OPEN FILE sector address map LD A,(dvar+20) AND A CALL Z,L4BFD ;no clear if open-type file(s) has SAM in use LD A,#30 ;bit 5=create SAM, bit 4=test for name ;(better than G+DOS because even if disc changed ;sectors used in either disc are set bits in SAM. ;G+DOS used LD A,10H - no oring of bits) CALL L4A18 JR NZ,w4C90 ;JR if name not found w4C3A PUSH DE ;file name already used CALL L4FF8 JP NZ,L504D ;"file name used" if "OPEN DIR" CALL L4E9E JP Z,L504D ;or if dir file CALL L4F22 DEFW #5BB9 AND A JR Z,w4C69 ;no "OVERWRITE? Y/N" if SAVE OVER wanted PUSH HL CALL t4617 ;in case "N" POP HL BIT 6,(HL) JP NZ,L505F ;"PROTECTED FILE" CALL w5703 ;"OVERWRITE" CALL w581F ;file name, "Y/N", key JR Z,w4C66 ;JR if "Y" POP DE POP IX SCF ;signal error RET ;and abort w4C66 CALL L4495 ;in case stopped w4C69 CALL L635D CALL L4E84 LD BC,#000F LD (HL),B ;mark entry in buffer as "deleted" ADD HL,BC ;point to SAM of file in buffer LD DE,L400F ;point to BAM for disc so far LD B,195 w4C79 LD A,(DE) XOR (HL) ;reverse bits ored in by FDHR LD (DE),A ;update BAM to take account of erasure INC E INC HL DJNZ w4C79 POP DE CALL L4BB8 CALL L44B4 ;write dir sect to disc LD IX,dchan CALL L4A6C ;complete BAM by scanning rest of directory JR Z,w4C3A ;JR if second or other copy... should never be! w4C90 POP IX ;clear area for new dir entry in buffer PUSH IX LD B,#00 w4C96 LD (IX+#13),#00 INC IX DJNZ w4C96 POP IX PUSH IX LD HL,L413A LD B,#0B CALL L4CE2 POP IX PUSH IX LD BC,#00DC ADD IX,BC LD HL,L417D+15 LD B,48-15 CALL L4CE2 POP IX CALL L4FF8 CALL Z,L496A ;avoid FNFS if existing opentype file, or if "OPEN DIR" CALL L6EF7 LD (IX+#20),D ;first track LD (IX+#21),E ;and sector of file in dir XOR A ;NC=OK JR L4CD9 L4CCF LD IX,dchan ;get buffer address LD HL,d7D13 LD (L7C0F),HL L4CD9 LD (IX+#0D),#00 ;clear ram pointer LD (IX+#0E),#00 RET L4CE2 LD A,(HL) LD (IX+#13),A INC HL INC IX DJNZ L4CE2 RET L4CEC PUSH HL PUSH DE PUSH BC PUSH IX LD HL,#036A LD DE,(dvar+151) CALL L7BB4 ;jump to DEFW #016F ;JBEEP POP IX POP BC POP DE POP HL RET ;special CFSM used when several blocks may be written to same file and last ;sector needs saving because HSVBL used. t4D03 CALL L4E97 CALL L44B4 ;last sector L4D09 PUSH IX ;close file sector map LD DE,(L41FC) INC E DEC E JR Z,L4D1E ;dir probably full - but do a full check in ;case we are closing an "out" file (FSLOT ;has been set to zero because it might have been ;obsolete if save used since open) CALL L44EA ;read dir sector with free slot LD A,(L41FE) LD (dchan+#0E),A ;pt RPT to free slot JR L4D26 L4D1E LD A,#40 ;find free slot, JPed to from CLOSP CALL L4A18 JP NZ,L5047 ;directory full L4D26 CALL L4E84 ;update directory, JPed to from CLOSP LD (L7C07),IX POP IX PUSH IX LD A,E DEC A OR D OR B ;offset from 'POINT' LD B,#00 ;B=count for 256 bytes JR NZ,w4D4E ;JR if not t0,s1,entry1 LD BC,#D20A ;C=#0A CALL L4D6B ;copy bytes #00-#D1 from buffer ADD HL,BC ;skip disc name - keep as read from disc ADD IX,BC ;(BC=#000A) LD B,#20 CALL L4D6B ;copy bytes #DC-#FB from buffer ;only copy up to #FB on 1st dir entry ;keep rand word, dir tag and 'extra ;dir tracks' byte as read from disc LD A,(IX+#15) ;read dir tag INC HL INC HL LD (HL),A ;use dir tag from buffer, not disc CP A ;Z w4D4E CALL NZ,L4D6B LD IX,(L7C07) CALL w7027 ;copy date/time to +#F2 to +#FB CALL L4E84 INC H DEC HL DEC HL LD A,(dvar+17) LD (HL),A ;tag file with directory code CALL L44B4 CALL t4617 POP IX RET L4D6B LD A,(IX+#13) LD (HL),A INC IX INC HL DJNZ L4D6B RET L4D75 LD A,(L4137) ;get a file from disc INC A ;test for file number JR Z,w4DBC ;JR if not 'LOAD N' (FSTR1=#FF) LD A,#01 ;"numbered file" CALL L4A18 ;find file JP NZ,L5D4F ;error if doesnt exist w4D83 CALL L4E5A ;fiddle ZX type codes CP #15 JP NC,L5032 ;error if DIR or OPENTYPE or SNP 128k SUB #12 ADC A,#00 JP Z,L5032 ;error if type #11 or #12 (arrays) LD DE,L413A LD BC,#000B LDIR LD B,#04 XOR A CALL L4E55 CALL L4EA7 CALL L4E84 LD DE,L417D LD BC,#000B LDIR LD B,#0F CALL L4E53 LD B,48-26 LD A,#FF CALL L4E55 JR w4DC4 w4DBC LD A,#10 ;named file, ignore type CALL L4A18 JP NZ,L5D4F w4DC4 CALL L4E5A LD A,(L413A) LD C,A SUB #14 ADC A,#00 JR NZ,L4DD9 ;JR if desired type <> CODE or SCREEN$ LD A,(HL) SUB #14 ADC A,#00 JR NZ,L4DD9 ;JR if loaded type <> CODE/SCREEN$ LD (HL),C ;loaded type=desired type L4DD9 LD A,C CP (HL) JP NZ,L5032 ;wrong file type if no match CALL L500A ;called by COPY - Z set (F7 used for other things) w4DE1 PUSH AF ;"flag 7" status - NZ if ZX LD DE,L4165 CALL L4EA7 ;211-219 ZX file data to HD002 DEC HL LD DE,L7F90-30 ;STR-30 LD C,42 LDIR ;210-251 with SNP regs at STR-20 CALL L4E46 POP AF JR Z,w4E2F ;JR if not ZX file LD B,#0B CALL L4E53 LD B,#16 LD A,#FF CALL L4E55 LD HL,(L4165+1) ;len XOR A CALL L7462 RES 7,H LD (L41AD+34),A ;difa LD (L416C),A LD (L41AD+35),HL LD (L4165+1),HL LD HL,(L4168) ;addr XOR A CALL L7462 DEC A AND #1F LD (L41AD+31),A LD (L416D),A LD (L41AD+32),HL LD (L4168),HL JR w4E39 w4E2F LD B,#DC CALL L4E86 LD BC,48-15 LDIR w4E39 LD B,#0D CALL L4E86 LD D,(HL) INC HL LD E,(HL) LD (L7C02),DE RET L4E46 CALL L4E84 LD DE,L41AD ;type/name LD BC,#000B LDIR LD B,#04 L4E53 LD A,#20 ;load (DE) with count B L4E55 LD (DE),A INC DE DJNZ L4E55 RET L4E5A CALL L4E9E CP #07 JR NZ,w4E63 LD A,#04 w4E63 CP #10 JR NC,w4E6D ;JR if Sam file DEC A OR #10 CALL L4FDA ;"ZX file" w4E6D LD (HL),A RET L4E6F CALL L4629 ;read sector SR DI LD C,#80 CALL L4487 L4E78 LD L,(IX+#0F) LD H,(IX+#10) RET L4E7F LD A,#10 ;find a file routine CALL L4A18 L4E84 LD B,#00 ;get RAM and pointer to buffer L4E86 LD (IX+#0D),B L4E89 LD L,(IX+#0F) LD H,(IX+#10) LD B,(IX+#0E) LD C,(IX+#0D) ADD HL,BC RET L4E97 LD D,(IX+#12) ;get the next track/sector LD E,(IX+#11) RET L4E9E CALL L4E84 LD A,(HL) AND #1F CP #15 ;DIR RET L4EA7 LD B,#D3 CALL L4E86 LD BC,#0009 PUSH HL LDIR POP HL RET ;D1.Z80 L4EB4 CALL L4F06 ;check is it end of line CP #0D RET Z CP ":" RET L4EBD LD (L411D),A ;check for syntax only CALL L4F22 DEFW #5C3B ;FLAGS AND #80 LD A,(L411D) RET L4ECB CALL L4EB4 ;check for end of syntax JR NZ,w4EFD CALL L4EBD RET NZ L4ED4 LD E,#00 ;end of statement ;no action DEFB #21 ;dummy LD HL,#011E w4ED7 LD E,#01 L4ED9 XOR A CALL L4F38 DEFW #5AA3+1 ;XPTR, no error CALL L501C LD (L411F),A ;recurse OK LD SP,(L4104) w4EE9 POP HL ;from end of hooks LD (L4104),HL ;old value RET w4EEE LD A,#F7 ;test for break routine IN A,(#F9) AND #20 RET NZ CALL L5097 DEFB 84 L4EF9 CALL L4F00 ;insist separator C L4EFC CP C w4EFD JP NZ,L5DCA ;error or skip char L4F00 CALL L7BB4 ;get the next char. DEFW #0020 RET L4F06 CALL L7BB4 ;get the char under pointer DEFW #0018 RET n4F0C CALL w618B ;CY if a letter or digit RET C L4F10 CP "9"+1 ;CY if a digit, NC if too high RET NC CP "0" CCF RET L4F17 EX (SP),HL ;read a double ROM word in BC PUSH DE CALL L4F9D PUSH DE CALL w4F7E JR L4F4E L4F22 EX (SP),HL ;read a ROM system variable (param word) to A reg PUSH DE CALL L4F9D PUSH DE CALL L4F8D JR L4F4E L4F2D EX (SP),HL ;write a double word from A ROM sys var (param word) to BC PUSH DE CALL L4F9D PUSH DE CALL L4F6F JR L4F4E L4F38 EX (SP),HL ;write ROM system variable PUSH DE CALL L4F9D PUSH DE LD E,A ;write A to (HL) in sys page IN A,(#FB) LD D,A XOR A OUT (#FB),A SET 7,H RES 6,H LD (HL),E LD A,D OUT (#FB),A LD A,E L4F4E POP HL POP DE EX (SP),HL RET ;place "NEXTST" addr - called by "OPEN" ;in case NEXTSTAT not on stack, place it. transforms: ;NEXT STAT/ERRSP to FOWIA/NEXTSTAT/ERRSP ; * * (*=SP) ;ERRSP to FOWIA/NEXTSTAT/ERRSP ; * * (*=SP) L4F52 LD HL,(L4104) INC HL INC HL INC HL INC HL ;main ROM stack ptr on dos stack DEC (HL) DEC (HL) ;dec stored SP LSB CALL L4F17 ;\(add one addr to ensure ints do not hit) DEFW #5C3D ;read ERRSP into BC LD H,B LD L,C LD BC,(L421E) CALL w4F6D ;dec HL to pt to addr below ERRSP, write BC DEC HL LD BC,#0004 ;null w4F6D DEC HL DEC HL L4F6F IN A,(#FB) ;write BC to (HL) in sys page EX AF,AF' XOR A OUT (#FB),A SET 7,H RES 6,H LD (HL),C INC HL LD (HL),B JR L4F98 w4F7E IN A,(#FB) ;read BC from HL in sys page EX AF,AF' XOR A OUT (#FB),A SET 7,H RES 6,H LD C,(HL) INC HL LD B,(HL) JR L4F98 L4F8D IN A,(#FB) ;replace call CMR:DW NRREAD - faster EX AF,AF' XOR A OUT (#FB),A SET 7,H RES 6,H LD A,(HL) L4F98 EX AF,AF' OUT (#FB),A EX AF,AF' RET L4F9D LD E,(HL) ;LD HL,(HL) INC HL LD D,(HL) INC HL EX DE,HL RET L4FA3 EX (SP),HL ;get the half FLAG3 PUSH HL ;orig HL on stack, then RET addr LD HL,w4FAE EX (SP),HL PUSH HL ;orig HL, PHLR, RET addr LD HL,L7C0C RET w4FAE POP HL RET L4FB0 CALL L4FA3 ;set FLAG3 subroutine SET 0,(HL) RET L4FB6 CALL L4FA3 SET 1,(HL) RET L4FBC CALL L4FA3 SET 2,(HL) RET L4FC2 CALL L4FA3 SET 3,(HL) RET L4FC8 CALL L4FA3 SET 4,(HL) RET w4FCE CALL L4FA3 SET 5,(HL) RET L4FD4 CALL L4FA3 SET 6,(HL) RET L4FDA CALL L4FA3 SET 7,(HL) RET w4FE0 CALL L4FA3 ;bit test of FLAG3 routs. BIT 0,(HL) RET L4FE6 CALL L4FA3 BIT 1,(HL) RET L4FEC CALL L4FA3 BIT 2,(HL) RET L4FF2 CALL L4FA3 BIT 3,(HL) RET L4FF8 CALL L4FA3 BIT 4,(HL) RET L4FFE CALL L4FA3 BIT 5,(HL) RET L5004 CALL L4FA3 BIT 6,(HL) RET L500A CALL L4FA3 BIT 7,(HL) RET w5010 LD A,(dvar+0) ;BORDER colour change AND #0F RET Z AND #07 AND E OUT (#FE),A RET L501C PUSH AF ;BORDER colour restore CALL L4F22 DEFW #5C4B OUT (#FE),A POP AF RET L5026 LD A,85 ;error report messages DEFB #21 w5029 LD A,86 DEFB #21 w502C LD A,87 DEFB #21 w502F LD A,93 DEFB #21 L5032 LD A,94 DEFB #21 w5035 LD A,99 DEFB #21 L5038 LD A,100 DEFB #21 w503B LD A,101 DEFB #21 L503E LD A,103 DEFB #21 L5041 LD A,104 DEFB #21 w5044 LD A,105 DEFB #21 L5047 LD A,106 DEFB #21 L504A LD A,22 ;EOF DEFB #21 L504D LD A,109 DEFB #21 w5050 LD A,111 DEFB #21 w5053 LD A,112 DEFB #21 w5056 LD A,113 DEFB #21 w5059 LD A,114 DEFB #21 L505C LD A,115 DEFB #21 L505F LD A,116 LD (L5067),A CALL L5097 L5067 DEFB 0 L5068 PUSH DE ;convert number in A to digits in ABC LD H,#00 LD L,A LD DE,#0064 LD C,#20 CALL L5085 PUSH AF ;hundreds digit LD DE,#000A CALL L5085 PUSH AF ;tens digit LD A,L ADD A,"0" LD B,A POP AF LD C,A POP AF POP DE RET L5085 XOR A w5086 SBC HL,DE JR C,w508D INC A JR w5086 w508D ADD HL,DE AND A JR NZ,w5093 LD A,C ;space or zero RET w5093 LD C,"0" ;** ADD A,C RET L5097 CALL L501C ;SAMDOS error print, DE holds track and sector LD HL,(L420B) LD A,H OR L JR Z,w50A3 LD SP,HL RET w50A3 LD A,D CALL L5068 LD (w50F6),A LD (w5111),A LD (w50F6+1),BC LD (w5111+1),BC LD A,E CALL L5068 LD (w50FE),BC CALL L4F17 DEFW #5A97 ;CHADD CALL L4F2D DEFW #5AA3 ;XPTR CALL L4F22 DEFW #5A96 ;CHADP CALL L4F38 DEFW #5AA2 ;XPTRP XOR A LD (L7C0C),A ;FLAG3 LD (L411F),A ;recurse OK LD E,A POP HL LD A,(HL) ;err no. LD SP,L7FFA ;OK whether cmd or hook RET d50DF DEFB #A0 ;0 DEFB #A0 ;1 DEFB #A0 ;2 DEFM 'Escape requeste' DEFB "d"+128 ;3 DEFM 'TRK-' w50F6 DEFM ' ,SCT-' w50FE DEFM ' ,Erro' DEFB "r"+128 ;4 DEFM 'Format TRK-' w5111 DEFM ' los' DEFB "t"+128 ;5 DEFM 'Check disk in driv' DEFB "e"+128 ;6 DEFB #A0 ;7 DEFB #A0 ;8 DEFB #A0 ;9 DEFB #00 DEFM 'devic' DEFB "e"+128 ;10 DEFB #A0 ;11 DEFM 'Verify faile' DEFB "d"+128 ;12 DEFM 'Wrong ' DEFB #17 DEFM ' typ' DEFB "e"+128 ;13 DEFB #A0 ;14 DEFB #A0 ;15 DEFB #A0 ;16 DEFB #A0 ;17 DEFM 'Reading a write ' DEFB #17+128 ;18 DEFM 'Writing a read ' DEFB #17+128 ;19 DEFB #0B DEFM 'AUTO* ' DEFB #17+128 ;20 DEFB #A0 ;21 DEFB #0B DEFM 'such driv' DEFB "e"+128 ;22 DEFM 'Disk is write protecte' DEFB "d"+128 ;23 DEFM 'Disk ful' DEFB "l"+128 ;24 DEFM 'Directory ful' DEFB "l"+128 ;25 DEFM 'File' DEFB #11 DEFM 'foun' DEFB "d"+128 ;26 DEFB #A0 ;27 DEFM 'File' DEFB #12 DEFM ' use' DEFB "d"+128 ;28 DEFB #A0 ;29 DEFM 'S' DEFB #08 DEFM ' use' DEFB "d"+128 ;30 DEFM 'Channel use' DEFB "d"+128 ;31 DEFM 'Directory' DEFB #11 DEFM 'foun' DEFB "d"+128 ;32 DEFM 'Directory' DEFB #11 DEFM 'empt' DEFB "y"+128 ;33 DEFB #0B DEFM 'pages fre' DEFB "e"+128 ;34 DEFM 'PROTECTED ' DEFB #17+128 ;35 L5214 LD (L7F90),SP ;non mask int rout. LD SP,L7F90 LD A,I PUSH AF PUSH HL PUSH BC PUSH DE EX AF,AF' EXX PUSH AF PUSH HL PUSH BC PUSH DE PUSH IX PUSH IY LD HL,L5316 ;push return address on stack PUSH HL LD (L420B),SP w5233 LD A,#04 ;test for snapshot type OUT (#FB),A ;ZX RAM at #8000 IM 1 L5239 LD BC,#F7FE IN E,(C) ;bits 0-4=digits 1-5 BIT 0,E JR Z,w5246 ;JR if "1" BIT 4,E JR NZ,w5253 ;JR if not "5" w5246 LD HL,(dvar+27) LD A,(dvar+26) ;normally 4 OUT (#FB),A CALL #0005 ;JP (HL), just ret usually (#0004) JR w5233 w5253 BIT 1,E ;RET if "2" RET Z BIT 2,E ;JR if not "3" JR NZ,w5260 LD A,#14 ;SCREEN$ type LD D,#1B ;screen length MSB JR L528E w5260 BIT 3,E ;JR if not "4" JR NZ,w526A LD A,#05 ;48kB snapshot type LD D,#C0 ;len MSB JR L528E w526A INC A AND #07 OUT (C),A ;border LD B,#FE IN E,(C) BIT 2,E JR NZ,L5239 ;loop if not "X" w5277 IN E,(C) BIT 2,E JR Z,w5277 ;loop till not "X" CALL #005F ;delay BC LD A,(L4106) OUT (#FB),A LD A,(#4108) OUT (#FC),A EI JP L4ED4 L528E LD (L41E4),A ;save variables of file LD HL,#8000 ;ZX RAM starts at #8000 LD E,L ;zero E LD (L41F4),DE LD (L41F6),HL LD IX,dchan ;test for directory space LD B,#FE IN A,(C) RRA LD A,#01 JR C,w52AA ;JR if not INC A ;drive 2 w52AA CALL L46EF LD A,#40 CALL L4A18 JR NZ,L5239 ;loop if no space LD A,D ;form snapshot file name AND #07 JR Z,w52BE ADD A,#30 LD (#41E4+5),A w52BE LD L,E SLA L DEC L LD A,(IX+#0E) ADD A,L ADD A,#40 LD (#41E4+6),A LD HL,L41E4 ;transfer name to file area LD DE,L413A LD BC,24 LDIR XOR A ;open a file LD (L7C0C),A LD (L4150),A CALL L4C2A LD HL,L7F90-20 ;save registers in directory LD DE,L7C13+220 LD BC,22 LD A,(L413A) CP #05 JR Z,w5300 ;JR if 48k snap - no hdr. copy regs XOR A LD (DE),A ;flags INC DE LD (DE),A ;screen mode CALL L5E25 LD HL,d530F ;SCREEN$ start, len LD DE,L7C13+236 LD BC,7 w5300 LDIR LD HL,(L41F6) LD DE,(L41F4) CALL L4840 JP L4D09 d530F DEFB #6E,#00,#80,#00,#00,#1B,#FF ;start, len L5316 DI ;return address of snapshot LD A,#03 OUT (#FB),A ;spectrum "ROM" at #8000 LD HL,#0000 LD (L420B),HL LD SP,L7F90-20 POP IY POP IX POP DE POP BC POP HL POP AF EX AF,AF' EXX LD HL,L5214 LD (#B8F6),HL ;in ZXROM LD HL,L4106 LD DE,#B8F8 LD BC,#0003 LDIR ; LD A,(SNPRT0) ;remarked in original ; LD (0B8F8H),A ; LD A,(SNPRT1) ; LD (0B8F9H),A ; LD A,(SNPRT2) ; LD (0B8FAH),A ;store info in emulator ROM area POP DE POP BC POP HL POP AF LD I,A AND A JR Z,L534E CP #3F JR Z,L534E IM 2 L534E LD SP,(L7F90) JP #B900 ;in ZXROM ;E1.Z80 w5355 DI ;disc format routine CALL L46EC CALL L4718 LD B,#0A w535E PUSH BC CALL L4670 POP BC DJNZ w535E CALL t4692 DI LD C,#80 CALL L4487 CALL L4E78 CALL L44FC AND #0D JR NZ,w537F ;JR if error on read t0/s1 CALL w5712 ;"FORMAT " ; LD HL,DRAM+0D2H ;remarked in original ; CALL pndn2 ;print disc name CALL w5822 ;"Y/N", key RET NZ w537F CALL L4812 CALL w5730 ;print "FORMAT DISK AT TRACK " LD DE,#0001 ;t0/s1 CALL L5476 ;prepare track data LD HL,#A280+#0176 ;end of t0/s1 entry 1 CALL L54EF JR w5396 L5393 CALL L5476 ;prepare track data w5396 CALL L5449 ;display track number CALL w5431 BIT 5,A JP NZ,L5041 ;JP if write-protected INC D CALL L49DB CP D JR Z,w53C7 ;JR if all tracks done AND #7F CP D JR Z,w53BD ;JR if time for side 2 CALL L4670 LD A,(dvar+14) ;#FF gives skew 1, #FE gives skew 2, 0 gives skew 0 DEC E ;E=0-9 ADD A,E JR C,w53B9 ADD A,#0A ;#FF->#09, #FE->#08 w53B9 LD E,A INC E ;1-10 JR L5393 w53BD CALL t4692 LD D,#80 CALL L4718 JR L5393 w53C7 CALL t4692 ;DE=0001 LD A,(L4152) CP #FF JR Z,w541A ;JR if simple format, not disk copy ; LD HL,(BUF) ;remarked in original ; LD (SVBUF),HL w53D1 CALL w573C CALL L5449 LD A,(L4152) CALL L46EF LD HL,LA280 w53E0 LD (L7C0F),HL CALL L44EA INC H INC H CALL L5521 JR NZ,w53E0 ;read 10 sectors to buffer LD A,(L4136) CALL L46EF LD HL,LA280 w53F6 LD (L7C0F),HL CALL L44B4 INC H INC H CALL L5521 JR NZ,w53F6 ;write 10 sectors from buffer CALL L545C JR NZ,w53D1 ; LD HL,(SVBUF) ;remarked in oryginal ; LD (BUF),HL CALL L4CCF JR w5425 L540D CALL L44EA CALL L5521 JR NZ,L540D CALL L4670 JR w541D w541A CALL w5748 w541D CALL L5449 CALL L545C JR NZ,L540D w5425 CALL L59D9 LD HL,LA280 CALL L4820 JP t4692 w5431 DI CALL L4451 ;get C=stat port LD A,C LD (L44DD+1),A ;self-mod status port INC C INC C INC C ;data port PUSH BC LD C,#F2 CALL w4478 POP BC LD HL,LA280 JP L44DD ;keep delay between PRECMP and WSA3 small L5449 PUSH DE ;print track on screen LD A,#15 ;column 21 CALL L4F38 DEFW #5A6E LD L,D LD H,#00 LD A,#20 CALL L5646 DI POP DE RET L545C INC D ;increment track. Z if all done CALL L49DB CP D RET Z ;RET if finished all trks LD H,A CALL L5FDB LD A,H JR C,w546B ;JR if not ram disc LD A,#50 w546B AND #7F CP D RET NZ ;RET if not finished side 1 CALL t4692 LD D,#7F INC D ;NZ RET L5476 LD HL,LA280 ;double density format LD BC,#3C4E ;60 (#3C) track hdr bytes of #4E CALL L54EA LD B,#0A ;10 sectors w5481 PUSH BC LD BC,#0C00 CALL L54EA LD BC,#03F5 CALL L54EA LD C,#FE CALL L54E9 LD C,D RES 7,C CALL L54E9 ;track LD A,D AND #80 RLCA LD C,A CALL L54E9 ;side LD C,E CALL L5521 CALL L54E9 ;sector LD C,#02 CALL L54E9 ;512-byte sects LD C,#F7 CALL L54E9 LD BC,#164E CALL L54EA LD BC,#0C00 CALL L54EA LD BC,#03F5 CALL L54EA LD C,#FB CALL L54E9 LD BC,#0000 CALL L54EA CALL L54EA ;512 bytes for data LD C,#F7 CALL L54E9 LD BC,#1B4E ;3 bytes extra for more time between sectors CALL L54EA POP BC DJNZ w5481 LD C,#4E CALL L54EA CALL L54EA DEC B ;track tail of 768 bytes (only about 200 used) L54E9 INC B ;write format in memory L54EA LD (HL),C INC HL DJNZ L54EA RET L54EF LD A,(dvar+16) ;place DTKS-4 at (HL), and rnd word at (HL-3), and name SUB #04 LD (HL),A ;mark dir entry 1 (t0,s1) with tks/dir-4 L54F5 PUSH HL ;called by RENAME DEC HL DEC HL LD A,R LD (HL),A DEC HL CALL L4F22 DEFW #5C78 ;FRAMES low LD (HL),A ;rnd no uses R reg and frames LD BC,-42 ADD HL,BC ;pt to disc name dest (byte #D2) PUSH DE LD DE,L413A+1 EX DE,HL LD A,(HL) AND #DF CP "D" JR NZ,L5519 CALL L6583 JR NZ,L5519 LD (HL),"*" ;alter "D " to "* " so FORMAT "D" ;does not use disc name "D" L5519 LD BC,#000A LDIR ;copy name to track buffer POP DE POP HL RET L5521 INC E ;increment sector routine LD A,E CP #0B RET NZ LD E,#01 RET w5529 AND #1F ;print type of file PUSH AF CP #16 JR C,w5532 LD A,#0D w5532 LD B,A LD HL,w55BA CALL L76E9 POP AF ;type CP #10 JR NZ,w5552 LD B,#F2 ;BASIC program CALL L4E86 LD A,(HL) AND #C0 JR NZ,L5594 INC HL LD E,(HL) INC HL LD D,(HL) EX DE,HL CALL L5634 JR L5594 w5552 CP #13 JR NZ,w5574 LD B,#EC ;CODE CALL L4E86 CALL L55AD INC C EX DE,HL PUSH DE LD A,#20 CALL L5612 LD A,"," CALL L567D POP HL CALL L55AD EX DE,HL XOR A CALL L5612 w5574 CP #04 JR NZ,L5594 LD B,#D7 ;ZX CODE CALL L4E86 LD D,(HL) DEC HL LD E,(HL) EX DE,HL PUSH DE CALL L5634 LD A,"," CALL L567D POP HL DEC HL LD D,(HL) DEC HL LD E,(HL) EX DE,HL XOR A CALL w5636 L5594 LD A,(dvar+19) AND A JR Z,w55AA LD A,#17 CALL L567D ;tab LD A,#23 CALL L567D CALL L567D CALL w7068 ;print date/time w55AA JP L5AEA L55AD LD A,(HL) ;get number from header AND #1F LD C,A INC HL LD E,(HL) INC HL LD A,(HL) AND #7F LD D,A INC HL RET w55BA DEFB #A0 DEFB #0A,"B","A","S","I","C"+128 DEFB #0A,"D",#09+128 DEFB #0A,"$",#09+128 DEFB #0A+128 DEFB #0A,"S","N","P"," ","4","8","K"+128 DEFB "M","D",".","F","I","L","E"+128 DEFB #0A,#0B+128 DEFB "S","P","E","C","I","A","L"+128 DEFB #0A,"S","N","P"," ","1","2","8","K"+128 DEFB "O","P","E","N","T","Y","P","E"+128 DEFM 'N/A EXECUT' DEFB "E"+128 DEFB #88,#88,#88,#88 DEFB "B","A","S","I","C"+128 DEFB "D",#09+128 DEFB "$",#09+128 DEFB "C"+128 DEFB #0B+128 DEFB " "," "," "," ","D","I","R"+128 L5612 LD (L411D),A ;print number in HL XOR A LD DE,#0000 RR C RR D RR C RR D LD A,D ADD A,H LD H,A LD A,C ADC A,E LD B,A LD DE,34464 ;=#86A0 LD C,#01 ;65536 LD A,(L411D) CALL L565A JR w5638 L5634 LD A,#20 w5636 LD B,#00 w5638 LD C,#00 LD DE,10000 CALL L565A L5640 LD DE,1000 CALL L5657 L5646 LD DE,100 CALL L5657 L564C LD DE,10 CALL L5657 LD A,L w5653 ADD A,"0" ;print digit JR L567D L5657 LD BC,#0000 L565A PUSH AF LD A,B LD B,#00 AND A w565F SBC HL,DE SBC A,C JR C,w5667 INC B JR w565F w5667 ADD HL,DE ADC A,C LD C,A LD A,B LD B,C AND A JR NZ,w5674 POP DE ADD A,D RET Z JR L567D w5674 CALL w5653 POP DE LD A,"0" RET L567B LD A,#20 ;send a space character L567D PUSH AF ;output A char to current chan CALL L7BB4 ;jump to DEFW #0010 POP AF RET L5685 POP HL ;display text after CALL L5686 LD A,(HL) AND #7F CP #0D JR NC,w56A0 PUSH HL PUSH DE AND A JR NZ,w5696 ;1..12 are compression codes CALL L59D9 ;0=CLSL CP A ;Z w5696 LD B,A LD HL,d56A9 ;local texts CALL NZ,L76E9 ;pnt msg B from list at HL POP DE POP HL SCF w56A0 CALL NC,L567D BIT 7,(HL) RET NZ INC HL JR L5686 ;0=clear lower screen d56A9 DEFB #A0 DEFB " ","d","i","s","k"+128 DEFM 'press a ke' DEFB "y"+128 DEFM 'at trac' DEFB "k"+128 DEFB " ","(","y","/","n",")"+128 DEFB "I","n","s","e","r","t"+128 DEFB " ","D","O","S"+128 DEFB " ","F","r","e","e"+128 DEFB "W","H","A","T","?"+128 DEFB ".","A","R","R","A","Y"+128 DEFB "Z","X"+128 DEFB "S","C","R","E","E","N","$"+128 ;screen routines w56EB CALL L5685 ;text follows DEFB #0D DEFM 'Number of' DEFB #07 DEFM 'K-Bytes =' DEFB " "+128 w5703 CALL L5685 ;text follows DEFB #00 DEFM 'OVERWRITE ' DEFB #22+128 w5712 CALL L5685 ;text follows DEFB #00 DEFM 'FORMAT ' DEFB #22+128 w571E CALL L5685 ;text follows DEFB #22,#04+128 w5723 CALL L5685 ;text follows DEFB #00,#05 DEFM 'source' DEFB #01,#02+128 w5730 CALL L5685 ;text follows DEFB #00 DEFM 'Format' DEFB #01,#03+128 w573C CALL L5685 ;text follows DEFB #00 DEFM ' Copy' DEFB #01,#03+128 w5748 CALL L5685 ;text follows DEFB #00 DEFM 'Verify' DEFB #01,#03+128 w5754 CALL L5685 ;text follows DEFB #00,#05 DEFM 'target' DEFB #01,#02+128 w5761 CALL L5685 ;text follows DEFM ' Fil' DEFB "e"+128 w5769 CALL L5685 ;text follows DEFB #07 DEFB "S","l","o","t"+128 w5771 CALL L5685 DEFB #00 DEFM 'LOADING' DEFB " "+128 w577D CALL L5685 ;text follows DEFB #00 DEFM ' SAVING' DEFB " "+128 w5789 CALL L5685 ;text follows DEFM 'SAM' DEFB #06," "," "," "+128 w5793 CALL L5685 ;text follows DEFM '" (y/n/a/e' DEFB ")"+128 w57A1 LD HL,L57BE ;print disc name, from format pndn2 LD A,(HL) ;#00 if old dos, or #FF if nev used it for IBU ;or first name char RES 7,(HL) ;so nev can use bit 7 as IBU marker INC A CP #02 JR C,w5789 ;print " SAM DOS " if old dos LD A,(HL) CP "*" JR NZ,w57BB ;print disc name if there is one, CALL L5685 ;print "MASTER DOS " if no name DEFM 'MASTER' DEFB #06+128 w57BB CALL L5685 ;text follows L57BE DEFB #00,#00,#00,#00,#00 ;over-written DEFB #00,#00,#00,#00,#00 DEFB " "+128 w57C9 CALL L5685 ;text follows DEFM 'OPEN Fil' DEFB "e"+128 w57D5 DEFB "U","N"," ",#08 ;space, backspace cancels leading space on KWDS w57D9 CALL L59D9 XOR A CALL w5800 ;tokens on CALL L4F22 DEFW #5B74 CP #F1 JR C,w57F6 ;JR if erase or copy PUSH AF CALL L4FE6 LD HL,w57D5 LD B,#04 CALL NZ,L6F9A ;print "UN" if protect or hide off POP AF w57F6 CALL L567D ;print PROTECT, HIDE, ERASE or COPY LD A,#22 CALL L567D ;now e.g. ERASE " LD A,#01 w5800 CALL L4F38 DEFW #5ABA ;tokens off RET w5806 CALL L49F0 ;print file name CALL w5793 ;Y/N/A/E CALL L5828 RET Z ;RET if "Y" CP "E" JP Z,L4ED4 ;end CP "A" RET NZ LD HL,L7C0C RES 7,(HL) ;"?" option off - do all CP A ;Z - "Y" RET w581F CALL L49F0 ;print file name w5822 CALL w571E ;"Y/N" CALL L4CEC ;compare for Y or N L5828 CALL L5859 JR NC,L5828 AND #DF CP #59 PUSH AF w5832 CALL L5859 JR C,w5832 CALL L59D9 POP AF RET L583C CALL L4FFE RET Z CALL w5754 JR L584C L5845 CALL L4FFE RET Z CALL w5723 L584C CALL L5859 JR NC,L584C w5851 CALL L5859 JR C,w5851 CALL L59D9 L5859 PUSH IX CALL L7BB4 ;jump to DEFW #0169 ;JREADKEY POP IX RET ;F11.Z80 k5863 LD C,#AA ;CALL MODE, ZX entry into RAM space CALL L4EF9 CALL L6132 CALL L4ECB LD A,C CP #02 JP NC,L5F12 LD A,#04 OUT (#FC),A ;screen in page 4, Spectrum mode DEC C JP Z,L5316 ;JP if "CALL MODE 1" DEC A ;CALL MODE 0 OUT (#FB),A ;page 3 (Spectrum "ROM") at #8000 DI JP #B914 ;JP to "ROM" L5883 CALL L6050 LD C,#8E ;TO CALL L4EFC CALL w609F CALL L4F06 JR w5896 L5893 CALL L6050 ;eval name with "?" option w5896 CP "?" JR NZ,w58A0 CALL L4F00 ;skip "?" CALL L4FDA w58A0 JP L4ECB L58A3 CALL L71BC ;COPY/BACKUP SR CALL L60A5 ;EXDAT and EXX strings at #4F00/#4F80 in sys pg CALL L71BC CALL L60C4 LD A,(L4136) LD B,A LD A,(L4152) CP B RET NZ ;RET if 2 disks in use CP #03 JP C,w4FCE ;set flag 5 if single-disc copy with 1 or 2 RET k58BE CALL L4F00 ;COPY, disc copy routine CP #A6 ;OVER JR NZ,w58C9 CALL L4F00 XOR A ;0="SAVE OVER" w58C9 CALL L4F38 DEFW #5BB9 CALL L5883 CALL L58A3 ;COPY/BACKUP SR CALL L5D07 ;copy NSTR2 to NSTR3 to ACT as saved name template CALL L59CC LDIR ;init buffer L58DC CALL L46EC CALL L4FE6 LD HL,(L4218) LD A,(L4209) JR NZ,w5918 ;JR if still part of last file to do CALL L5CF0 ;refresh buffer LD HL,L7C0C RES 3,(HL) ;"first pass - OFSM needed" CALL L5D3F ;find file - abort if not found JR C,L58DC ;JR if dir type CALL L5C5B JR NZ,L58DC ;JR if "?" and "N" LD B,#0B CALL L4E86 LD B,(HL) INC HL LD C,(HL) PUSH BC ;no. of sectors in file XOR A ;Z so "not ZX file" to GTFL2 CALL w4DE1 CALL L44E6 POP BC LD HL,#01FE CALL L6F25 ;get AHL=HL+BC*510 (max file size) CALL L7462 RES 7,H ;A=pages, HL=len mod 16k w5918 PUSH AF ;entry here if 2nd or later passes PUSH HL CALL w5771 ;"LOADING " LD HL,L41AD+1 CALL L49F5 ;get in B no. of pages in biggest free block page in E CALL L59AC INC B DEC B JP Z,L505C ;error if no free pages LD HL,L7C0C RES 1,(HL) ;"close after this" LD L,E ;page POP DE ;len mod 16k POP AF ;required pages, minus 1 CP B ;free pages JR C,w5945 ;JR if we can complete the copy in this pass SUB B LD (L4209),A ;pages left to do LD (L4218),DE ;len mod 16k left CALL L4FB6 ;"no close" LD A,B LD DE,#0000 ;len mod 16k=0 w5945 LD (L4212),DE ;len mod 16k to do (for SVBLK) LD H,A LD (L4214),HL ;PGES1/PAGE of buffer CALL L599E CALL L475A CALL L583C CALL L60E2 CALL w6199 CALL L46EC CALL L4FF2 JR NZ,w596C ;JR if not first pass CALL L4C2A JR C,L5995 ;JR if "OVERWRITE?" and CALL L4FC2 ;"no OFSM next time" w596C CALL w577D ;"SAVING " LD HL,L413A+1 CALL L49F5 CALL L4495 ;spin disk if stopped CALL L599E LD DE,(L4212) ;len CALL w482D CALL L4FE6 JR NZ,L5995 ;no close if part still to do LD HL,L7F90-30 LD DE,L7C13+210 LD BC,#002A LDIR CALL t4D03 L5995 CALL L60E2 ;msg if single drive CALL L5845 JP L58DC L599E LD HL,(L4214) LD A,H LD (L4150),A LD A,L OUT (#FB),A LD HL,#8000 RET ;find free pages ;exit: sys page at #8000, B=size of max free block in pages, E=page number L59AC XOR A OUT (#FB),A LD HL,#5100+up+31 ;on sys page LD B,#00 ;biggest block so far=0 pages L59B4 INC L w59B5 DEC L RET Z LD A,(HL) AND A JR NZ,w59B5 ;loop, looking for a free page x59BB LD C,#00 ;current block=0 pages w59BD DEC L LD A,(HL) INC C AND A JR Z,w59BD ;loop while pages free, counting LD A,B CP C JR NC,L59B4 ;JR if current block no bigger than max LD B,C ;new max size LD E,L INC E ;point to first page in free block =new start page JR L59B4 L59CC CALL L4812 LD HL,L7C0D LD DE,#B800 ;allows #1580 bytes for sector list at #A280 LD BC,#0306 ;len of RPT, BUF, NSR, FSA, DRAM RET L59D9 PUSH IX ;used by MODE 1/2 CLS CALL L7BB4 ;jump to DEFW #0151 ;JCLSLOWER POP IX RET ;call up directory k59E3 CALL L64CB ;DIR, call GTIXD, GTDEF, null name LD A,#02 LD (L4138),A ;stream 2 XOR A LD (dvar+19),A ;"PRINT DATES" off CALL L4F00 CP "=" JP Z,w70C3 CP "#" JR NZ,w5A01 CALL L6119 CALL L5DC6 w5A01 CP #F9 ;"DATE" token JR NZ,w5A10 LD (dvar+19),A ;"PRINT DATES" on (NZ) CALL L4F00 ;skip "DATE" CALL L4EB4 JR Z,L5A47 ;"DIR DATE" gives detailed, dated dir w5A10 CALL L5BF3 CALL L4EB4 JR Z,w5A40 ;just "DIR" gives simple dir CALL w5FE1 ;eval drive, or file name JR NC,w5A30 ;JR if it was a name CALL L5DCE ;,/;/" JR NZ,w5A36 LD A,(L4136) PUSH AF ;Z CALL L6050 ;eval name - ,/;/" followed drive number CALL NZ,L71BC POP AF ;Z LD (L4136),A ;keep drive no set by number w5A30 CALL NZ,L71BC ;process name if run time CALL L4F06 w5A36 CP "!" JR NZ,L5A47 ;JR if e.g. DIR 1,"NAME" or DIR 1 - detailed CALL L4F00 ;skip "!" - e.g. DIR 1,"NAME"! or DIR 1!-simple CALL L5BF3 w5A40 CALL L4ECB LD A,#02 ;simple dir JR t5A56 L5A47 CALL L5BF3 CALL L4ECB LD A,#01 ;window CALL L7BB4 ;jump to DEFW #014E ;JCLSBL, main cls LD A,#04 ;single column detailed dir ;setup for directory ;NSTR1+1,* ;SSTR1 ,2 ;A =2 for simple, 4 for detailed dir t5A56 PUSH AF CALL L46EC LD A,(L4138) CALL L7BB4 ;jump to DEFW #0112 ;JSETSTRM CALL L5B09 ;zero vars POP AF ;2 if simple CP #02 JR NZ,w5AB1 CALL L5B16 ;dir to buffer CALL L5AF7 ;print header LD HL,(L412C) LD DE,#A000 AND A SBC HL,DE ;HL=text len (1sl JR Z,L5AA9 ;\ LD BC,#000A LD D,B LD E,B ; > cuted in 4.3 w5A80 INC DE SBC HL,BC JR NZ,w5A80 ;/ LD HL,#A000 ;HL=start, DE=files LD A,(dvar+9) AND A CALL NZ,w5B71 CALL w5BC2 ;names/line in B. could be 1,2,3 etc LD C,B w5A93 PUSH BC ;B=names/line counter, C=reload CALL L49F5 ;print name, advance HL POP BC DEC DE LD A,D OR E JR Z,L5AA9 ;exit if all done LD A,#20 DJNZ w5AA4 ;JR and use space unless last name on line LD A,#0D LD B,C ;reload counter w5AA4 CALL L567D ;cr or space JR w5A93 L5AA9 CALL L4820 CALL L5AEA JR w5AB4 w5AB1 CALL L4A18 ;do complex directory w5AB4 CALL w56EB ;"Number of Free K-Bytes = " CALL L5B24 ;get HL=free sects, DE=free slots PUSH DE SRL H RR L ;halve free sects XOR A CALL L5640 ;free kB CALL L5AEA ;carriage return LD HL,(L421C) PUSH HL XOR A CALL L5640 ;print no. of files in current dir CALL w5761 ;print " File" POP HL CALL L5AEF LD A,"," CALL L567D CALL L567B POP HL PUSH HL XOR A CALL L5640 ;print slots free CALL w5769 ;print " Free Slot" POP HL CALL L5AEF L5AEA LD A,#0D w5AEC JP L567D L5AEF DEC HL LD A,H OR L RET Z LD A,"s" JR w5AEC ;make it plural unless only 1 file L5AF7 CALL L5AEA ;print directory header CALL w57A1 ;print disc name CALL L72AB ;get BC=len, HL=start of path data LD B,C CALL L6F9A ;print B from HL CALL L5AEA JR L5AEA L5B09 LD HL,#0000 LD (L410E),HL ;zero "sectors used" counter LD (L421A),HL ;zero "files on disc" counter LD (L421C),HL ;zero "files in dir" counter RET L5B16 CALL L4812 LD HL,#A000 LD (L412C),HL ;init buffer ptr LD A,#02 JP L4A18 ;simple dir to screen buffer L5B24 CALL L49DB ;get HL=free sects, DE=free slots LD C,A ;tracks to A LD A,(dvar+16) LD B,A CALL L5FDB ;CY if not ram disc LD A,C BIT 7,A JR Z,w5B3A ;JR if single sided JR C,w5B39 ;JR if normal disk SUB #30 ;e.g 130->82, 168->120 DEFB #FE ;dummy CP A,#87 w5B39 ADD A,A ;*2 for double-sided normal. 208->160, 168->80 w5B3A SUB B ;number of non-directory tracks LD HL,#0000 LD B,#0A ;10 sects/trk LD D,H LD E,A w5B42 ADD HL,DE ;calc sectors for data DJNZ w5B42 LD A,(dvar+16) CP #05 JR C,w5B4D INC HL ;allow for unused t4/s1 giving extra space if DTKS 5 or more w5B4D LD DE,(L410E) AND A SBC HL,DE PUSH HL ;free sects LD A,(dvar+16) LD C,A ADD A,A ;*2 ADD A,A ;*4 ADD A,C ;*5 (5-195) LD L,A LD H,#00 ADD HL,HL ;*10 LD A,C CP #05 JR C,w5B66 ;JR if 4-track dir DEC HL ;allow for 2 unusable t4/s1 entries w5B66 ADD HL,HL ;*20 LD DE,(L421A) ;files on disc AND A SBC HL,DE ;all slots-files=free slots EX DE,HL POP HL RET ;entry: D=strings to sort, HL=first string w5B71 LD BC,#000A ;name len LD A,C DEFB #FE ;dummy CP #D9 t5B76 EXX ;A=len to sort on, BC=string len, DE=no. of strings, HL=start DEC A LD (L5B98+1),A ;len to match on after 1st PUSH DE ;files to sort PUSH HL ;start w5B7D PUSH DE ;files PUSH DE EXX POP BC ;elements to sort counter INC C DEC C JR Z,w5B86 ;eg count #0100 left alone INC B ;count #0106->#0206 so MSB/LSB cnt ok w5B86 EXX PUSH HL ;start of current el. L5B88 LD D,H ;entry: BC"=strings to examine LD E,L ;HL=top of list (current max), BC=str. len w5B8A LD A,(DE) w5B8B ADD HL,BC EXX DEC C JR Z,w5BAA w5B90 EXX CP (HL) JR C,w5B8B ;if (HL) lower than max, no new max - loop JR NZ,L5B88 PUSH HL PUSH DE ;save starts of both strings L5B98 LD B,#00 ;self-mod. 9 chars left to match on, usually w5B9A INC DE ;max ptr - in common memory INC HL LD A,(DE) CP (HL) ;compare equivalent letters in each string JR NZ,w5BA2 ;exit if mismatch found DJNZ w5B9A ;loop, matching up to B' chars w5BA2 POP DE POP HL ;get back starts of both strings LD B,#00 JR C,w5B8A ;either pick up old max first letter JR L5B88 ;or reload DE with new max ptr, as needed w5BAA DJNZ w5B90 ;dec MSB EXX ;got max string POP HL ;HL pts current el., DE to max LD B,C w5BAF LD A,(DE) ;swop top of list (HL) with max (DE) EX AF,AF' LD A,(HL) LD (DE),A EX AF,AF' LD (HL),A INC HL INC DE DJNZ w5BAF POP DE ;elements to sort counter DEC DE LD A,D OR E JR NZ,w5B7D POP HL POP DE RET w5BC2 LD A,(dvar+8) ;get in B number of columns for directory LD B,A AND A RET NZ ;RET if fixed number else determine according to window width CALL L4F17 DEFW #5A56 ;WINDRHS/LHS in C/B LD A,C SUB B INC A ;window width (normally 32, 64 or 85) LD B,#01 SUB #0B RET C INC A DEC B w5BD7 INC B ;count names that will fit across current window SUB #0B ;name len, inc space JR NC,w5BD7 RET w5BDD CALL L4F00 ;OVER option CP #A6 ;OVER RET NZ w5BE3 CALL L4FB6 JR L5BFA w5BE8 CALL L4F00 ;RENAME/ERASE DIR option w5BEB CP #90 ;"DIR" RET NZ CALL L4FC8 JR L5BFA ;skip "DIR" L5BF3 SUB "?" ;allow "?" to mean "all files" RET NZ DEC A LD (dvar+17),A ;cdirt=#ff L5BFA JP L4F00 ;skip "?" k5BFD CALL w5BDD ;ERASE, erase a file CALL w5BEB CALL L5893 CALL L71BC L5C09 CALL L5D3F JR Z,w5C11 ;JR if flag=erase file, not dir JR NC,L5C09 ;skip erase if not dir type AND A ;NC w5C11 JR C,L5C09 ;skip rename if dir type LD A,(HL) CALL L4FE6 JR NZ,w5C1D ;JR if "ERASE OVER" BIT 6,A JR NZ,w5C4C ;JR if protected w5C1D CALL L5C5B JR NZ,L5C09 ;JR if "?" and "N" CALL L4FF8 JR Z,w5C45 ;JR if erase file, not dir LD BC,#00FA ADD HL,BC LD A,(HL) LD (dvar+18),A ;set temp dir to subject of erasure ;(this is EXX version, moved to cdirt by EXDAT) CALL L60C4 ;save current file details LD L,"*" LD (L413A+1),HL ;H cannot be "." (#2E) so name is "*"+not "." LD A,#10 ;find file, ignore type CALL L4A18 ;find any file in this directory JP Z,w5059 ;"directory not empty" if a file found CALL L60C4 ;orig CDIRT and name back CALL L5CFB ;load and point to dir file entry again w5C45 LD (HL),#00 CALL L44B4 JR L5C09 w5C4C CALL L4CEC CALL L4FC2 ;"tried to erase protected file" JR L5C09 w5C54 CALL L5C5B ;optional handler for erase, protect and hide RET NZ ;ret if "?" option and LD (HL),A ;erased/protected/hidden JR w5C9C L5C5B CALL L4FB0 ;"got one" CALL L500A RET Z ;ret if not "?" option PUSH AF PUSH DE PUSH HL CALL w57D9 ;cmd name CALL w5806 ;file name, Y/N/A/E, key. Z if yes or all POP HL POP DE POP BC LD A,B RET ;Z if yes w5C70 INC H ;Z if directory OK DEC HL DEC HL LD A,(dvar+17) CP #FF RET Z ;RET if "match any" CP (HL) RET k5C7B CALL w5BE8 ;RENAME, rename a file CP #8E ;"TO", skip any "dir", set FLAG4 JR NZ,w5C9F CALL L604D CALL L4ECB ;rename disk CALL L71BC LD DE,#0001 CALL L44EA CALL L4CD9 LD B,#FF CALL L4E86 CALL L54F5 ;copy name, new rnd no. w5C9C JP L44B4 w5C9F CALL L5883 CALL L58A3 CALL L5D07 ;copy 2nd name to template area LD A,(L4136) ;first file drive CALL L46EF ;so e.g. rename "D2:ASD" to "FROG" OK L5CAE CALL L5CF0 ;refresh buffer CALL L5D3F ;find 1st name file - abort if not found JR Z,w5CB9 ;JR if flag= rename file, not dir JR NC,L5CAE ;skip rename if not dir type AND A ;NC w5CB9 JR C,L5CAE ;skip rename if dir type CALL L5C5B JR NZ,L5CAE ;JR if and PUSH HL CALL L60C4 ;first file name to NSTR2 POP HL CALL w619C ;copy loaded name to NSTR1, use template on it CALL L4E7F JP Z,L504D ;"file name used" CALL L5CFB ;pt to first file entry again PUSH DE ;t/s PUSH HL INC H DEC HL DEC HL ;sub dir tag LD A,(dvar+17) ;sub dir value for 2nd name LD (HL),A ;set sub dir tag POP DE INC DE ;name posn LD HL,L413A+1 LD BC,#000A LDIR POP DE ;t/s CALL L44B4 CALL L4FB0 ;"done one" CALL L60C4 JR L5CAE L5CF0 CALL L4FEC RET Z ;RET if sndfl not used yet w5CF4 LD DE,(L4124) JP L44EA ;ensure dram contains dir entries in case 2nd one wanted L5CFB CALL w5CF4 ;pt to svtrs entry LD A,(L4122) LD (IX+#0E),A JP L4E84 L5D07 LD HL,L4156+1 ;copy name from 2 to 3 to act as name template LD DE,L416E+1 LD BC,#000E LDIR RET k5D13 LD A,#40 ;PROTECT, protect routine DEFB #21 ;dummy LD HL,#803E k5D16 LD A,#80 ;HIDE, hide file routine LD (L4135),A CALL L4F00 CP #89 ;OFF CALL Z,w5BE3 ;set F1, skip CALL L5893 CALL L71BC w5D29 CALL L5D3F LD A,(L4135) LD C,A CPL LD B,A LD A,(HL) AND B CALL L4FE6 JR NZ,w5D3A OR C w5D3A CALL w5C54 JR w5D29 L5D3F CALL L5D60 ;from ERASE, HIDE, PROTECT JR C,w5D53 ;JR if got one POP HL ;junk return CALL w4FE0 RET NZ ;OK if done at least 1 file CALL L4FF2 ;set by ERASE. always 0 from COPY JP NZ,L505F ;"protected file" L5D4F CALL L5097 ;"file not found" DEFB 107 ;get info for ERASE/RENAME ;return CY if dir type, Z if FLAG4="do files", NZ if it ="do dirs" w5D53 CALL L4E84 LD A,(HL) AND #1F ;type SUB #15 CP #01 ;CY if dir type JP L4FF8 ;F12.Z80 ;select a file in the directory, keeping place in directory so later ;parts can be looked at later. ;DRAM is unchanged and does not need re-reading unless next sector needed L5D60 CALL L4FEC JR NZ,L5D9E CALL L4FBC CALL L4CCF XOR A LD (IX+#04),A ;FDHR flags=0 for CHKNM LD (IX+#0E),A ;1st entry CALL t4692 CALL L44EA ;t0/s1 CALL L72F0 ;set dir tks, check rand no JR w5D80 L5D7D CALL L44EA w5D80 LD (L4124),DE w5D84 CALL L4E84 LD A,(IX+#0E) LD (L4122),A LD A,(HL) AND A JR Z,w5D9B ;JR if free slot CALL w5C70 CALL Z,L4BC8 JR NZ,L5D9E ;JR if not matched SCF RET w5D9B INC HL OR (HL) RET Z ;RET if all used directory handled. NC L5D9E LD A,(L4122) LD (IX+#0E),A DEC A JR Z,w5DAF ;JR if ptr was to 2nd entry CALL L4CD9 INC (IX+#0E) JR w5D84 ;deal with 2nd entry w5DAF LD DE,(L4124) CALL L5521 JR NZ,L5D7D INC D LD HL,dvar+16 LD A,D CP #04 JR NZ,w5DC2 INC E ;skip t4,s1 w5DC2 CP (HL) JR C,L5D7D RET L5DC6 CALL L5DCE ;separator report routine RET Z L5DCA CALL L5097 DEFB 29 L5DCE CP "," ;the separator subroutine JR Z,L5DD9 CP ";" JR Z,L5DD9 CP #22 RET L5DD9 CALL L4F00 ; LD (SVA),A ;remarked in original ; XOR A ; LD A,(SVA) CP A RET ;evaluate parameters in syntax for READ AT/WRITE AT D,T,S,ADDR L5DDE LD C,#87 ;AT CALL L4EF9 CALL L5FF9 ;get drive number CALL L5DC6 ;get track number CALL L6132 PUSH BC ;C=trk if run time CALL L5DC6 ;get sector number CALL L6132 POP DE ;E=trk LD B,E ;BC=t/s PUSH BC CALL L5DC6 ;get address CALL w6176 ;Z if syntax PUSH AF PUSH HL ;AHL=addr CALL L4EB4 LD BC,#0001 ;default=1 sect JR Z,L5E12 ;JR if no "sectors" param CALL L612F ;number of sectors JR Z,L5E12 DEC HL LD A,H CP #04 JP NC,L5F12 ;allow #0000-#03FF in DECED, #0001-#0400 in orig, BC= 1-1024 sectors L5E12 POP HL POP AF ;AHL=addr, NZ if run CALL NZ,w64BC ;set/check addr in AHL, sectors in BC POP HL LD (L41E0),HL ;t/s CALL L4ECB LD A,(L4136) LD (L41DD),A RET L5E25 LD HL,L4149 ;save header information LD DE,L7C13+211 LD B,#09 w5E2D LD A,(HL) LD (DE),A CALL t6CB5 INC HL INC DE DJNZ w5E2D RET L5E37 LD A,(HL) ;remove floating point numbers CP #0E JR NZ,w5E44 LD BC,#0006 CALL L7BB4 ;jump to DEFW #0163 ;JRECLAIM w5E44 LD A,(HL) INC HL CP #0D JR NZ,L5E37 RET k5E4B CALL L4F00 ;LOAD, load command (failed normal syntax) CALL L4EBD ;\char after LOAD CALL Z,L5E37 ;remove fp forms from HL on if syntax time CALL L6132 JP Z,L4ECB LD (L4218),HL ;file num can be 2 bytes LD A,L LD (L4137),A CALL L4D75 w5E64 LD A,(L41AD) CP #14 JR NZ,L5E9A ;JR if not SCREEN$ or former type 5 CALL L500A JR Z,L5E9A ;JR if SCREEN$ CALL L44E6 ;48k snapshot is found LD BC,#0300+250 LD HL,L4106 w5E79 IN A,(C) LD (HL),A INC HL INC C DJNZ w5E79 ; IN A,(250) ;remarked in original ; LD (SNPRT0),A ; IN A,(251) ; LD (SNPRT1),A ; IN A,(252) ; LD (SNPRT2),A LD A,#04 OUT (#FB),A ;ZX "SCREEN" at #8000 OUT (#FC),A ;display page 4, SCREEN MODE 1 LD HL,#8000 LD DE,#4000 LD A,#02 LD (L4150),A CALL L475A ;load 48kB to ZX image CALL t4617 JP L5316 L5E9A CP #10 JR NZ,w5EED ;JR if not BASIC CALL L500A JP NZ,L5032 ;"wrong file type" if ZX BASIC CALL L4F17 DEFW #5AA0 PUSH BC POP HL CALL L4F22 DEFW #5A9F LD (L417D+31),A LD (L417D+32),HL EX DE,HL LD C,A PUSH BC CALL L4F17 DEFW #5A94 PUSH BC POP HL CALL L4F22 DEFW #5A93 POP BC DEC HL BIT 7,H JR NZ,w5ECC DEC A w5ECC PUSH BC PUSH DE CALL L5EFF PUSH AF EX DE,HL LD A,C CALL L5EFF EX DE,HL LD C,A POP AF AND A SBC HL,DE SBC A,C POP DE POP BC CALL L7462 LD (L417D+34),A LD (L417D+35),HL XOR A LD (L417D+15),A w5EED LD IX,#4B00 CALL L6231 CALL w6284 LD HL,L7FF0-1 SET 6,(HL) ;ensure ROM1 on on exit from dos by altering port 251 status on stack JP w4ED7 ;now jump to ROM1 to load is OK L5EFF CALL L5F05 ;get 19-bit number AND #07 RET L5F05 RLC H ;get 20-bit number RLC H RRA RR H RRA RR H AND #0F RET L5F12 CALL L5097 DEFB 30 k5F16 CALL L64CB ;FORMAT, write format on disc LD A,#04 LD (dvar+16),A ;default tracks/dir XOR A LD (L4212),A ;default tks/disc CALL L4F00 CP #8E ;TO JR Z,w5F6B ;JR if 'FORMAT TO "NAME"' CALL L4EB4 JR Z,w5F7D CALL L6050 CP "," JR NZ,w5F5C ;JR if 'FORMAT "NAME" TO "NAME"' CALL L612F JR Z,w5F42 LD A,B AND A JR NZ,L5F12 LD A,C LD (dvar+16),A w5F42 CALL L4F06 CP "," JR NZ,L5F82 CALL L612F ;total tks of ram disc JR Z,L5F82 LD A,B AND A JR NZ,L5F12 LD A,C LD (L4212),A ;tks/disc AND A JR NZ,L5F82 L5F59 JP L5F12 w5F5C CP #8E ;TO JR NZ,L5F82 CALL L609C ;second name of two CALL L4ECB CALL L71BC ;first JR w5F71 w5F6B CALL L609C ;second (only) name CALL L4ECB w5F71 CALL L46D3 ;EXDAT and check drive CALL L71BC ;second name CALL L46D3 w5F7A JP w5355 w5F7D CALL L4ECB JR w5F88 L5F82 CALL L4ECB CALL L71BC ;first name w5F88 LD A,(dvar+16) LD C,A CP 40 JR NC,L5F59 LD B,#04 ;low DTK limit LD A,(L4136) CP #03 JR C,w5FA7 LD B,#01 ;allow 1 or more dir tks for ramd LD A,C AND A JR Z,L5FCD ;JR if e.g. FORMAT"D3:",0 - erase ram disc LD A,(L4212) AND A JR Z,L5F59 ;e.g. FORMAT "D3:",5,0 illegal as is FORMAT "D3:",5 JR w5FAD w5FA7 LD A,(L4212) AND A JR NZ,L5F59 ;e.g. FORMAT "D1:",5,10 is illegal. only FORMAT "D1",4 etc OK w5FAD LD A,C CP B JR C,L5F59 ;allow 4-39 dir tracks (80-780 files) if real disc or 1-39 if ramdisc LD A,(L4212) AND A JR Z,L5FCD ;JR if real disc format LD C,A LD B,159 ;limit LD A,(dvar+16) SUB C JR NC,L5F59 ;total tks must be >DTKS ADD A,C SUB #04 JR NC,w5FC7 ;JR if dir is normal or large ADD A,B LD B,A ;lower limit - 3 DTK=158, 2=157, 1=156 w5FC7 LD A,C SUB #02 CP B JR NC,L5F59 ;DTKS=1, tot tks 2-157 OK, etc. L5FCD LD A,(L4136) CP #03 JR C,w5F7A JP w74C1 ;format ramdisc L5FD7 XOR A LD (L4111),A L5FDB LD A,(L7C0B) ;test if ram disc - NC if so CP #03 RET w5FE1 CP #2A ;evaluate drive no. or file name (used by dir) JR Z,w6000 ;exit: CY if drive CALL L7BB4 ;jump to DEFW #011E ;JEXPTEXPR JR Z,w5FF2 ;JR if string CALL w6137 ;unstack number if running SCF ;"drive" JR L6015 ;RET, or set drive w5FF2 CALL w610A ;unstack string if running SCF CCF ;NC="name" JR w6053 ;RET, or EVNAME L5FF9 CALL L4F06 ;evaluate drive number - WRITE AT *,T,S,A allowed CP "*" JR NZ,w6012 w6000 CALL L4F00 PUSH AF CALL w64DB ;default number LD A,(L7C0B) LD C,A POP AF ;char after "*" CALL L4EBD SCF ;"number" JR L6015 w6012 CALL L6132 L6015 RET Z PUSH AF LD A,C CALL L6020 ;convert drive number in A to A CALL L6578 ;set drive, CDIRT POP AF RET L6020 DEC A CP #07 INC A JR NC,w6032 ;JR if not 1-7 - leave alone PUSH BC PUSH HL LD C,A LD B,#00 LD HL,dvar+111-1 ;drive number pretend table ADD HL,BC LD A,(HL) POP HL POP BC w6032 LD (L4136),A RET w6036 LD BC,(L41E2) LD DE,(L41E0) SET 7,D RES 6,D ;buffer addr adjust #4F10->#8F10 XOR A LD B,A LD (L411E),A ;page 0 JR L6054 L6049 CALL L5097 DEFB 18 ;invalid file name L604D CALL L4F00 L6050 CALL L6105 ;evaluate file name, exit: Z/NZ for syn/run, A=char after w6053 RET Z ;RET if syntax time L6054 PUSH AF LD A,C OR B JR Z,L6049 ;"invalid file name" if len 0 LD HL,79 SBC HL,BC JR C,L6049 ;error if too long IN A,(#FB) PUSH AF PUSH BC ;real len LD HL,#000E SBC HL,BC JR NC,w606E LD BC,#000E w606E LD HL,L413A LD A,#0F w6073 LD (HL),#20 INC HL DEC A JR NZ,w6073 LD HL,L413A+1 EX DE,HL LD A,(L411E) AND #1F OUT (#FB),A PUSH HL LDIR POP HL POP BC ;real len LD A,C CALL L4F38 DEFW #4F60 ;store real len LD DE,L4F10 ;??? CALL L7BB4 ;jump to DEFW #008F ;LDIR:RET, to buffer in sys page POP AF OUT (#FB),A POP AF RET L609C CALL L4F00 ;evaluate second file name w609F CALL L60A5 ;\exit: Z/NZ for syntax/run. A corupt CALL L6050 L60A5 CALL L60C4 ;swop long names in sys page buffer as well as other data IN A,(#FB) PUSH AF PUSH BC PUSH DE PUSH HL XOR A OUT (#FB),A LD BC,#0058 LD HL,#8F10 LD DE,#8F68 CALL L60F6 POP HL POP DE POP BC POP AF OUT (#FB),A RET L60C4 PUSH AF PUSH BC PUSH DE PUSH HL LD HL,(dvar+17) LD A,H LD H,L LD L,A LD (dvar+17),HL ;swop main and exx directories LD BC,#001C LD DE,L4136 LD HL,L4152 CALL L60F6 POP HL POP DE POP BC POP AF RET L60E2 CALL L60C4 LD A,(L420A) EX AF,AF' LD A,(dvar+16) LD (L420A),A EX AF,AF' LD (dvar+16),A ;swop DTKS/DTKSX CALL L59CC ;get HL=RPT, DE=paged in buffer, BC=#0306 L60F6 LD A,(DE) ;swop BC at HL/DE EX AF,AF' LD A,(HL) EX AF,AF' LD (HL),A EX AF,AF' LD (DE),A INC DE INC HL DEC BC LD A,B OR C JR NZ,L60F6 RET L6105 CALL L7BB4 ;jump to, evaluate string expression DEFW #011B ;JEXPTSTR w610A CALL L4EBD RET Z PUSH AF CALL L7BB4 ;jump to DEFW #0124 ;JSTKFETCH LD (L411E),A POP AF RET L6119 CALL L4F00 ;evaluate stream information L611C CALL L6132 RET Z PUSH AF LD A,C CP #11 JR NC,w612B LD (L4138),A POP AF RET w612B CALL L5097 DEFB 21 ;"invalid stream number" L612F CALL L4F00 L6132 CALL L7BB4 ;jump to, evaluate number routine DEFW #0118 ;JEXPT1NUM w6137 CALL L4EBD RET Z L613B PUSH AF CALL L7BB4 ;jump to DEFW #0121 ;JGETINT POP AF RET w6143 CALL L7BB4 ;jump to, evaluate big number routine DEFW #0118 ;JEXPT1NUM CALL L4EBD RET Z PUSH AF IN A,(#FB) PUSH AF IN A,(#FA) INC A CALL L3FDF ;DOS at #8000 too CALL L7BB4 ;jump to DEFW w6168+up POP AF OUT (#FB),A CALL L613B PUSH HL ;X div 64k CALL L613B ;BC=X mod 64k POP DE ;DE=X div 64k POP AF RET w6168 RST #28 ;calculator at #A168 DEFB #25 ;DUPlicate DEFB #27 ;FIVELIT DEFB #91,0,0,0,0 DEFB #D5 ;STOre5 DEFB #08 ;MODulo DEFB #06 ;SWOP DEFB #DD ;ReCaL5 DEFB #09 ;IntegerDIVision DEFB #34 ;EXIT2 w6176 CALL L7BB4 ;jump to, evaluate address routine DEFW #0118 ;JEXPT1NUM CALL L4EBD RET Z CALL L7BB4 ;jump to DEFW L3F8C ;unstlen, AHL=pages/ addr mod 16k SET 7,H ;HL=offset DEC A LD C,#00 INC C ;NZ RET ;test for letter w618B CP #41 ;check for alpha char CCF RET NC CP #5B RET C CP #61 CCF RET NC CP #7B RET ;transfer file names in copy ;e.g. COPY "*" TO "*" (NSTR3) with "FROG" (NSTR1) loaded gives "FROG" in NSTR1 ; COPY "*" TO "?X.BIN" with "AB.BIN" loaded gives "AX.BIN" w6199 LD HL,L41AD w619C LD DE,L413A ;called by RENAME LD BC,#000F LDIR ;NSTR1=data from disc LD DE,L413A+1 LD HL,L416E+1 LD B,#0A w61AC LD A,(HL) CP "*" JR Z,w61BB CP "?" JR Z,L61B6 ;leave chars in tgt opposite "?" alone LD (DE),A ;tgt=src unless src="?" L61B6 INC HL INC DE DJNZ w61AC RET w61BB INC HL LD A,(HL) CP "." RET NZ ;RET if src="*???" unless "*." w61C0 LD A,(DE) CP "." JR Z,L61B6 INC DE DJNZ w61C0 ;look for "." in tgt, then match extensions RET n61C9 CALL L4E46 LD B,#DC CALL L4E86 LD BC,#0021 LDIR LD HL,L41AD LD DE,L417D LD C,#30 LDIR LD B,#0D CALL L4E86 LD D,(HL) INC HL LD E,(HL) RET ;G1.Z80 ;hook code routines L61E9 CALL L61EF ;input a header from IX JR NZ,w6205 RET L61EF CALL w62A1 CALL w623B LD A,(L4139) CP "D" RET ;input a header from IX, allow device D/T/N. returns NC if D, CY if T/N L61FB CALL L61EF RET Z CP "T" JR Z,w6208 CP "N" w6205 JP NZ,L46D9 ;invalid device w6208 CALL L4F38 DEFW #5BB7 ;temp device LD A,(L4136) CP #08 JR NC,w6216 ;JR if no sensible tape speed specified LD A,#70 ;default tape speed (irrel for net) w6216 CALL L4F38 DEFW #5BB8 ;temp speed LD HL,L413A+1 LD A,(HL) SUB #20 JR NZ,w6229 DEC A ;A=#FF LD (L417D+1),A ;null name JR L6231 w6229 LD DE,L417D+1 LD BC,#000E LDIR L6231 LD BC,#0000 ;output UIFA to ROMUIFA LD DE,L417D ;copy to ROM hdr PUSH IX JR w629D ;ends with SCF w623B CALL L43E4 ;convert new hdr to old LD HL,L417D+1 CALL L64F6 LD A,(L7FFF) ;entry LRPORT value on stack BIT 6,A CALL NZ,w71C5 ;IF ROM1 used HGTHD then use long name LD A,(L417D) LD (L413A),A LD (L4149),A LD A,(L417D+31) LD (L4151),A ;once LD HL,(L417D+32) LD (L414C),HL LD A,(L417D+34) AND #1F LD (L4150),A LD HL,(L417D+35) RES 7,H LD (L417D+35),HL LD (L414A),HL RET t6275 PUSH IX ;hook to open a file for LOAD/VERIFY - IX=hdr CALL L61FB JR C,w62C2 ;JR if tape or net CALL L46EC CALL L4D75 POP IX w6284 PUSH IX ;output DIFA to ROMDIFA (DIFA to IX+80) POP HL PUSH HL LD BC,#0024 ADD HL,BC ;IX+#24 CALL L4F8D ;MSB of len mod 16k (hdr) to A LD HL,L41AD+#24 XOR (HL) AND #80 ;take bit 7 from hdr (sometimes hi, sometimes lo) XOR (HL) ;verify depends on equality! LD (HL),A LD DE,L41AD LD BC,#0050 w629D POP HL ;output a header, was IX ADD HL,BC ;NC. dest in HL=IX or IX+80, src in DE=DIFA or UIFA JR w62A8 w62A1 LD DE,L417D PUSH IX POP HL ;src=HL, dest=UIFA SCF w62A8 BIT 7,H IN A,(#FB) LD BC,#00FB JR NZ,w62B7 ;JR if no paging required SET 7,H RES 6,H OUT (C),B ;system page w62B7 JR C,w62BA EX DE,HL w62BA LD C,#30 LDIR OUT (#FB),A SCF ;for TXINF RET w62C2 POP HL ;junk LD HL,(L4104) INC HL INC HL INC HL INC HL INC (HL) ;stored SP LSB (even) INC (HL) ;discard one addr - RET to load file LD E,#03 ;LOAD/MERGE VERIFY entire file from T/N JP L4ED9 L62D1 CALL L4CCF CALL w642E LD HL,(L41DE) LD (L414C),HL ;start LD A,(L41E2) ;CDE was len LD C,A LD (L4150),A LD DE,(L41E0) RES 7,D LD (L414A),DE RET L62EF LD A,(L4139) CP "N" RET NZ POP HL ;junk RET addr CALL L7AEE EXX ;start, len to HL, CDE for pass out RET t62FB OUT (#FB),A t62FD LD BC,m4BE0 ;verify file already opened by HGTHD. HL=start, CDE=len, paged in. CALL L62EF CALL L62D1 LD (IX+#0D),#09 L630A LD A,D OR E JR NZ,w6317 LD A,C AND A JP Z,t4617 DEC C LD DE,#4000 w6317 CALL t6D34 CP (HL) JP NZ,w502F ;verify failed DEC DE INC HL LD A,H CP #C0 JR C,L630A CALL L3FF2 JR L630A t632A CALL L61FB ;get header, allow devices D/T/N JR C,w6358 ;JR if T/N CALL L46EC IN A,(#FB) LD (L4130),A LD A,(L417D+31) CALL L3FDF CALL L4C27 JR C,w6352 ;JR if "OVERWRITE?" and CALL L5E25 LD HL,(L414C) LD DE,(L414A) CALL L4840 CALL L4D09 w6352 LD A,(L4130) OUT (#FB),A RET w6358 LD E,#02 ;save entire file to tape or net JP L4ED9 L635D CALL L5FDB RET NC ;RET if ram disc LD A,(dvar+29) INC A w6365 PUSH AF XOR A CALL w4685 ;delay about 0.25 sec POP AF DEC A JR NZ,w6365 RET t636F CALL L613B ;get DVAR param LD HL,dvar ADD HL,BC ;add DVAR base IN A,(#FA) AND #1F ADD A,#02 ;A=dos page+1 ADD HL,HL ADD HL,HL ;left justify 16k offset - junk upper bits LD B,#96 ;init exponent L6380 DEC B ADD HL,HL RLA BIT 7,A JR Z,L6380 RES 7,A ;res sgn bit LD E,A LD A,B ;exponent L638B LD D,H LD C,L LD B,#00 JP L7A95 w6392 LD A,#02 DEFB #21 ;dummy LD HL,#013E t6395 LD A,#01 DEFB #FE ;dummy CP #AF t6398 XOR A PUSH IX LD C,#FB IN B,(C) PUSH BC PUSH AF ;0 if eof, 1 if ptr CALL w6D43 ;AHL=ptr POP DE DEC D JR Z,L63BA ;JR if ptr DEC D JR NZ,w63B0 CALL L6F1A ;get file len in AHL JR L63BA w63B0 CALL L6D1A LD HL,#0000 LD A,H JR NZ,L63BA INC HL ;HL=1, eof=true L63BA POP BC OUT (C),B POP IX L63BF LD B,A ;stack AHL as a number OR H OR L JR Z,L63C9 ;zero is a special case LD A,B LD B,#98 ;init exponent JR L6380 L63C9 LD A,H ;stkhl on FPCS. used by eof LD H,L LD L,A XOR A LD E,A JR L638B d63D0 DEFB #01,#FF,#FF,"D",#10 DEFM "AUTO* " ;9 spaces DEFB #00 DEFW #FFFF,#FFFF,#FFFF,#FFFF t63EC CALL L63F8 ;look for an AUTO file JP NZ,w503B ;error if not found w63F2 CALL w4D83 JP w5E64 L63F8 LD A,#95 ;load tok CALL L4F38 DEFW #5B74 LD HL,d63D0 LD DE,L4136 LD BC,#001C LDIR CALL L64D3 CALL L46EC LD A,#10 ;"look for name" JP L4A18 t6415 CALL L63F8 RET NZ ;RET if not found JR w63F2 t641B CALL L61E9 ;hook open file CALL L46EC CALL L4C27 JP NC,L5E25 ;JP if not "OVERWRITE?"+ RET t6428 CALL L61E9 CALL L4D75 w642E CALL L44E6 LD B,#09 ;load header information w6433 CALL t6D34 DJNZ w6433 RET t6439 CALL L61E9 CALL L46EC CALL L4E7F JP NZ,L5D4F LD (HL),#00 JP L44B4 ;write at a track and sector k644A CALL L5DDE ;WRITE JR t6460 ;read at a track and sector k644F CALL L5DDE ;READ JR t6457 t6454 CALL L64B1 ;hook read 1 sector at DE t6457 LD IY,L44EA ;hook far read many sectors at DE JR w646D t645D CALL L64B1 ;hook write 1 sector at DE t6460 CALL L46DD ;hook far write many sectors at DE CALL L4718 ;\convert HKA and check drive CALL L4495 LD IY,L44B4 w646D IN A,(#FB) PUSH AF XOR A LD (L420D),A ;so ram disc keeps track unfiddled CALL L46DD CALL L4CCF LD HL,(L41DE) ;addr LD BC,(L410A) ;sectors LD A,(L41E2) ;addr page AND #1F OUT (#FB),A LD DE,(L41E0) ;t/s w648C PUSH BC CALL L7603 LD (L7C0F),HL CALL #0006 LD BC,(dvar+37) ;usually #0200 ADD HL,BC CALL L5521 JR NZ,w64A5 PUSH HL CALL L545C POP HL w64A5 POP BC DEC BC LD A,B OR C JR NZ,w648C POP AF OUT (#FB),A JP L4CCF ;normal buf again L64B1 LD HL,(L41DE) ;calculate address section XOR A CALL L7462 DEC A ;page 0-2 for sects B/C/D LD BC,#0001 ;1 sect to do w64BC LD (L41E2),A ;called by EVPRM. AHL=addr, BC=sects INC A JP Z,L5F12 ;#0000-#3FFF illegal addr LD (L41DE),HL ;offset LD (L410A),BC ;sectors to do t64CA RET ;dummy hook L64CB LD A,"*" ;called by DIR, DIR$ LD (L413A+1),A ;null name LD (L413A+2),A ;ensure not "." if DIR$ L64D3 CALL L4F22 ;get default letter and number DEFW #5A06 LD (L4139),A w64DB CALL L4F22 ;get default number DEFW #5A07 AND A JR Z,w64E7 CP #08+1 JR C,w64EA ;JR if legal drive - else prob. T speed w64E7 LD A,(dvar+15) ;use "other" default w64EA PUSH HL LD (dvar+15),A CALL L6020 ;convert drv num CALL L6578 POP HL RET L64F6 CALL L64D3 ;evaluate file information at (HL). 14 chars if HL=NSTR1+1 LD (L7C05),HL LD A,(HL) CP #FF JR NZ,w6508 ;JR unless null name LD A,"T" ;LOAD "" becomes LOAD "T:" LD (HL),A INC HL LD (HL),":" DEC HL w6508 AND #DF n650A LD C,A ;check for first digit INC HL LD A,(HL) CP ":" JR Z,w6553 SUB "0" CP #0A JR NC,L655A LD D,A ;check for second digit, save first digit LD A,C ;first char CP "D" INC HL LD A,(HL) ;char after digit JR NZ,L653B ;JR if not "D1XXXXX" CP ":" JR NZ,w652A ;JR if not "D1:XXXX" CALL L6583 JR NZ,L654F ;JR if not "D1: " JR w6533 w652A CP " " JR NZ,L653B ;JR if not e.g. "D2 XXXXX" CALL L6583 JR NZ,L655A ;JR if not "D1 " w6533 LD (HL),":" INC HL LD (HL),"*" ;e.g. "D1" or "D1:" become "D1:*" DEC HL ;pt to ":" JR L654F L653B SUB #30 CP #0A JR NC,L655A ;JR if 2nd digit not found LD E,A ;evaluate 2 digit number LD A,D ADD A,A ADD A,A ADD A,D ADD A,A ADD A,E LD D,A INC HL LD A,(HL) ;check for ":" CP ":" JR NZ,L655A L654F LD A,D CALL L6020 w6553 LD A,C LD (L4139),A ;letter INC HL ;skip ":" JR w655D L655A LD HL,(L7C05) w655D LD DE,(L7C05) ;file name start AND A SBC HL,DE LD (L4216),HL ;store no. of chars trimmed off front (0-4) ADD HL,DE LD BC,#000A LD DE,L413A+1 LDIR ;left justify name (or copy to NSTR1+1) LD B,#04 CALL L4E53 ;pad with 4 spaces...not needed.. LD A,(L4136) L6578 LD (L7C0B),A CALL L72E0 ;get CDIRP addr LD A,(HL) LD (dvar+17),A RET L6583 LD B,#0B ;check for 11 spaces PUSH HL w6586 INC HL LD A,(HL) CP " " JR NZ,w658E DJNZ w6586 w658E POP HL RET ;MOVE.Z80 k6590 CALL L6705 ;MOVE, move command CP #8E ;"TO" JP NZ,L5DCA ;"nonsense" CALL L60C4 CALL L6705 CALL L60C4 CALL L4ECB CALL L4FBC ;"MOVE" XOR A OUT (#FB),A LD A,#BF LD (L4137),A CALL L671C ;open "IN" temp channel - get NSTR1=addr JP C,L6D7E ;if OPMOV returns C when creating "in", it ;was due to a non-open stream being used LD A,(L4137) ;drive no. for 2nd channel is same as first?? LD (L4156),A CALL L60C4 LD A,#DF LD (L4137),A LD IX,L7C00 LD HL,L7C0C RES 4,(HL) ;so OFSM normal (previous OPMOV might have set it) CALL L671C ;open "out" temp channel JR NC,w65FE ;JR if OK, if "OVERWRITE?" and , or stream not open, cont PUSH AF ;Z if strm not open LD IX,(L4156) ;addr of first channel (in NSTR1 after EXDAT) LD BC,#4000 ADD IX,BC LD A,(IX+#04) CP "D"+#80 JR NZ,w65E8 ;only reclaim first channel if it is temp "D" CALL L6B59 CALL L65ED w65E8 POP AF JP Z,L6D7E ;stream not open error RET L65ED LD C,(IX+#09) ;reclaim a channel pted to by IX in sect C LD B,(IX+#0A) PUSH BC PUSH IX POP HL CALL L7BB4 ;jump to DEFW #0163 ;JRECLAIM POP BC RET w65FE CALL L60C4 ;first chan addr in NSTR1 again CALL w66A8 JP NZ,L668B ;JR if not MOVE D to S/T/K XOR A LD (#5C3C+up),A ;not auto-list, sys page INC A LD (#5ABA+up),A ;in quotes so no keywords, sys page LD A,D AND #1F CP #0A JR Z,L668B ;JR if opentype PUSH AF LD B,#09 CALL L6655 ;junk header POP AF CP #10 JR NZ,L665D ;IF not program, suppress unprintables XOR A LD (#5ABA+up),A ;not in quotes - keywords on w6625 CALL L66C9 ;line no. MSB CP #FF JR Z,L6695 ;end now if end of prog - ignore vars PUSH AF CALL L66C9 ;line no. LSB LD HL,(L4156) LD (#9C51),HL POP HL LD L,A ;HL=line no CALL L5634 LD B,#02 CALL L6655 ;junk line len data w6640 CALL L66C9 CP #0E CALL Z,w6653 ;junk 5-byte forms PUSH AF CALL L66F0 POP AF CP #0D JR NZ,w6640 JR w6625 w6653 LD B,#06 L6655 PUSH BC CALL L66C9 POP BC DJNZ L6655 RET L665D CALL L66C9 ;move non-opentype, non-program to S/K/T, read char JR NC,L6695 ;JR if eof BIT 7,A JR Z,w6679 LD C,A LD A,(dvar+24) AND A LD A,C JR Z,w6674 ;JR if >127 to be inverted CP #FF JR NZ,L6682 JR w667F w6674 LD HL,#5A54+up LD (HL),#FF ;inverse w6679 AND #7F CP #20 JR NC,L6682 w667F LD A,(dvar+25) ;usually "." L6682 CALL L66F0 ;write printable char XOR A LD (#5A54+up),A JR L665D L668B CALL L66C9 ;read char JR NC,L6695 ;JR if eof CALL L66F0 ;write char JR L668B L6695 XOR A LD (L7C0C),A CALL L60C4 CALL L675C CALL L60C4 CALL L675C JP L677F w66A8 LD HL,(L413A) ;disc to screen? Z if so (D to S/K/P). exit with D=src file type LD BC,up+4 ADD HL,BC ;sys page is at #8000. pt to chan letter LD A,(HL) CP "D"+#80 RET NZ ;RET if disc not src LD BC,#0013-4 ADD HL,BC LD D,(HL) ;src file type LD HL,(L4156) LD BC,up+4 ADD HL,BC ;pt to chan letter LD A,(HL) CP "S" RET Z CP "P" RET Z CP "K" RET L66C9 LD HL,(L413A) ;MOVE - read char, exit: CY if got char in A, NC if eof LD (#5C51+up),HL L66CF LD HL,(#5C51+up) LD DE,up+2 ADD HL,DE ;sys page is at #8000 LD E,(HL) INC HL LD D,(HL) EX DE,HL ;HL=input address LD A,H CP #4B JR Z,w66E9 ;JR if dos LD (w66E5),HL CALL L7BB4 ;jump to w66E5 DEFW #0000 JR w66EC w66E9 CALL t6C26 w66EC RET C ;RET if got char JR Z,L66CF ;loop unless eof RET L66F0 LD HL,(L4156) ;MOVE - write char in A LD (#5C51+up),HL LD DE,up+1 ADD HL,DE LD D,A LD A,(HL) CP #4B LD A,D JP Z,t6C68 JP L567D L6705 CALL L4F00 ;evaluate a move syntax CP "#" JP Z,L6119 L670D CALL L6050 RET Z ;RET if syntax time w6711 PUSH AF CALL L71BC POP AF RET w6717 CALL w6036 JR w6711 ;open a move channel. return NSTR1=channel addr in channels (sect B) ;CY if error, (and Z if stream not open), NC if OK L671C LD A,(L4138) INC A JR Z,w6737 ;JR if not a stream DEC A CALL L6D82 LD D,A LD A,B OR C SCF RET Z ;RET if stream not open, with CY LD A,D CALL L7BB4 ;jump to DEFW #0112 ;JSETSTRM, set stream LD IX,(#9C51) JR w6756 w6737 LD A,(L4139) AND #DF CP "D" JP NZ,L5DCA CALL L46EC CALL L68F2 LD A,#01 INC A ;NZ = error not due stream not open RET C ;RET if aborted (OVERWRITE?+) LD A,(L413A) LD (L4137),A LD BC,-up ADD IX,BC w6756 LD (L413A),IX AND A ;NC=OK RET L675C LD A,(L4138) ;close a move channel INC A RET NZ ;RET if there was a stream - don't close it LD IX,(L413A) LD BC,#4000 ADD IX,BC w676A PUSH IX ;entry: IX points to channel in sect C POP HL LD DE,-up ADD HL,DE ;correct to sect B, like chans LD DE,(#5C4F+up) OR A SBC HL,DE INC HL LD (L4124),HL ;channel disp JP w6B4D L677F LD IX,(#5C4F+up) ;reclaim temporary channels LD DE,6*5+up ADD IX,DE w6788 LD A,(IX+#00) CP #0D RET Z LD A,(IX+#04) CP "D"+#80 JR NZ,w679A CALL w676A JR L677F w679A CALL L4FE6 JR Z,w67A4 ;JR if not CLEAR # CALL L65ED JR L677F w67A4 LD E,(IX+#09) LD D,(IX+#0A) ADD IX,DE JR w6788 k67AE CALL L4F00 ;BACKUP CALL L5883 ;eval file to file CALL L58A3 ;EVFILES, set single-disc flag as needed CALL L46EC LD HL,#8000 LD (L41DE),HL ;src/dest CALL L4BFD ;clear SAM LD A,#20 CALL L4A18 ;create SAM LD B,195 ;bytes in SAM LD HL,L400F+194 w67CD LD A,(HL) AND A JR NZ,w67D4 ;exit when first used map byte found DEC HL DJNZ w67CD w67D4 LD L,B LD H,#00 ADD HL,HL ADD HL,HL ADD HL,HL ;HL=sectors used LD BC,#0028 ADD HL,BC ;allow for directory tks 0-3 INC B ;NZ LD DE,#0001 LD (L41E0),DE ;start at t0/s1 w67E6 PUSH DE ;t/s to write to PUSH HL ;sects left to do CALL Z,L5845 ;prompt for src disc if 1-drive backup (Z if entry from loop) CALL L59AC LD A,B AND A JP Z,L505C ;error if no pages free LD (L41E2),DE ;HKBC=page LD L,A LD H,#00 ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL EX DE,HL ;DE=sectors free at 32/page POP HL ;left to do SBC HL,DE ;sub left to do,free PUSH HL ;new left to do, unless last pass JR C,L680B ;JR if can finish in this pass JR Z,L680B EX DE,HL ;HL=free JR w680F L680B ADD HL,DE ;HL=left to do CALL L4FB6 ;"last pass" w680F LD (L410A),HL ;IX=sects to do LD A,(L4136) LD (L41DD),A ;drive CALL t6457 ;read sects POP HL ;left to do EX (SP),HL LD (L41E0),HL ;t/s to write to next PUSH DE ;t/s reached on src CALL L583C ;prompt for dest disc if 1-drive backup CALL L60C4 LD A,(L4136) LD (L41DD),A ;drive CALL L5004 JR NZ,w6840 ;JR if not first pass LD A,(L41E2) OUT (#FB),A LD HL,#80FF CALL L54F5 ;set rnd word and name CALL L4FD4 ;"not first pass" w6840 CALL t6460 ;write sects POP HL LD (L41E0),HL ;t/s to read from next if more passes CALL L60C4 ;\DE=t/s to write to next (different, if ramd) POP HL ;left to do or junk CALL L4FE6 JR Z,w67E6 ;loop until last pass RET ;SER2.Z80 ;HKHL=addr of MSB of ptr in strms (in section B) ;HKC=file name len ;HKDE=file name start (usually in buffer) ;CHAD pts to #0D or ":" or "IN" or "OUT" t6851 CALL L4F06 CALL L686C CALL w6717 LD HL,(L41DE) DEC HL LD BC,#5C16 AND A SBC HL,BC LD A,L SRL A LD (L4138),A JR w68B3 L686C CP #0D RET Z CP ":" RET Z CP #FF JR NZ,w6885 CALL L4F00 LD C,#BF ;use ZX "IN" code CP #60 ;#FF #60 is "IN" code JR Z,L688C LD C,#A5 ;ZX "RND" code CP #3C ;#FF #3C is "RND" code JR Z,L688C w6885 LD C,#DF ;ZX "OUT" code CP #E0 ;"OUT" token JP NZ,L5DCA L688C LD A,C LD (L4137),A JP L4F00 k6893 CALL L4EBD ;OPEN, OPEN # command syntax routine CALL Z,L5E37 ;remove any fp forms in syntax time CALL L4F00 CP "#" JP NZ,w709B CALL L6119 ;skip, eval stream CALL L5DC6 ;insist ,/; (skipped) or quote CALL L670D ;name CALL L686C ;deal with CR/:/IN/OUT CALL L4F52 ;place next stat addr CALL L4ECB w68B3 LD A,(L4138) CALL L6D82 ;BC=current disp in strms CP #04 JR C,w68C6 ;don't worry if streams 0-3 already open LD HL,5*5+1 ;disp of last standard channel AND A SBC HL,BC JP C,w5050 ;"stream used" if stream open to non-standard now w68C6 LD A,(L4139) AND #DF CP "D" JP NZ,L5DCA ;"nonsense" CALL L46EC LD A,#0A LD (L413A),A ;file type n68D8 LD A,(L4138) ;open a stream to 'D' channel ADD A,A LD HL,#5C16+up LD E,A LD D,#00 ADD HL,DE PUSH HL ;addr of ptr in strms CALL L68F2 POP DE RET C ;RET if error ; BIT 0,(IX+MFLG) ;remarked in original ; JR Z,OPDST1 ;JR if open IN or RND ; CALL COMMP ; IN A,(C) ; BIT 6,A ; JR Z,OPDST1 ;need to write to get this bit to work! ; CALL RCLMX ; JP REP23 ;"disc is write protected" RES 7,(IX+#04) ;"D" not "D"+#80 - perm channel EX DE,HL LD (HL),E INC HL LD (HL),D ;strm ptr RET L68F2 XOR A ;open a 'D' disc channel OUT (#FB),A LD IX,(#9C4F) LD DE,6*5+up ADD IX,DE ;skip 6 standard channels w68FE LD A,(IX+#00) CP #0D JR Z,w693A ;JR if chans terminator found - new channel LD A,(IX+#04) ;found an open channel AND #5F CP "D" JR NZ,L6930 LD A,(L4136) CP (IX+#0B) JR NZ,L6930 PUSH IX ;check name of channel POP HL LD DE,#0014 ADD HL,DE EX DE,HL LD HL,L413A+1 LD B,#0A w6923 LD A,(DE) XOR (HL) AND #DF JR NZ,L6930 INC HL INC DE DJNZ w6923 JP w5053 ;"channel used" L6930 LD E,(IX+#09) ;get the length of channel LD D,(IX+#0A) ADD IX,DE JR w68FE w693A PUSH IX ;it is a new channel - now test directory for filename LD A,#10 CALL L4A18 ;Z if found POP HL ;addr of chans terminator - LOCN for new chan PUSH HL LD A,(L4137) JP NZ,w6A1C ;JR if not found PUSH AF CALL L6A77 ;create channel CALL L4E84 ;HL=dir entry (uses IX=DCHAN) POP AF POP IX ;chans ptr PUSH HL ;dir entry ptr LD C,#04 ;bits 1 and 0 show read, bit 2 shows exists CP #BF ;IN JR Z,L6965 CP #DF ;OUT JP Z,L5038 ;writing a read file if exists and OUT CP #A5 ;RND JR NZ,L6965 ;JR if default - IN LD C,#06 ;bits 1 and 0 show rnd, bit 2 shows exists L6965 LD A,C CALL L6D93 LD DE,#0013 LD BC,#0100 PUSH IX POP HL ;channel ADD HL,DE EX DE,HL ;DE=type/name etc dest in channel POP HL ;dir entry PUSH HL ;dir entry PUSH DE ;type in channel LDIR ;copy 256 bytes from dir entry to channel ;includes type, name, ????, BAM, length POP DE ;type in channel POP HL ;dir entry LD BC,#000B LD A,(HL) LD (L413A),A LDIR INC HL INC HL LD D,(HL) INC HL LD E,(HL) PUSH DE ;first t/s XOR A LD (IX+#1F),A LD (IX+#1E),A ;file's sector=0 to start with CALL L6EE4 ;inc sector, load and mark first sector with t/s CALL L6A66 ;get stream offset in HL POP DE PUSH HL LD (IX+#20),D ;trk LD (IX+#21),E ;sect PUSH IX POP HL LD BC,#13+#F2 ADD HL,BC ;pt to execution addr of #FFFFFF unless G+DOS LD BC,#0009 ;hdr len LD A,(IX+#13) ;type BIT 6,A ;protect bit JR Z,w69B4 LD (IX+#0C),#04 ;ensure protected files are read-only w69B4 AND #1F CP #0A JR NZ,w69C0 ;JR if not opentype LD A,(HL) INC A JR NZ,w69DC ;JR if G+DOS open-type file LD C,A ;C=0. no hdr in opentype file DEC A ;A=#FF so no JR w69C0 CP #10 JR C,w69D4 ;JR if ZX type DEC HL ;pt to len data for all file types LD D,(HL) DEC HL LD E,(HL) DEC HL LD A,(HL) EX DE,HL CALL L5F05 ;get 20-bit len ADD HL,BC ;hdr len or zero ADC A,#00 LD B,A JR L69E7 w69D4 LD HL,#C000 LD B,L CP #05 JR Z,L69E7 ;JR if 48k snap w69DC CALL L6F39 DEC HL LD D,(HL) DEC HL LD E,(HL) DEC HL DEC HL LD B,(HL) EX DE,HL ;BHL=len in ZX form L69E7 CALL L6F06 ;get HL=len mod 510, HL'=div 510 EX DE,HL CALL L6F39 ;NC LD (HL),E INC HL LD (HL),D ;len mod 510 INC HL EXX PUSH HL ;len div 510 (len cnt) EXX POP DE LD (HL),E INC HL LD (HL),D ;len div 510 XOR A LD (L413A+1),A ;no name so no "OVERWRITE?" PUSH IX LD IX,dchan ;ensure clearing hits DCHAN, not channel CALL L4FC8 ;"no sector needed" CALL t4C08 ;set up SAM, clear, inc SAMCNT ;ensure extending rnd file never uses earlier sectors. look backwards thru ;SAM, force to FFS after last used sector seen POP IX LD HL,L400F+195 w6A0E DEC L LD A,(HL) AND A ;(NC) JR Z,w6A0E ;look for last byte with any bit (sect) used INC L w6A14 DEC L LD (HL),#FF JR NZ,w6A14 POP HL ;stream offset AND A ;NC=OK (not needed...) RET ;file not found ;open a new "RND" file or an "OUT" file w6A1C CP #BF ;IN JP Z,L5D4F ;"file not found" if "IN" with new file PUSH AF CALL L6A77 POP AF POP IX CP #A5 LD A,#02 JR Z,w6A2F ;JR if RND (bits 1-0 = 10) bit 2=0 (new file) DEC A ;bits 1-0 show OUT (01). OUT is default. w6A2F CALL w6A36 ;sets FTRK/FSCT, cnt=1, exit with HL=strm ptr JP NC,L6D01 ;C=aborted RET w6A36 CALL L6D93 ;set MFLG etc CALL L635D ;delay if not ramdisc in case 1st sct written too soon ;create SAM for drive, init area at IX, inc samcnt. as sectors are written, SAM ;accumulates used sects for drive, FSAM ditto for file. but if 2 OUT files open ;to different drives, 1 SAM=disaster! even 2 OUT files on 1 drive must ensure ;2nd does not clear sam or bits reflecting FSAM are lost! CALL t4C08 JR NC,w6A4E ;JR if not abort due "OVERWRITE" and "N" LD BC,#0313 PUSH IX POP HL CALL L7BB4 ;jump to DEFW #0163 ;JRECLAIM SCF ;"opend aborted" RET w6A4E CALL L4FEC JR Z,L6A66 ;JR if not move PUSH IX POP HL LD BC,#00EF ADD HL,BC EX DE,HL ;DEST=byte 220 in FFSA (dest disc channel) LD HL,(L4156) LD B,up/256 ADD HL,BC ;ditto for src (if disc channel) LD BC,#0024 LDIR ;copy 220-255 L6A66 PUSH IX ;calculate stream offset POP HL LD DE,#4000 AND A SBC HL,DE LD DE,(#9C4F) SBC HL,DE INC HL RET ;NC - OK L6A77 PUSH HL ;create a 'D'+#80 channel at HL XOR A LD BC,#0313 CALL L7BB4 ;jump to DEFW #010C ;MKRBIG, open space for channel POP DE LD HL,d6A97 LD BC,#000B LDIR ;o/p,i/p,"D"+#80,0,0,0,0,len EX DE,HL LD BC,#0313-11 w6A8E LD (HL),#00 ;clear the new channel area INC HL DEC BC LD A,B OR C JR NZ,w6A8E RET d6A97 DEFW m4BA0,m4BA9 ;disc 'D' channel data DEFB "D"+#80,#00,#00,#00,#00 DEFW #0313 ;chan len (IX+9/10) ;hook 151 - disc block o/p BC from DE. faster than repeated use of RST 08H ;for single chars t6AA2 LD DE,(L41E0) ;src LD HL,(L41E2) ;count BIT 7,D JR NZ,L6AB4 ;JR if src in sect C SET 7,D RES 6,D ;else adjust sys page src (e.g. STR$) to sect C XOR A OUT (#FB),A ;sys page in sect C (#0013 resets orig pg at end) L6AB4 LD A,H OR L RET Z DEC HL ;dec char count PUSH DE PUSH HL LD A,(DE) CALL t6C68 POP HL POP DE INC DE BIT 6,D CALL NZ,L3FEB ;incpagde JR L6AB4 k6AC8 LD C,"*" ;CLOSE, CLOSE# streams command CALL L4EF9 ;insist "*" CALL L4EB4 JR Z,w6ADD ;JR if CR/0D - CLOSE * is close all CALL L611C ;eval stream no. CALL L4ECB LD A,(L4138) JR L6B12 w6ADD CALL L4ECB JR w6AED k6AE2 LD C,"#" ;CLEAR, CLEAR# streams command CALL L4EF9 CALL L4ECB CALL L4FB6 ;"CLEAR#" w6AED XOR A w6AEE PUSH AF CALL L6B12 POP AF INC A CP #10 JR C,w6AEE CALL L677F XOR A LD (dvar+20),A LD (L7C0C),A RET t6B03 LD HL,(L41E0) LD BC,#5C16 AND A SBC HL,BC LD A,L SRL A LD (L4138),A L6B12 CALL L6D82 ;clear stream and close channel LD A,C OR B RET Z ;RET if closed already LD (L4124),BC ;close the stream PUSH HL ;ptr to strms LD HL,(#9C4F) DEC HL ADD HL,BC SET 7,H RES 6,H ;pt to channel switched in at #8000-#BFFF EX (SP),HL ;HL=ptr to strms LD BC,#0000 LD DE,-#9C1E EX DE,HL ADD HL,DE ;add -#9C1E, strms ptr JR C,w6B38 ;JR if stream >3 LD BC,d6C1E+8 ADD HL,BC LD C,(HL) INC HL LD B,(HL) w6B38 EX DE,HL SET 7,H RES 6,H ;addr in streams LD (HL),C INC HL LD (HL),B POP IX ;channel start LD A,B OR C RET NZ ;RET if stream 0-3 just closed LD A,(IX+#04) ;test for disc 'D' channel AND #5F CP "D" RET NZ w6B4D LD A,(IX+#0C) AND #03 JR NZ,w6B63 ;JR if its not an "IN" file CALL L6B59 ;(DECSAM done by SDCM for RND/OUT) JR w6B69 L6B59 LD A,(dvar+20) AND A RET Z ;no dec below zero! DEC A LD (dvar+20),A RET w6B63 CALL L4FE6 CALL Z,w6BB4 ;call if not CLEAR # w6B69 CALL L65ED ;reclaim the channel XOR A ;close and update stream disp LD HL,#5C16+up w6B70 LD (L7C05),HL LD E,(HL) INC HL LD D,(HL) ;disp of a stream LD HL,(L4124) AND A SBC HL,DE JR NC,L6BA9 ;JR if no need to alter it EX DE,HL AND A SBC HL,BC EX DE,HL LD HL,(L7C05) LD (HL),E INC HL LD (HL),D ;reduced disp replaced DEC DE LD HL,(#5C4F+up) ADD HL,DE LD DE,up+4 ADD HL,DE LD D,A LD A,(HL) AND #5F CP "D" LD A,D JR NZ,L6BA9 LD DE,#000F-4 ADD HL,DE LD E,(HL) INC HL LD D,(HL) ;old MBUFF EX DE,HL SBC HL,BC EX DE,HL LD (HL),D DEC HL LD (HL),E ;adjusted MBUFF L6BA9 LD HL,(L7C05) INC HL INC HL INC A CP #10 JR C,w6B70 ;loop for streams 0-15 RET w6BB4 CALL L470E XOR A LD (L41FC),A ;ensure no use of FSLOT, DE=t/s CALL L44A9 ;write current sector if it has been altered CALL L6B59 BIT 5,(IX+#0C) RET Z ;RET if file was not altered - no need to alter directory entry CALL L6F1A ;get file len in AHL, sects in BC LD D,A LD A,(IX+#13) AND #1F CP #10 LD A,D JR C,w6BDA ;JR if opentype and ZX files LD DE,-9 ADD HL,DE ADC A,#FF ;AHL=AHL-9 (hdr not included in len) w6BDA LD (IX+#1F),C ;over-write ptr LD (IX+#1E),B EX DE,HL CALL L6F39 DEC HL LD (HL),D ;old format mid len - so G+DOS can read ;(unless first dir entry - name uses area) DEC HL LD (HL),E ;low DEC HL DEC HL LD (HL),A ;hi - byte D2 EX DE,HL CALL L7462 EX DE,HL LD BC,#001D ADD HL,BC ;pt to byte #EF LD (HL),A INC HL LD (HL),E INC HL LD (HL),D ;new form of len INC HL LD (HL),#FF ;"exec addr" of #FFXXXX PUSH IX BIT 2,(IX+#0C) JP Z,L4D1E ;JR if file is a new one - make new dir entry ;else dealing with an altered existing file PUSH IX POP HL LD BC,#0013 ;19 ADD HL,BC LD DE,L413A LD C,#0B LDIR ;copy name to NSTR1 LD A,#08 CALL L4A18 ;look for file entry JP NZ,L5D4F ;error if not found JP L4D26 ;update directory - overwriting old entry d6C1E DEFB 1,0,1,0,6,0,16,0 t6C26 CALL w6C34 ;hook routine to read byte from disc. used by "D" channel RET C ;RET if got char RET Z ;RET if not EOF CALL L4FEC JP Z,L504A ;"EOF" if not a MOVE cmd OR #01 ;NC,NZ - EOF RET w6C34 IN A,(#FB) ;disc 'D' channel input subroutine PUSH AF XOR A OUT (#FB),A PUSH IX ;keep FPC happy during INKEY$ LD HL,#5C3C+up RES 3,(HL) ;"no need to copy line to LS"- needed? LD IX,(#5C51+up) LD BC,#4000 ADD IX,BC BIT 0,(IX+#0C) JP NZ,w5035 ;"reading a write file" if type="OUT" CALL L6D1A JR NZ,w6C5A ;JR if not EOF ADD A,#0D ;NC+NZ=EOF (when ptr=len) JR w6C5E w6C5A CALL t6D34 SCF ;"got key" w6C5E PUSH AF POP BC ;AF in BC for transmission out POP IX EX AF,AF' POP AF OUT (#FB),A EX AF,AF' RET t6C68 LD D,A ;hook routine to write byte in A to disc. used by "D" channel IN A,(#FB) PUSH AF XOR A OUT (#FB),A LD IX,(#9C51) LD BC,#4000 ADD IX,BC LD A,(IX+#0C) AND #03 JP Z,L5038 ;"writing a read file" if "in" LD A,(#9B74) CP #C6 ;value for "INPUT" JR Z,w6CA0 ;no write if so CALL L6D1A ;Z if ptr=len PUSH AF LD A,D CALL w6CC6 ;save byte SET 3,(IX+#0C) ;"sector written to" SET 5,(IX+#0C) ;"file written to" POP AF CALL Z,L6D01 ;copy ptr to len if writing to extend file LD A,(#5C4B+up) ;restore border colour - quickly OUT (#FE),A w6CA0 POP AF OUT (#FB),A RET L6CA4 CALL L496A LD (HL),D ;t INC HL LD (HL),E ;s complete buffer of 512 EX DE,HL L6CAB CALL L4E97 ;swap the next track/sector LD (IX+#12),H LD (IX+#11),L RET t6CB5 PUSH BC PUSH HL PUSH AF CALL L474C ;HL=addr of write point, Z if BC=510 ;BC=rpt (disp from buffer start to write point) JR NZ,L6CF5 PUSH DE CALL L6CA4 ;place next t/s in IX+, get DE=current t/s CALL L44B4 ;exits with HL pointing to buffer start, rpt reset JR w6CF4 w6CC6 PUSH BC ;new save byte to disc - serial files PUSH HL PUSH AF CALL L474C JR NZ,L6CF5 ;JR if buffer not full PUSH DE PUSH HL CALL L6D1A ;CP ptr with file len POP HL JR NZ,w6CF1 ;JR if we are not at file end CALL L6CA4 CALL L470E ;select drive PUSH BC ;prev drive CALL w44B1 ;exit with HL at buffer start POP BC LD A,C CALL L4715 ;prev PUSH HL LD D,H LD E,L INC DE LD BC,#01FF XOR A ;Z LD (HL),A LDIR ;blank new sector POP HL w6CF1 CALL NZ,L6ED8 w6CF4 POP DE L6CF5 POP AF LD (HL),A POP HL POP BC L6CF9 INC (IX+#0D) ;increment ram pointer RET NZ INC (IX+#0E) RET L6D01 PUSH HL CALL L6F39 ;NC LD A,(IX+#0D) LD (HL),A INC HL LD A,(IX+#0E) LD (HL),A INC HL LD A,(IX+#1F) LD (HL),A INC HL LD A,(IX+#1E) LD (HL),A POP HL ; SET 4,(IX+MFLG) ;"file has been extended" RET L6D1A CALL L6F39 ;CP ptr with len. Z if match (and HL=len MSB of 4) LD A,(IX+#0D) CP (HL) ;HL pts to len low (like RPT) RET NZ INC HL LD A,(IX+#0E) CP (HL) RET NZ INC HL LD A,(IX+#1F) CP (HL) RET NZ INC HL LD A,(IX+#1E) SUB (HL) RET ;A=0 if EOF, Z flag t6D34 PUSH BC ;load byte from disc PUSH DE PUSH HL CALL L474C CALL Z,L6ED8 ;call if buffer full, write this sector if altered, read next LD A,(HL) POP HL POP DE POP BC JR L6CF9 ;ptr/EOF sr, exit: AHL=ptr value, DE=channel start w6D43 CALL L7BB4 ;jump to DEFW #0121 ;JGETINT INC H DEC H JR NZ,L6D7A CP #10 JR NC,L6D7A L6D50 CALL L6D82 LD A,B OR C JR Z,L6D7E ;error if stream not open DEC BC LD HL,(#5C4F+up) ADD HL,BC LD BC,up ADD HL,BC ;channel start PUSH HL POP IX LD A,(IX+#04) CP "D" JP NZ,L46D9 ;"invalid device" LD C,(IX+#1F) LD B,(IX+#1E) ;ptr in 510's LD L,(IX+#0D) LD H,(IX+#0E) ;ptr mod 510 JP L6F25 L6D7A CALL L5097 ;"invalid stream number" DEFB 21 L6D7E CALL L5097 ;"stream is not open" DEFB 47 ;stream displacement ;entry: A=stream no. ;exit: A unchanged, HL=addr in streams, BC=ptr value from streams L6D82 PUSH AF ADD A,A LD C,A XOR A OUT (#FB),A LD B,A LD HL,#5C16+up ;stream zero ADD HL,BC LD C,(HL) INC HL LD B,(HL) ;BC=current disp in strms DEC HL POP AF RET ;set IX+mflg, IX+bufl/h using A and BC ;(set type=IN (0), OUT (1) or RND (2), set buffer LOCN=IX+BC) L6D93 PUSH HL LD (IX+#0C),A PUSH IX POP HL LD BC,#0113 ADD HL,BC LD (IX+#0F),L ;bufl LD (IX+#10),H ;bufh LD A,(L4136) LD (IX+#0B),A ;mdrv POP HL RET w6DAC LD C,"#" ;POINT #S,X or POINT #S,OVER X CALL L4EF9 CALL L611C ;eval stream CALL L5DC6 ;,/; (skipped) or quote CP #A6 ;OVER JP Z,w6E3B CALL w6143 ;BC=x mod 64k, DE=x div 64k CALL L4ECB PUSH BC PUSH DE LD A,(L4138) CALL L6D50 ;pt IX to channel, check OPEN "D" IN CALL L6F1A POP BC ;x div 64k POP DE SBC HL,DE SBC A,B JR C,w6DF2 EX DE,HL CALL L6F06 PUSH HL EXX LD (IX+#1F),L LD (IX+#1E),H EXX ;find t/s of DE'th sector in a file, using FSAM ;entry: IX pts to file area, HL'=sect (1=first sector) ;exit: D=track, E=sect, NZ, or Z=not found (not that many sectors in FSAM) ;uses AF, BC, DE, HL, HL', D' PUSH IX POP HL LD BC,#0022 ADD HL,BC ;pt HL to FSAM PUSH HL LD B,195 w6DEB LD A,(HL) INC HL AND A JR NZ,w6DF5 ;JR if map byte has any used sectors in it w6DF0 DJNZ w6DEB w6DF2 JP L504A ;EOF if ran out of map bits w6DF5 LD E,#08 ;8 bits to examine w6DF7 RRA JR NC,w6E03 ;JR if sector not used EXX DEC HL ;dec 'desired sector' counter LD D,A LD A,H OR L LD A,D EXX JR Z,w6E08 ;JR if got the one we wanted w6E03 DEC E JR NZ,w6DF7 ;loop for all bits JR w6DF0 ;next byte if all bits done w6E08 POP BC ;FSAM start SCF SBC HL,BC ;HL=map byte ADD HL,HL ADD HL,HL ADD HL,HL ;map sector (div 8) LD D,#00 LD A,#08 SUB E LD E,A ADD HL,DE ;D=0, E=bit (7-0 for bit 7-0 in byte) LD D,#03 ;first data track=4 w6E18 CALL L499D ;inc D, check for end of side LD BC,-10 ADD HL,BC JP C,w6E18 SBC HL,BC LD H,D INC L CALL L4E97 EX DE,HL AND A SBC HL,DE JR Z,w6E37 PUSH DE CALL L44A9 POP DE CALL w6EE7 w6E37 POP DE ;setrpt LD (IX+RPTL),E ;in 4.3 ; LD (IX+RPTH),D ; RET JP w6EBC w6E3B CALL L612F CALL L4ECB PUSH BC LD A,(L4138) CALL L6D50 ;AHL=current ptr CALL L4E89 ;HL=buff ptr, BC=disp in buffer (0-509) EX DE,HL LD HL,510 AND A SBC HL,BC LD B,H LD C,L ;BC=bytes left in buffer EX DE,HL ;HL=buff ptr POP DE ;items to skip LD A,D OR E RET Z w6E59 LD A,B OR C JR Z,L6E6E ;if sector searched, enter sect loop (never on first pass) LD A,(dvar+10) CPIR JR NZ,L6E6E ;JR if delim not found - search next sect DEC DE LD A,D OR E JR NZ,w6E59 ;loop until skipped right number of delims. LD HL,510 ;\if BC=0, use next sect JR w6EB1 L6E6E LD (L4212),DE ;delim count XOR A LD (L4214+1),A ;"not found" CALL L44A9 CALL L6EC8 CALL w4567 ;read next sector, looking for delim CALL w6EF3 ;mark sect with cur t/s CALL L6EFE LD DE,(L4216) ;counter PUSH HL ;buffer start PUSH IX POP HL ;channel start LD BC,#0311 ADD HL,BC ;pt to ntrk LD BC,(L4214) ;record ptr - if 00XX, no match ; if NTRK or less, real match ; if NSECT, spurious match on trk ; if NSECT+1, spurious match on sct LD A,B AND A JR Z,w6E9E ;JR if DE not counted down yet, no addr in BC SBC HL,BC ADD HL,BC JR NC,w6EAD ;JR if OK w6E9E POP AF ;junk buffer start LD A,(dvar+10) CP (HL) JR NZ,w6EA6 INC DE ;correct counter for spurious match on track w6EA6 INC HL CP (HL) JR NZ,L6E6E ;JR if sector wasn't a spurious match INC DE ;correct counter JR L6E6E w6EAD POP BC ;buffer start LD HL,(L4214) ;ptr within buffer w6EB1 SBC HL,BC ;record ptr-buffer start (#0001-#01FE) ;(when entry at PRCE, HL=510, BC=bytes left) EX DE,HL LD HL,510 AND A SBC HL,DE ; JP NZ,setrpt ;JP if record in this sector JR Z,w6EC3 ;\not present in 4.3 w6EBC LD (IX+#0D),E LD (IX+#0E),D RET ;/ w6EC3 CALL L6EC8 JR L6EE4 L6EC8 PUSH IX ;read next t/s from IX+NTRK POP HL LD DE,#0311 ADD HL,DE LD D,(HL) INC HL LD E,(HL) ;DE=next t/s LD A,D OR E JP Z,L504A ;EOF if last sector RET ;called when ptr has reached buffer end on read or write (not at file end) ;writes current sector if it has been written to, before reading next one L6ED8 LD D,(HL) ;track INC HL LD E,(HL) ;sect from end of current buffer PUSH DE EX DE,HL CALL L6CAB ;set new cur. t/s from HL, get DE=old cur. t/s CALL w44AC ;if sector has been written to, save it POP DE L6EE4 CALL L6EFE w6EE7 CALL L470E ;select drive PUSH BC ;prev drive CALL L44EA POP BC LD A,C CALL L4715 ;prev w6EF3 RES 3,(IX+#0C) ;"not written to yet", mark NSRL/H with DE L6EF7 LD (IX+#12),D ;save the next track/sector LD (IX+#11),E RET L6EFE INC (IX+#1F) ;inc cnt (current sector number) RET NZ INC (IX+#1E) RET ;entry: BHL=24-bit number ;exit: HL=number mod 510, HL'=number div 510 L6F06 XOR A LD D,A ;D must be zero later EXX LD L,A LD H,A ;sector count inited EXX LD A,B LD BC,510 ;DBC=510 w6F10 EXX INC HL EXX SBC HL,BC SBC A,D JR NC,w6F10 ADD HL,BC ;HL=disp in sector RET ;HL=sector ;get file len in AHL. NC from M510 L6F1A CALL L6F39 ;HL pts to len low (like RPT) LD E,(HL) INC HL LD D,(HL) INC HL LD C,(HL) INC HL LD B,(HL) ;BC=len div 510 EX DE,HL ;HL=len mod 510 ;let AHL=HL+BC*510 L6F25 PUSH BC ;needed by 'GLEN' XOR A LD DE,#01FE JR w6F30 w6F2C EX AF,AF' ADD HL,DE ADC A,#00 w6F30 EX AF,AF' DEC BC LD A,B OR C JR NZ,w6F2C ;loop until A'HL=ptr EX AF,AF' ;NC POP BC RET L6F39 PUSH IX POP HL LD BC,#00E9 ADD HL,BC ;HL pts to len low (like RPT) RET ;TIME.Z80 k6F41 LD HL,dvar+81 ;DATE DEFB #FD ;dummy LD IY,dvar+96 k6F45 LD HL,dvar+96 ;TIME LD (dvar+79),HL CALL L6FA2 ;update buffers CALL L4F00 CALL L4EB4 JR Z,w6F8B ;JR if printing of data, not setting data CALL L6105 ;DE=start, BC=len CALL L4ECB LD A,(L411E) CALL L3FDF ;page string in LD HL,(dvar+79) LD B,#06 L6F67 LD A,C AND A LD A,"0" JR Z,w6F75 ;pad with zeros once string len=0 LD A,(DE) INC DE DEC C CALL L4F10 JR NC,L6F67 ;loop if not a digit w6F75 LD (HL),A w6F76 INC HL LD A,(HL) CALL L4F10 JR NC,w6F76 ;loop if not a digit DJNZ L6F67 ;loop placing 6 numbers from string, or pads CALL w700E ;check values JP C,L5F12 LD IY,w6FFE ;write date and time to clock hardware from buffers JR w6FA6 w6F8B CALL L4ECB LD A,#02 CALL L7BB4 ;jump to DEFW #0112 ;JSETSTRM LD B,#09 LD HL,(dvar+79) L6F9A LD A,(HL) ;print B from HL - used to print date/time/path name INC HL CALL L567D DJNZ L6F9A RET L6FA2 LD IY,w6FED ;read clock hardware info into date and time buffers w6FA6 LD A,(dvar+150) ;clock port AND A RET Z ;abort if no clock! DI ;crashes if not... PUSH HL LD C,A LD B,#D0 ;control register LD HL,#07D0 w6FB3 LD A,#01 OUT (C),A ;hold on IN A,(C) BIT 1,A JR Z,w6FC6 ;exit if not busy XOR A OUT (C),A ;hold off DEC HL CP H JR NZ,w6FB3 POP HL ;give up - no clock?? RET w6FC6 LD B,#50 ;hours-h register LD HL,dvar+96 CALL #0006 ;handle hours CALL #0006 ;handle mins CALL #0006 ;handle secs LD HL,dvar+81 LD B,#70 ;day-h CALL #0006 ;day LD B,#90 ;mth-h CALL #0006 ;month LD B,#B0 ;yr-h CALL #0006 ;year XOR A LD B,#D0 OUT (C),A ;hold off POP HL RET w6FED CALL w6FF1 ;entry: HL pts to dest, B=clk register, C=port DEC HL ;exit: HL inced by 3, register deced by 2, 2 digits placed w6FF1 IN A,(C) ;read digit AND #0F ADD A,#30 CP #3A JR NC,L7007 ;ensure hardware errors do not place a non-digit LD (HL),A JR L7007 w6FFE CALL w7002 ;entry: HL pts to src, B=clk register, C=port DEC HL ;exit: HL inced by 3, register deced by 2, 2 digits sent to clock w7002 LD A,(HL) ;read digit SUB #30 OUT (C),A L7007 INC HL INC HL LD A,B SUB #10 ;next port LD B,A RET w700E LD DE,(dvar+79) ;date/time sr to check values LD HL,#0009 ;NC if OK, CY if >limit ADD HL,DE ;DE pts to data to check, HL to limit LD B,#03 ;values to check w7018 CALL L7057 ;get value in a LD C,A LD A,(HL) INC HL CP C RET C ;RET if value>hi limit LD A,C CP (HL) RET C ;RET if value00 ;G+DOS files have #00 ->#01 ;DOS 3.0 files have #01 or more ->#02 CP #02 RET C ;RET if no date LD C,"/" CALL w707D ;date, with "/" separator LD C,":" LD A," " JR w7081 ;time, with ":" separator ;print six digits from 3 bytes at (HL) as NN (separator) NN (separator) NN ;entry: C=separator w707D CALL L708B LD A,C w7081 CALL L567D CALL L708B LD A,C CALL L567D L708B PUSH HL PUSH DE PUSH BC LD L,(HL) LD H,#00 LD A,"0" CALL L564C POP BC POP DE POP HL INC HL RET ;SUBD.Z80 ;OPEN DIRectory - jumped to from "OPEN" when next char<>"#" w709B LD C,#90 ;DIR CALL L4EFC CALL L670D ;name CALL L4F52 ;place next stat addr CALL L4ECB LD A,#15 ;"directory" LD (L413A),A CALL L4FC8 ;"no sector needed" CALL L4C27 LD A,(dvar+21) ;set by fdhr INC A ;tag value for this directory's files CP #FF JP Z,L5047 ;error if too many dir files LD (L7C13+#FA),A ;copied to sector buffer by cfsm JP L4D09 ;cfsm ;set current directory - jumped to from "DIR" cmd when "=" follows it w70C3 CALL L4F00 ;skip "=" CP "^" ;uparrow JR Z,w70CF CALL L71A1 JR NZ,w70E5 w70CF EX DE,HL ;start of "string" to DE CALL L4F00 CALL L4ECB LD BC,#0001 ;len IN A,(#FB) DEFB #FE ;dummy CP #D9 t70DC EXX ;hook set dir. A=page, BC=len, DE=start, of name LD (L411E),A CALL L6054 ;eval as name, avoiding string fetch JR w70EB w70E5 CALL L6050 CALL L4ECB w70EB LD HL,L413A+1 CALL L64F6 CALL L46E5 CALL L72E5 ;get path len addr in HL LD A,(HL) LD (L4212),A ;save path len to allow up arrow trim/no trim LD HL,L413A+1 LD A,(HL) CALL L71A1 ;check if root JR NZ,L710F CALL L6583 JR NZ,L710F ;JR if not root by itself else set root (no disc access) ;set root=perm dir. called if rand word changes, used if DIR=/ w7109 LD BC,#0002 ;path len for "1:" or "2:" JP w718E ;select root (B=0) L710F CP "^" ;up-arrow JR NZ,L712A CALL L6583 JR NZ,L712A ;JR if not up-arrow by itself CALL w724A ;change cdirt to level of parent dir if there ;is a parent dir. save trimed path len in tempw1 CALL L72E5 LD A,(L4212) LD (HL),A ;trim length CALL L72E0 ;get cdirp addr LD A,(dvar+17) LD (HL),A RET L712A IN A,(#FB) PUSH AF CALL L71D2 ;get B=len, HL=start, of paged-in path string PUSH BC ;len in B PUSH HL CALL L71F5 ;descend path till last file in nstr1+1 CALL L71AB ;find directory CALL L72E5 POP DE POP BC ;B=len w713D LD A,(DE) CALL L71A1 LD A,#02 ;path len is 2 if dir name starts with root. ;later names add to this stump, e.g. ;DIR="\GAMES\SCAB" sets PATH$ to "1:\GAMES\SCRAB" ;whatever current dir is. ;otherwise e.g. if PATH$="1:\GAMES" and DIR="SCRAB" ;then PATH$ becomes "1:\GAMES\SCRAB" JR Z,w714D ;JR if root LD A,(DE) CP "^" ;up-arrow JR NZ,w7155 LD A,(L4212) ;len left by upar sr w714D LD (HL),A ;set length INC DE ;skip leading root or arrow symbol. root sym is ;added automatically as name is added to path DJNZ w713D ;dec len CALL L5097 DEFB 18 w7155 PUSH BC CALL L72AB ;get HL=path start, BC=len ADD HL,BC EX DE,HL ;pt DE to end of path data, HL to name POP AF LD B,A INC B ;B=name chars to copy, plus 1 for divider LD A,(dvar+12) ;divider symbol JR w7165 w7163 LD A,(HL) INC HL w7165 EX AF,AF' INC C LD A,C CP #26+1 ;max len+1 JR NC,L717A ;JR if no room left (would be 33rd char next) EX AF,AF' CALL L71A1 JR NZ,w7175 LD A,(dvar+12) ;always use first alternative divider in PATH$ w7175 LD (DE),A INC DE DJNZ w7163 ;copy name INC C L717A DEC DE DEC C LD A,(DE) CP " " JR Z,L717A ;trim spaces, C=new path len PUSH BC CALL L4E84 ;start of dir entry POP BC LD DE,#00FA ;disp to tag value for files in this dir ADD HL,DE LD B,(HL) POP AF OUT (#FB),A w718E CALL L72E0 ;get cdirp addr LD (HL),B ;set cdirp LD A,B LD (dvar+17),A ;and cdirt CALL L72E5 ;get path len addr LD (HL),C w719A CALL L5FDB JP NC,w75AB ;store rd path name if ram disc RET L71A1 PUSH HL ;root check - Z if root symbol LD HL,(dvar+12) ;usually "\" and "/" CP H JR Z,w71A9 CP L w71A9 POP HL RET L71AB CALL L5D60 ;find directory. exit with HL=point JR NC,w71B9 ;error if directory not found LD HL,L7C0C RES 2,(HL) ;"not initialised" so later use of fndfl and sndfl starts from t0/s1 CALL L4E9E RET Z ;RET if dir type w71B9 JP w5056 ;error if not right type L71BC LD HL,#413B CALL L64F6 CALL L46E5 w71C5 IN A,(#FB) ;get last name PUSH AF CALL L71D2 ;get B=len, HL=start, of paged-in path string CALL L71F5 ;descend path till last file in nstr1+1 POP AF OUT (#FB),A RET L71D2 XOR A ;prepare path OUT (#FB),A ;page in string buffer LD A,(#4F60+up) ;real string length LD HL,(L4216) ;chars trimmed off front - e.g. "D2:" SUB L JR C,L71E6 ;JR if e.g. "" or "D2" altered to "T:" OR "D2:" ;so trimmed chars > orig len JR Z,L71E6 ;JR if all chars trimmed (e.g. "D2:") LD B,A ;corrected len LD DE,#8F10 ;sys page buffer ADD HL,DE ;corrected start RET ;len in B, start in HL L71E6 LD HL,d71F3 ;use " " if tape LD B,#01 LD A,(L4139) CP "T" RET Z INC HL ;else "*" RET d71F3 DEFM " *" ;descend path tree ;entry: HL pts to path string, B=len (<>) ;action: path is broken into directory names and each directory is selected ;until a final name is returned in nstr1+1 L71F5 CALL w7242 ;check if first char in name is up-arrow, handle if so CALL L71A1 JR NZ,L7205 INC HL ;skip "\" DEC B JR Z,L723E ;e.g. load "\" is an error XOR A LD (dvar+17),A ;root is temp directory L7205 CALL w721A ;get file name RET C ;RET if last name PUSH HL PUSH BC CALL L71AB ;find directory file LD BC,#00FA ;disp to tag value for files in this dir ADD HL,BC LD A,(HL) LD (dvar+17),A POP BC POP HL JR L7205 ;extract file name from string ;entry: HL points to posn in src string, B=src len left ;exit: C=file name len, nstr1+1 holds name ; if CY, name is the last one ;HL points to next name start (root symbol is skipped), B is updated ;e.g. "UTILS\PDS\TEST" broken down to: UTILS, PDS, TEST w721A LD DE,L413A+1 PUSH DE LD A," " LD C,#0A w7222 LD (DE),A INC DE DEC C JR NZ,w7222 ;initial clear of name. C becomes 0 POP DE w7228 LD A,(HL) INC HL DEC B CALL L71A1 RET Z ;RET if root. NC INC B INC C ;name len EX AF,AF' LD A,C CP #0B JR Z,L723E EX AF,AF' LD (DE),A INC DE DJNZ w7228 SCF ;"last name" RET L723E CALL L5097 DEFB 18 ;"invalid file name" ;up-arrow means "go up one level" - search PATH$ for last root symbol ;entry: HL points to string, B=len ;exit: HL points past up-arrow, B is less w7242 LD A,(HL) CP "^" RET NZ INC HL ;skip leading up-arrow DEC B JR Z,L723E ;e.g. load "up-arrow" is an error w724A PUSH BC PUSH HL CALL L72AB ;get HL=path start, BC=len ADD HL,BC LD A,(dvar+12) w7253 DEC HL DEC C JR Z,w72A7 ;JR if no root found - no action CP (HL) JR NZ,w7253 LD A,C LD (L4212),A ;new len stored for use by "DIR=" PUSH HL CALL L72E5 ;pt HL to len LD A,(HL) ;old POP HL INC HL ;point to start of trimmed dir name LD DE,L413A+1 SUB C DEC A ;len of trimmed name CP #0B JR C,w7270 ;should be JR always.... LD A,#0A w7270 LD C,A LD B,#00 LDIR LD C,A LD A,#0A SUB C JR Z,w7282 ;JR if no pads needed EX DE,HL w727C LD (HL),#20 INC HL DEC A JR NZ,w727C w7282 LD HL,dvar+17 LD A,(HL) LD (HL),#FF ;"any" w7288 PUSH AF CALL L71AB ;find parent directory CALL L4FBC ;"restart from current t/s" LD BC,#00FA ADD HL,BC POP AF ;orig cdirt CP (HL) JR NZ,w7288 ;JR if name correct but not real parent according to tag LD BC,254-250 ADD HL,BC LD A,(HL) LD (dvar+17),A ;make current level same level as parent=up 1 LD HL,L7C0C RES 2,(HL) ;start from t0/s1 CALL w719A ;store rd path name w72A7 POP HL POP BC LD A,(HL) RET L72AB CALL L72E5 ;get BC=path len, HL=path, for drive LD B,#00 LD C,(HL) ;BC=path len CALL L5FDB ;A=drive, NC if ram disc JR NC,w72BF LD HL,L7F13 DEC A RET Z LD HL,L7F39 RET w72BF PUSH BC PUSH DE CALL w75AC ;called with NC - fetch name to pthrd LD HL,L40D0 POP DE POP BC RET ;return tracks/disc for current ram disc in A L72CA LD HL,dvar+39-3 ;drive 3 is first entry CALL L72E8 ;get addr LD A,(HL) ;t/disk RET L72D2 LD HL,dvar+44-3 ;+41, get first page addr for ram disc JR L72E8 L72D7 LD HL,dvar+63-2 ;+61, get rnd word addr LD A,(L7C0B) ADD A,A JR w72EB L72E0 LD HL,dvar+49-1 ;+48, get cdirp addr JR L72E8 L72E5 LD HL,dvar+56-1 ;+55, get path len addr L72E8 LD A,(L7C0B) w72EB ADD A,L LD L,A RET NC INC H RET ;set dir tks from sector just read. compare rand word on disc with current, ;alter dir to root if a new disc, update current rand word in memory L72F0 PUSH DE CALL L4E84 PUSH HL INC H DEC HL LD A,(HL) ADD A,#04 LD (dvar+16),A DEC HL DEC HL LD C,(HL) DEC HL LD B,(HL) ;BC=rnd word from disc CALL L72D7 ;get cur. rand word addr in HL LD A,C CP (HL) JR NZ,w730D ;JR if new disc INC HL LD A,B CP (HL) ;NZ if new disc DEC HL w730D LD (HL),C INC HL LD (HL),B POP HL ;point value PUSH HL PUSH BC PUSH HL CALL NZ,w7109 ;set root if new disc POP HL ;point value LD BC,#00D2 ADD HL,BC ;disc name on disc LD DE,L57BE LD C,#0A LDIR ;copy name to msg buffer POP BC ;current rnd no. LD A,(L420E) LD HL,L7C0B CP (HL) JR NZ,L734B LD A,(dvar+20) AND A JR Z,L734B ;JR if no open files to warn about LD HL,(dvar+77) ;SAM rnd no. SBC HL,BC JR Z,L734B ;JR if same disc as when sam openned CALL L59D9 CALL w57C9 ;"OPEN file" CALL L4CEC LD A,(L4138) CALL L7BB4 ;jump to DEFW #0112 ;JSETSTRM L734B POP HL POP DE RET ;RAMD.Z80 ;ram disc write sector at DE. D=track, E=sector. w734E CALL L4E78 ;get src addr in HL. may be #8000 if write at or save block LD A,d7D13/256 ;dram/256 CP H JR Z,w7362 ;JR if src=dram (first sectors, serial files) PUSH DE ;t/s LD DE,d7D13 LD BC,#0200 PUSH DE LDIR POP HL ;src=dram so paging of dest possible (used by WRITE AT) POP DE ;t/s w7362 PUSH DE ;t/s PUSH HL ;src CALL L73E2 ;get rd addr in HL EX DE,HL ;dest in rd into DE POP HL ;src in RAM LD BC,#0200 LDIR OUT (#FB),A w7370 POP DE ;t/s CALL L4CD9 JP L4E78 ;ram disc search sector at DE ;entry: DE=t/s, (tempw1)=delim count, (delim)=delim ;exit: tempw3 holds new delim count, tempw2=locn ;could be faster if sector only read to buffer when matched and count=0: else ;just read last 2 bytes?? w7377 CALL L73BD ;HL=data start PUSH DE PUSH HL LD DE,(L4212) LD BC,#0002 w7383 LD A,(dvar+10) L7386 CP (HL) INC HL JR Z,w7391 DJNZ L7386 DEC C JR NZ,L7386 JR w7399 w7391 DEC DE LD A,D OR E JR NZ,w7383 LD (L4214),HL ;locn of match and count=0 w7399 LD (L4216),DE ;new count POP HL POP DE RET w73A0 CALL L73BD ;ram disc prepare sam from dir entry read PUSH DE PUSH HL EX DE,HL LD HL,#4000 LD B,#02 w73AB LD A,(DE) INC D AND A JR Z,w73B8 ;JR if an erased entry DEC D w73B1 LD A,(DE) OR (HL) LD (HL),A INC DE INC L JR NZ,w73B1 w73B8 DJNZ w73AB POP HL POP DE RET L73BD CALL L4E78 ;ram disc read sector at DE. D=track, E=sector. LD BC,#0200 w73C3 PUSH DE ;t/s PUSH HL ;main mem ptr PUSH BC CALL L73E2 ;get src addr in HL LD BC,#0200 LD DE,d7D13 LDIR ;copy ramdisc to dram OUT (#FB),A ;orig urport POP BC POP HL LD A,#7D CP H JR Z,w7370 ;ret if dest=dram - done it EX DE,HL ;DE=buf LD HL,d7D13 LDIR JR w7370 ;ram disc address - get HL=addr, page selected, from D/E (t/s) ;get A=cur. urport. BC, DE used L73E2 LD A,(L420D) AND A JR Z,L73FC CALL L7425 LD HL,(#82FF) OUT (#FB),A LD A,L ADD A,#03 CP D ;cp dtks-1,trk JR NC,L73FC ;jr if trk in directory - no fiddle ;(always jr on track 0 - when dtks is obsolete!) SUB #03 JR NC,L73FC ;leave track alone if 4 dir tks or more ;A=-1 if dtks=3, -2 if 2, -3 if 1 dtk ADD A,D LD D,A ;e.g. track 4 access becomes track 1 if dtks=1 ;so if dtks=1, disk=40 trk, trk 0=0, trks 4-42 become 1-39 L73FC CALL L72CA ;get A=tracks/drive AND A JP Z,L503E ;"no such drive" if tks=0 LD C,A LD A,D CP C w7406 JP NC,L5026 ;trk/sct error if track >=(limit) AND #7F CP 80 JR NC,w7406 ;error if e.g. trk 81 BIT 7,D JR Z,w7417 ;jr if "side 1" LD A,D SUB #30 ;128->80 LD D,A w7417 CALL L743D ;get pageform of disc addr PUSH HL CALL w75A0 ;pt to entry "A" in list LD L,(HL) ;get page value OUT (#FB),A LD A,L POP HL JR L7429 L7425 CALL L72D2 ;sel first page LD A,(HL) ;A=first page ;select ram disc page. entry: A=page. #00..#1f=internal ram, #20..#FF=external ;exit: A=orig urport value L7429 DI PUSH DE ;save throughout LD D,A ;#40..#7F=mega RAM 1,#80..#BF=mega RAM 2,#C0..#FF=mega 3 ;#20..#3F=mega RAM 0 second half CP #20 JR C,w7434 ;jr if main RAM OUT (#80),A ;select mega RAM LD D,#80 ;xmem bit high w7434 IN A,(#FB) PUSH AF LD A,D OUT (#FB),A POP AF ;orig page POP DE ;orig RET L743D LD L,D ;calculate page form from t/s in DE LD H,#00 LD B,H LD C,L ADD HL,HL ADD HL,HL ADD HL,BC ADD HL,HL ;track*10 LD C,E DEC C LD A,C CP #0A JP NC,L504A ;"end of file" if sector not 1..10 ADD HL,BC ;sector number 0 to disc limit-1 PUSH HL LD C,#1F XOR A ;NC DEC A ;A=#FF w7454 INC A SBC HL,BC JP NC,w7454 POP HL ;sect no 0 to limit-1 LD C,A ADD HL,BC ;sect=sect+int(sect/31) to avoid every 32nd sect INC HL ;avoid sect 0,32,64,96 etc ADD HL,HL ;HL=sect no.*2 LD A,H LD H,L LD L,B ;AHL=20-bit displacement (512*sect) ;now get A=pg disp, HL=offset L7462 RL H ;transform 20-bit number in AHL to page, addr (#8000..#BFFF) RLA RL H RLA ;NC. page now OK RR H SCF RR H ;addr now OK in #8000..#BFFF form RET w746E CALL L44B4 ;ram disc save block, save first block LD BC,#0000 ;sect count=0 JR w74A6 w7476 EQU $ ; PUSH DE ;prev trk CALL L47F2 ;check bytes remaining, sub 511 EX DE,HL LD HL,(L7C05) ;src JR C,w74AC ;JR if 510 or less bytes to go - prepare last sct INC DE ;correct for sub 511 ->sub 510 now LD (L7C02),DE LD DE,d7D13 ;temp store LD BC,#01FE LDIR ;copy data to temp buffer in common memory CALL L7603 LD (L7C05),HL ; POP DE ;prev trk CALL L495F ;fast find next free sect in SAM LD L,D LD H,E LD (d7D13+510),HL EX DE,HL CALL L6CAB ;get t/s in D/E CALL L44B4 LD BC,(L4128) INC BC ;inc sector count w74A6 LD (L4128),BC JR w7476 w74AC EQU $ ; POP DE ;prev trk LD BC,(L7C02) LD (IX+#0E),B LD (IX+#0D),C LD DE,d7D13 PUSH BC LDIR ;last part-buffer copied EX DE,HL ;buffer dest in HL POP BC ;ptr JP L494E w74C1 CP #08 ;format ram disc. A=dstr1 JP NC,L503E ;"no such drive" DI LD (L7C0B),A XOR A OUT (#FB),A ;sys page at #8000 CALL L72CA ;get tks/drive AND A JR Z,L74F7 ;JR if new ramdisc CALL w759F ;pt to table start - 50 bytes of pages used+0 in first page LD DE,d7D13 PUSH DE LD BC,52 LDIR ;copy to buffer POP HL OUT (#FB),A ;orig LD D,#5100/256+40H ;alloct table L74E4 LD A,(HL) INC HL LD E,A AND A ;terminator is 0 JR Z,L74F7 ;exit if all used pages de-allocted AND #E0 JR NZ,w74F1 ;JR if mega RAM page LD (DE),A ;free page in alloct JR L74E4 w74F1 LD A,E CALL L767A ;free bit in mega RAM map JR L74E4 L74F7 LD HL,d7D13 ;pt to table start - 50 bytes of pages used LD B,52 XOR A w74FD LD (HL),A INC HL DJNZ w74FD ;clear table LD A,(L4212) ;tks/disc AND A JP Z,w758A ;just erase any existing ram disc if tks=0 LD D,A DEC D LD E,#0A ;last sector on disc CALL L743D ;get page form of t/s addr INC A LD C,A ;pages needed CALL L769D ;count free pages in A and B CP C JP C,w759B LD A,C PUSH AF ;pages needed LD B,#00 LD HL,d7D13 ADD HL,BC ;last required posn in table,+1 POP BC ;B=pages needed LD DE,#5100+up+#20 L7524 CALL w765B ;search for free MR page and reserve it JR Z,w7538 ;JR if page free (A=page) DEC E ;internal RAM page no./alloct ptr XOR A OUT (#FB),A ;sys page in at #8000 LD A,(DE) AND A JR NZ,L7524 ;JR if page not free LD A,(L7C0B) OR #D0 LD (DE),A ;reserve in alloct LD A,E w7538 DEC HL ;next table posn LD (HL),A ;page number to ram disc's list CALL L7429 EXX LD HL,w763D LD DE,#8002 LD BC,e763D-w763D LDIR ;create mover code in unused "sector" of each page LD HL,#8020 LD B,H ;B=128 w754D LD (HL),#ED INC HL LD (HL),#A0 INC HL DJNZ w754D ;create 128 LDIs LD (HL),#3D ;DEC A INC HL LD (HL),#C2 ;JP NZ INC HL LD (HL),#20 INC HL LD (HL),#80 ;#8020 INC HL LD (HL),#C9 ;RET LD B,#3E ;max number of possible dir entries in page LD HL,#8200 ;first possible dir entry w7568 LD (HL),C INC L LD (HL),C ;ensure it starts 00/00 so "never used" DEC L INC H ;next entry DJNZ w7568 EXX DJNZ L7524 LD HL,#82FF CALL L54EF ;set dtks and rnd word and name LD HL,d7D13 LD DE,#8125 ;after multi-LDI code LD BC,#0034 LD A,(HL) LDIR ;copy page table from temp buffer to 1st page PUSH AF CALL L72D2 ;first page addr POP AF LD (HL),A ;set first page var w758A CALL L72CA ;get addr of tks/disc LD A,(L4212) ;desired tks/disc CP 80 JR C,w7596 ADD A,#30 ;e.g. 80->128, 160->208 w7596 LD (HL),A ;NZ so disc usable now, or zero so non-existent XOR A OUT (#FB),A ;ensure xmem bit low RET w759B CALL L5097 DEFB 1 w759F XOR A w75A0 LD C,A CALL L7425 ;sel first page, exit with A=orig LD HL,#8125 ;start of full table LD B,#00 ADD HL,BC ;pt to required entry RET w75AB SCF ;store ram disc path name w75AC DI ;move ram disc path name EX AF,AF' ;entry: (drive) set, NC if fetch from rd, CY if store CALL L72CA ;get A=tracks/drive AND A JP Z,L503E ;"no such drive" if tks=0 CALL L7425 ;sel first page, exit with A=orig LD HL,#8160 LD DE,L40D0+2 EX AF,AF' JR NC,w75C2 EX DE,HL w75C2 LD BC,#0026-2 LDIR ;copy path name from ram disc to/from temp buffer LD A,(L7C0B) ADD A,#30 LD L,A LD H,":" LD (L40D0),HL EX AF,AF' OUT (#FB),A RET w75D6 LD HL,(L7C05) ;ram disc load block sr, dest CALL w762D JR NC,w75EE LD BC,510 CALL w73C3 LD A,(d7D13+510) LD B,A LD A,(d7D13+511) LD C,A JR w75F1 w75EE CALL w760D ;load 510 bytes to dest from t/s D/E w75F1 LD HL,(L7C05) LD DE,#01FE ADD HL,DE CALL L7603 LD (L7C05),HL LD D,B LD E,C ;next t/s JP L4CD9 L7603 BIT 6,H RET Z CALL L3FF2 LD (L412E),A RET w760D PUSH DE ;t/s PUSH HL ;main memory ptr - dest CALL L73E2 ;pt HL to src in ramd, page in POP DE ;dest PUSH AF ;orig page LD C,A ;main mem page SCF ;"510" EX AF,AF' DEC C ;to be paged in at #4000 IN A,(#FA) LD B,A XOR C ;A=value for port 250 to page in dest at #4000 AND #E0 XOR C CALL #8002 LD B,(HL) INC HL LD C,(HL) ;next t/s POP AF OUT (#FB),A POP DE ;current t/s RET n762A CALL L4E78 ;pt HL to buff (either dram or #8000..#BFFF) w762D LD A,H CP #80 RET C ;ret if HL in dram PUSH HL LD BC,#41FF ADD HL,BC POP HL RET C ;CY if HL will cross page boundary - use buff RES 7,H SET 6,H RET ;addr in #4000..#7FFF area now w763D LD (#8000),SP ;at #8002 LD SP,#8200 OUT (#FA),A ;page in dest in section B PUSH BC ;orig port 250 value EX AF,AF' LD A,#04 ;4 moves of 128 bytes JR C,w7650 ;JR if 510 bytes wanted CALL #8020 ;mover - do 128*4=512 AND A ;NC w7650 CALL C,+#8024 ;move #1FE bytes POP AF OUT (#FA),A LD SP,(#8000) RET e763D EQU $ ;search for free MR page ;exit: if Z, A=page number, page reserved w765B XOR A w765C DEC A CALL w7668 JR Z,L7672 ;JR if free CP #20 JR NZ,w765C AND A ;NZ RET ;test mega ram bit (page). return Z if page "A" free, NZ if in use or non- ;existent. table set up at boot time, all #FFhs if no megarams ;entry:A=#00..#FF w7668 PUSH HL PUSH AF CALL L7685 ;get addr, mask AND (HL) ;Z if bit low (free) POP HL LD A,H POP HL RET L7672 PUSH AF ;set mega RAM bit A. all regs saved PUSH HL CALL L7685 OR (HL) ;NZ JR w7681 L767A PUSH AF ;reset mega RAM bit A. all regs saved PUSH HL CALL L7685 CPL ;set mask bit low AND (HL) w7681 LD (HL),A POP HL POP AF RET ;get mega ram table addr in HL, mask in A (bit set hi) ;entry: A=bit ;exit: HL and A set, other regs saved L7685 PUSH BC LD B,A RRA RRA RRA AND #1F ;div by 8 LD C,A LD A,B AND #07 INC A LD B,A ;B=1 to 8 for bit 7..0 LD A,#01 w7694 RRCA DJNZ w7694 ;A=#80 if B was 1, #40 if B was 2... LD HL,dvar+118 ADD HL,BC ;pt to byte (B=0) POP BC RET L769D CALL w76B0 ;get free mega RAM pages in E (0..224) LD B,E LD HL,#5100+up+32 w76A4 CALL L4F8D ;read A from sys page AND A JR NZ,w76AB INC B ;inc free pg cnt w76AB DEC L JR NZ,w76A4 LD A,B RET ;count free mega ram pages - result in DE. BC saved w76B0 LD HL,dvar+118+4 ;+122, avoid use of mega RAM 0 first half LD E,#1C ;bytes to look at w76B5 PUSH BC ;called by boot XOR A LD D,A w76B8 LD C,(HL) INC HL LD B,#08 w76BC RR C JR C,w76C3 INC A ;inc A by number of low (free) bits JR Z,w76C9 ;JR if hit 256 when called from boot w76C3 DJNZ w76BC ;do 8 bits DEC E JR NZ,w76B8 ;do 32 or 28 bytes DEC D w76C9 INC D LD E,A POP BC RET ;HOOKS.Z80 t76CD EXX ;hook 169 - print token A CP #FF ;\get HL=passed in xptr JR Z,w76F9 SUB #F6-funo ;#EF PUSH AF PUSH HL ;xptr CALL L4F22 DEFW #5C3B RRA CALL NC,L567B POP BC ;xptr CALL L4F2D DEFW #5AA3 POP BC LD HL,d7754 L76E9 CALL L76EF ;entry here avoids leading space. B=char JP L567B L76EF LD A,(HL) INC HL RLA JR NC,L76EF DJNZ L76EF JP L5686 ;print msg from HL w76F9 LD (dvar+153),HL ;save xptr till later - avoid print hooks killing error marker LD BC,#00FB IN E,(C) OUT (C),B LD B,E LD HL,(#5C51+up) ;CURCHL SET 7,H RES 6,H LD E,(HL) INC HL LD D,(HL) LD (#5AB5+up),DE ;OPSTORE LD DE,m5896 ;xtra vectors - post #FF hook LD (HL),D DEC HL LD (HL),E OUT (C),B RET t771B PUSH AF ;hook 170 - post #FF print LD BC,(dvar+153) ;\char after #FF CALL L4F2D DEFW #5AA3 ;xptr POP AF CP #30 JR C,L7751 CP #30+funo ;#37 CCF JR C,L7751 ;JR if not new fn else deal with #30+ SUB #2F LD BC,#00FB IN E,(C) OUT (C),B LD B,E LD HL,(#5C51+up) ;CURCHL SET 7,H RES 6,H LD DE,(#5AB5+up) ;OPSTORE LD (HL),E INC HL LD (HL),D ;restore normal o/p addr OUT (C),B LD B,A LD HL,d7754 CALL L76EF ;print new fn name - no leading space AND A ;NC=done it L7751 PUSH AF POP BC RET funo EQU 7 cmno EQU 3 d7754 DEFB #A0 DEFB "T","I","M","E","$"+128 ;#30 $ DEFB "D","A","T","E","$"+128 ;#31 $ DEFB "I","N","P","$"+128 ;#32 $ DEFB "D","I","R","$"+128 ;#33 $ DEFB "F","S","T","A","T"+128 ;#34 N DEFB "D","S","T","A","T"+128 ;#35 N DEFB "F","P","A","G","E","S"+128 ;#36 N ; DEFB "S","C","R","A","D"+128 ;#37 N DEFB "B","A","C","K","U","P"+128 ;247 DEFB "T","I","M","E"+128 ;248 DEFB "D","A","T","E"+128 ;249 ; DEFB "A","L","T","E","R"+128 ;250 ; DEFB "S","O","R","T"+128 ;251 t7785 LD C,#FB ;hook 171 - get token IN B,(C) PUSH BC XOR A OUT (#FB),A LD HL,w77C0 LD DE,#8F00 LD BC,e77C0-w77C0 ;#000E LDIR ;extra code to buffer IN A,(#FA) INC A CALL L3FDF ;page keyword list in at #8000 EXX ; LD DE,(HKDE) LD HL,d7754-1+up LD A,funo+cmno+1 ;#0B, items in list+1 CALL L7BB4 ;jump to DEFW #018A ;JGTTOK POP BC OUT (C),B JR Z,L77BD ;RET if no match CP funo+1 ;#08 JR NC,w77BB ;JR if cmd EX DE,HL AND A SBC HL,DE ADD A,#2F ;FNS=30H+ SCF JR L77BD w77BB ADD A,#BB-funo ;#B4, 247+ L77BD PUSH AF POP BC RET w77C0 POP IY ;copied to #4F00 to deal with fns LD BC,#0011 ADD IY,BC ;pt to 17 bytes further on in tokenise sr POP DE ADD HL,DE EX DE,HL LD (HL),#FF ;fn leader placed in basic line JP (IY) e77C0 EQU $ t77CE EXX ;hook 172 - length function patch INC HL INC HL INC HL LD C,(HL) ;disp to "immed codes" (part of "JR") LD B,#00 ADD HL,BC PUSH HL ;immed codes LD C,#11 ADD HL,BC ;pt to numcont LD C,(HL) INC HL LD B,(HL) ;BC=numcont ; LD A,(HKA) CP #34-#1A ;#1A JR NC,w77E8 ;JR if numeric result LD BC,#0006 ADD HL,BC LD C,(HL) INC HL LD B,(HL) ;BC=strcont w77E8 PUSH AF CALL L7AEE ;over-write addr after hook code on main ROM stack ;with numcont or strcont according to type of result CALL L4CCF POP AF POP HL ;immed codes CP #3F-#1A ;#25, length JR Z,w780C SUB #30-#1A ;#16 JP C,L5DCA CP funo JP NC,L5DCA ADD A,A LD L,A LD DE,d7875 w7804 LD H,#00 ;used by main hook routine. DE=table, L=entry ADD HL,DE LD E,(HL) INC HL LD D,(HL) EX DE,HL JP (HL) w780C LD BC,#000A ADD HL,BC LD C,(HL) INC HL LD B,(HL) ;imfntab LD HL,#0008 ADD HL,BC LD E,(HL) INC HL LD D,(HL) ;imlength IN A,(#FA) OR #40 OUT (#FA),A ;ROM1 on IN A,(#FB) PUSH AF XOR A OUT (#FB),A ;sys page at #8000 EX DE,HL LD DE,#8D80 LD BC,#0078 LDIR LD HL,w7866 LD C,#0F LDIR LD A,#0B LD (#8D80+#6C),A LD HL,#4D80+#36 LD (#8D80+#24),HL POP AF OUT (#FB),A ;orig CALL L4F17 DEFW #5A97 ;chadd INC BC LD A,(BC) CP "#" JR NZ,w7860 CALL L4F00 ;pt to "#" CALL L4F00 ;skip "#" CALL L7BB4 ;jump to DEFW #0118 ;JEXPT1NUM CALL L79F6 JP w6392 ;fnlength w7860 CALL L7BB4 ;jump to DEFW #4D80 ;call modified "LENGTH" code in cdbuf RET w7866 BIT 6,H ;code to patch "LENGTH" for LENGTH(0,A$) error on page boundary JR Z,w7873 RES 6,H LD A,(#5123) INC A LD (#5123),A e7866 EQU $ w7873 JR $-#56 ;??? d7875 DEFW f7A70 ;TIME$ DEFW f7A74 ;DATE$ DEFW f797D ;INP$ DEFW f7883 ;DIR$ DEFW f79FC ;FSTAT DEFW f78B6 ;DSTAT DEFW f7954 ;FPAGES ; DEFW ;SCRAD f7883 CALL L64CB ;get "any" name, gtdef CALL L4F00 CP "(" JR Z,w7892 CALL L79F6 JR w78A0 w7892 CALL L604D LD C,")" CALL L4EFC CALL L79F6 CALL L71BC w78A0 CALL L5B16 ;dir to buffer LD HL,(L412C) LD DE,#A000 AND A SBC HL,DE ;HL=text len (10 per name) LD B,H LD C,L IN A,(#FB) CALL L7A95 JP L4820 ;DSTAT(d,x) - status of disc d. if d=*, use default drive ;x=1 gives 0 if write protected or no free slots, else gives free space ;x=2 gives 1 if write protected ;x=3 gives free space (sects*510-9) ;x=4 gives free slots ;x=5 gives total files ;x=6 gives files in current dir ;x=7 gives dtks ;x=8 gives current drive f78B6 CALL L7978 ;insist "(" CALL L5FF9 ;drive number to dstr1 CALL L79E5 ;skip comma, get x in BC. no RET if syntax LD A,C ;param CP #08 LD A,(L4136) ;drive JR Z,wB8F8 ;stack current drive if param=8 SUB #02 JR NZ,L78D7 LD A,(dvar+2) AND A JR NZ,L78D7 ;JR if drive 2 exists CALL w7A64 ;get AEHL=-1 w78D4 JP L638B ;stack-1 L78D7 CALL L46EC LD B,A PUSH BC CALL L7A58 POP BC JR Z,w78D4 ;if no disc, stack -1 LD A,B ;drive DEC C JR NZ,w78EF ;JR unless special wp/free slot/space CALL L795F LD A,#00 JR NZ,L794E ;zero space free if write prot JR w78FE w78EF DEC C JR Z,w794B ;JR to check write protect LD A,C CP #06 LD A,(L7C0B) wB8F8 JR Z,L794E LD A,C wB8FB JP NC,L5F12 w78FE PUSH AF IN A,(#FB) PUSH AF CALL L5B09 ;zero vars CALL L5B16 ;dir to buffer CALL L5B24 ;get HL=free sects, DE=free slots ADD HL,HL ;free 256-bytes POP AF OUT (#FB),A POP AF EX DE,HL AND A JR NZ,w791B LD A,H OR L w7916 JP Z,L63C9 ;no space if no slots JR w7922 w791B CP #02 JR Z,w7916 ;stack free slots DEC A JR NZ,w7939 w7922 LD A,D OR E JR Z,L794E ;JR if no free sectors LD L,#00 LD A,D LD H,E ;AHL=sects*512, DE=sects*2 AND A SBC HL,DE SBC A,#00 ;AHL=sects*510 LD DE,#0009 SBC HL,DE SBC A,#00 ;allow for header JP L63BF w7939 LD HL,(L421A) SUB #02 JR Z,L7951 LD HL,(L421C) DEC A JR Z,L7951 LD A,(dvar+16) JR L794E w794B CALL L795F L794E LD L,A LD H,#00 L7951 JP L63C9 f7954 CALL L4F00 ;free pages fn CALL L79F6 CALL L769D JR L794E L795F CP #03 ;entry: A=drive LD A,#00 JR NC,w7975 ;JR if ram disc CALL L4718 ADD A,#02 LD C,A OUT (C),A ;impossible sector CALL L4476 CALL L449E RLCA RLCA ;bit 6 (write prot) to bit 0 w7975 AND #01 RET L7978 LD C,"(" JP L4EF9 f797D CALL L7978 ;INP$(#stream,no.of chars) function LD C,"# ;\insist "(" CALL L4EFC CALL w79E2 ;get chars in BC, stream in DE. no RET if syntax time LD HL,#0010 AND A SBC HL,DE JP C,L6D7A ;limit stream to 0-16 DEC BC ;Z->#FFFF LD A,B CP #40 JP NC,L5F12 PUSH BC CALL L4F17 DEFW #5C51 ;curchl POP HL PUSH BC IN A,(#FB) PUSH AF INC HL ;HL=1-#4000 PUSH HL LD A,E CALL L7BB4 ;jump to DEFW #0112 ;JSETSTRM POP BC CALL L7BB4 ;jump to DEFW #0109 ;JWKROOM PUSH BC PUSH DE w79B3 PUSH BC PUSH DE IN A,(#FB) PUSH AF XOR A OUT (#FB),A ;sys page CALL L66CF JP NC,L504A ;EOF LD D,A POP AF OUT (#FB),A ;wkroom LD A,D POP DE POP BC LD (DE),A INC DE DEC BC LD A,B OR C JR NZ,w79B3 POP DE ;start POP BC ;len IN A,(#FB) EX AF,AF' POP AF OUT (#FB),A ;orig EX AF,AF' CALL L7A95 ;stack ADEBC POP BC ;orig curchl CALL L4F2D DEFW #5C51 ;curchl RET ;eval number, comma, number, bracket. abort if syntax, else ;return 1st num in DE, 2nd in BC w79E2 CALL L6132 ;get num in HL, Z if syntax L79E5 PUSH HL LD C,"," CALL L4EFC CALL L6132 PUSH HL LD C,")" CALL L4EFC POP BC ;2ND POP DE ;1ST L79F6 CALL L4EBD RET NZ POP HL RET ;file status function ;FSTAT("NAME",1)=file number ;FSTAT("NAME",2)=file length ;FSTAT("NAME",3)=file type ;FSTAT("NAME",4)=file type and protect/hide bits f79FC CALL L64D3 CALL L7978 ;insist on "(" CALL L6050 CALL L79E5 ;comma, number, ")", abort PUSH BC ;number DEC BC ;legal values now 0-3 LD HL,#0003 AND A SBC HL,BC JP C,L5F12 CALL L71BC CALL L7A58 POP BC JP Z,L638B ;stack -1 if no hole or non-formated ramdisc PUSH BC CALL L4E7F ;look for named file, point POP BC LD A,#00 JR NZ,L7A32 ;JR if not found - stack 0 DEC C JR Z,w7A35 LD A,(HL) ;type DEC C JR Z,w7A3D ;JR if param was 4 DEC C JR NZ,L7A32 AND #1F L7A32 JP L794E w7A35 CALL L4730 ;convert t/s in D/E to a number in BC LD H,B LD L,C n7A3A JP L63C9 w7A3D LD DE,#0000 AND #1F CP #05 LD A,#03 JR Z,w7A51 ;JR if 48k snap, ADE=48k LD BC,#00EF ADD HL,BC ;point to len data in buffer (dir entry) LD A,(HL) INC HL LD E,(HL) INC HL LD D,(HL) w7A51 EX DE,HL ;AHL=page form CALL L5F05 ;get 20-bit number JP L63BF ;SCRAD CALL GTNC ;remarked in original ; CALL FABORT ; CALL NRRD ; DW CUSCRNP ; AND #1F ; INC A ; LD HL,#8000 ; JR STK20B L7A58 LD A,(L7C0B) CP #03 JR C,w7A68 CALL L72CA AND A RET NZ ;RET if ram disc formatted w7A64 LD H,A LD L,A JR w7A6D w7A68 LD D,A ;side 1 (track <80) CALL L46AC ;test for index hole. Z if none, A=0, HL=0 RET NZ ;RET if hole found w7A6D DEC HL ;value LD E,H ;sgn byte. A=0 and EHL=#FFFFFF if no hole RET ;Z f7A70 LD HL,dvar+96 ;time start DEFB #FD ;dummy LD IY,dvar+81 f7A74 LD HL,dvar+81 ;date start PUSH HL ;time/date fn common CALL L4F00 POP HL ;str start CALL L79F6 CALL L6FA2 LD BC,#0008 ;str len JR w7A8D t7A87 CALL L64D3 ;hook call for PATH$ CALL L72AB w7A8D SET 7,H RES 6,H EX DE,HL IN A,(#FA) INC A ;DOS page L7A95 CALL L7BB4 ;jump to DEFW #0127 ;JSTKSTORE RET t7A9B PUSH AF ;hook 173 - via cmdv - SAVE/LOAD/MERGE/VERIFY CALL L4F17 DEFW #5BDA ;cmd addrt to BC ; LD A,(HKA) POP AF CALL L4F38 DEFW #5B74 ;write curcmd SUB #90 ADD A,A LD L,A LD H,#00 ADD HL,BC LD C,#FA IN B,(C) SET 6,B OUT (C),B ;ROM1 on LD E,(HL) INC HL LD D,(HL) IN A,(#FB) PUSH AF XOR A OUT (#FB),A PUSH DE ;SLVM addr LD HL,o7B10 LD DE,#9000-e7B10+o7B10 ;#8FC3, dest in buffer for merge patch code LD BC,e7B10-o7B10 ;#003D LDIR ;DE ends at #9000 POP HL LD C,#58 LDIR ;DE adv to #8158, src to SLVM+#58 PUSH HL LD HL,L7AF4 LD C,o7B10-L7AF4 ;#1C LDIR POP HL LD (#9000+#59),HL ;patch JP to SLMV+#58 LD HL,(#9000+#25) ;read SBFSR addr LD (#9000+#5C),HL ;patch call SBFSR replacement LD HL,#5000+#5B LD (#9000+#25),HL ;patch call SBFSR POP AF OUT (#FB),A ;orig LD BC,#5000-e7B10+o7B10 ;#4FC3, start of merge patch in buffer ;over write main rom stack - first addr with BC. ;OWSTK LD HL,(ENTSP) ; INC HL ; INC HL ; LD E,(HL) ; INC HL ; LD D,(HL) ; EX DE,HL ;HL=main rom stack ptr read from DOS stack L7AEE LD HL,(L7FFC) JP L4F6F L7AF4 JP #0000 CALL #0000 ;SBFSR LD A,C LD DE,#4F60 LD (DE),A DEC DE ;#4F5F LD HL,#4F4F LD BC,#0050 ;for #4F00-#4F4F copied to #4F10-#4F5F LDDR ;copy to safety in case e.g. "S" code UDG " " INC DE ;#4F10 LD C,A CP #0F RET C LD C,#0E RET ;correct merge bug (if too many nums merge for gap size between numend and ;and savars) o7B10 LD A,(#5B74) CP #96 ;MERGE JR NZ,L7B47 LD HL,(#5A82) LD DE,(#5A85) LD A,(#5A84) LD C,A LD A,(#5A81) CP C JR Z,w7B2D ;JR if same page RES 7,D SET 6,D ;sub #4000 AND A w7B2D SBC HL,DE ;get gap size LD A,H CP #06 JR NC,L7B47 ;JR if lots of space to merge nums (1.5kB or more) IN A,(#FB) PUSH AF LD A,C OUT (#FB),A ;page in numendp XOR A LD BC,#0610 ;ABC=space LD HL,(#5A85) ;make room here CALL +#010C POP AF OUT (#FB),A L7B47 RST #20 LD BC,#5FFA OUT (C),B ;ROM1 on (cmr turns off ROM1) e7B10 EQU $ t7B4D CALL L79F6 ;hook 174 - run/clear patch IN A,(#FB) PUSH AF CALL L4F17 DEFW #5A88 ;NVARS LD A,B CP #BC JR C,w7B6B ;nvars is too close to end of page - expand CALL L7B97 ;post prog gap to put nvars in next page XOR A LD BC,#0400 CALL L7BB4 ;jump to DEFW #010C ;JMKRBIG JR L7B93 ;nvars now at least #C000->#8000 in next page w7B6B CP #85 JR C,L7B93 ;RET if nvars too close to page start for any post- ;prog gap to be closed. PUSH BC ;nvars CALL L7B97 EX DE,HL ;DE=prog end CALL L4F22 DEFW #5A87 POP HL LD C,A ;CHL=nvars IN A,(#FB) ;prog end page XOR C AND #1F JR Z,w7B84 ;JR if normal subtract OK - pages match SET 6,H ;add #4000 to nvars w7B84 SCF ;normal gap=1, so SCF for normal=0 SBC HL,DE JR Z,L7B93 ;RET if no gap to close LD B,H LD C,L EX DE,HL ;reclaim at prog end CALL L7BB4 ;jump to DEFW #0163 ;JRECLAIM LD (HL),#FF ;ensure prog terminated L7B93 POP AF OUT (#FB),A RET L7B97 CALL L4F17 DEFW #5AA0 ;gap after program to move nvars to next page PUSH BC CALL L4F22 DEFW #5A9F OUT (#FB),A POP HL w7BA5 LD D,(HL) INC D RET Z ;RET if terminator INC HL INC HL LD E,(HL) INC HL LD D,(HL) INC HL ADD HL,DE CALL L3FEF JR w7BA5 ;call main ROM (CMR) - rewritten to allow hooks to be used by routines called by cmr L7BB4 EXX POP HL LD E,(HL) INC HL LD D,(HL) INC HL PUSH HL LD HL,(L7FFC) ;main ROM SP on entry to DOS PUSH HL LD HL,w7BF4 PUSH HL LD C,A IN A,(#FB) LD H,A IN A,(#FA) LD B,A INC A AND #1F OUT (#FB),A ;DOS at #8000 also JP w7BD2+up w7BD2 LD A,#1F DI OUT (#FA),A ;sys page at #4000 LD IY,(#5C59) ;DOSSTK LD A,H ;orig urport LD HL,#0000 ADD HL,SP LD (#5C59),HL ;so calls to dos do not hit current stack LD SP,(L7FFC+up) ;new stack just below main ROM stack EI PUSH HL ;orig SP PUSH BC ;B=orig lrport PUSH IY ;orig dosstk LD HL,m58A4 ;RET addr to paging sr after defkeys PUSH HL PUSH DE ;routine addr to call JP m589F ;page in orig urport, set A reg, RET w7BF4 POP IY LD (L7FFC),IY ;orig in case hook use changed it RET ;avoid stack creep ;continue from boot sector w7BFB LD A,#5B ;jumped to at boot time (inip3+up) LD BC,#D65B ;look for #5BD65B of LD DE,(UMSG) LD HL,#3D00 ;at #3DB1 in ROM30 CALL L7C52+up ;changable address??? LD DE,-4 ADD HL,DE ;postff addr PUSH HL LD HL,w7D4F+up ;o5896+up??? LD DE,o5896 LD BC,e5896-o5896 LDIR ;data to after dklim POP HL LD (m589B+1),HL ;return address LD HL,#3A31 ;:/1 LD (L7F13+up),HL INC L LD (L7F39+up),HL ;init path for drive 2 LD A,(dvar+150+up) ;clock port LD C,A LD B,#F0 ;control reg LD A,#05 ;%0101 NOT TEST/24H/RUN /REST OUT (C),A ;rest hi OUT (C),A ;we can set 24h now LD A,#04 ;%0100 NOT TEST/24H/RUN /NOT REST OUT (C),A LD HL,L7FF0 LD (#5C59),HL ;DOSSTK LD A,#01 LD (L7C0B+up),A LD A,#CF LD BC,#82C9 ;??? LD HL,#E200 ;#E2B6 in ROM30 CALL L7C52+up LD DE,#0004 ADD HL,DE LD (m4BE6+1),HL ;LOAD/VERIFY hook patch RET L7C52 LD DE,#0000 w7C55 PUSH BC ;chars 2 and 3 LD B,A w7C57 LD A,D LD D,E INC HL LD E,(HL) CP B JR NZ,w7C57 POP BC EX DE,HL SBC HL,BC EX DE,HL JR NZ,w7C55 DEC HL DEC HL RET ;mega RAM init - used at boot time when DOS at #8000. call MRINIT+up w7C68 DI LD A,(#5BC2) ;DOSFLaG - DOS page DEC A OUT (#FA),A ;DOS paged in at #4000 as well as #8000 (BOOT) LD (L4212),SP LD SP,#8000 CALL w7CB8 ;call sr in sect B. exit with DE=MR pages LD HL,(L4212) LD BC,#5FFA OUT (C),B ;normal page at #4000 (ROM1 on) LD SP,HL LD A,D OR E RET Z ;RET if no free pages EX DE,HL ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL ;*16=k (16-4096) LD (L4212+up),HL RST #28 DEFB #2A ;LKADDRW - put on stack DEFW L4212+up DEFB #33 ;EXIT LD A,#02 CALL +#0112 ;JSETSTRM CALL +#017E ;JSTRS CALL +#0013 ;print it LD DE,txtexm+up LD BC,txtexme-txtexm JP #0013 ;print BC from DE txtexm DEFM "K External Memory" DEFB #0D txtexme EQU $ ;count external memory w7CB8 IN A,(#FB) PUSH AF OR #80 ;external mem bit on OUT (#FB),A LD C,#00 ;start at page 0 w7CC1 LD A,C OUT (#80),A ;select mega RAM (if present) LD HL,#8000 XOR A LD (HL),A CP (HL) JR NZ,L7CF4 ;JR if cannot be set to zero INC A LD (HL),A CP (HL) JR NZ,L7CF4 ;JR if cannot be set to #FF LD A,C CALL L767A ;res mega RAM bit - free LD HL,#0000 ADD HL,SP EXX LD SP,#C000 LD HL,#0000 LD BC,#0004 L7CE3 PUSH HL PUSH HL PUSH HL PUSH HL PUSH HL PUSH HL PUSH HL PUSH HL ;clear 16 bytes DJNZ L7CE3 ;do it 256 times=4kB DEC C JR NZ,L7CE3 ;do 4kB four times EXX LD SP,HL JR w7CF8 L7CF4 LD A,C CALL L7672 ;set mega RAM bit A - not present w7CF8 INC C JR NZ,w7CC1 ;do pages #00-#FF POP AF OUT (#FB),A ;external mem bit off LD HL,dvar+118 LD E,#20 ;bytes to look at JP w76B5 ;count free pages ;serial i/o srs for opentype files, copied to #4BA0 w7D06 EQU $ ORG o4BA0 ;moved #0049 bytes m4BA0 DEFB #40 ;"block move supported" JR m4BA6 m4BA3 RST #08 DEFB #97 ;o/p BC from DE RET m4BA6 RST #08 DEFB #A7 RET m4BA9 RST #08 DEFB #A8 EXX PUSH BC POP AF RET m4BAF DEFB #00 m4BB0 CP #F7 ;print tokens RET C POP HL LD HL,(#5AA3) RST #08 DEFB #A9 ;hptv - DOS print token RET m4BBA CP #3F-#1A ;#25, evaluator patch JR Z,m4BC1 ;RET unless "LENGTH" CP #3B-#1A ;#21, deal with <#3B (PI) RET NC m4BC1 POP HL RST #08 DEFB #AC ;hklen - no return ;CMDV patch for SLVM m4BC4 LD HL,L7FF0 ;exeute command LD (#5C59),HL ;DOSSTK CP #94 ;SAVE RET C ;RET if less than "SAVE" CP #98 JR NC,m4BD5 ;JR if not SLMV POP HL RST #08 DEFB #AD ;hslmv - "RET" to modified code in buffer m4BD5 CP #B3 ;CLEAR JR Z,m4BDB CP #B0 ;RUN RET NZ m4BDB PUSH AF RST #08 DEFB #AE ;RUN/CLEAR patch POP AF RET ;HLVTG JP 0 ;ROM LOAD/VERIFY ;net patches m4BE0 AND A ;NC, where called from??? DEFB #3E ;"JR+1" m4BE2 SCF EXX LD A,#FF m4BE6 JP #0000 ;ROM LOAD/VERIFY ;o/p addr used when char after #FF is printed, at xtra e4BA0 EQU $ ORG $-o4BA0+w7D06 w7D4F EQU $ ORG o5896 ;moved m5896 RST #08 DEFB #AA ;HPFF EXX PUSH BC POP AF m589B JP C,+#0000 ;JP postff if DOS didn't handle it RET ;just RET if done it m589F OUT (#FB),A ;orig urport LD A,C ;orig A EXX RET m58A4 EX AF,AF' POP IY LD (#5C59),IY ;DOSSTK POP AF ;ORIG LRPORT POP IY DI LD SP,IY JP #0286 ;OUT (250),A: EI: EX AF,AF': RET ;match tokens m58B4 RST #08 ;make keyword DEFB #AB EXX PUSH BC POP AF RET Z RET NC ;needed? JP L4F00 ;extension to deal with fns e5896 EQU $ ORG $-o5896+w7D4F DEFS 24 end EQU $ ;form #7D77 only zeros follow