; HBBSUBS.Z80 v1 17 Apr 88 ; ; Copyright on the material herein is claimed by Russ Pencin and others. ; ; Modified by Irv Hoff, based on Russ Pencin's PBBS, based on Simon ; Ewin's EMX. ;======================================================================= ; ; Data area ; RRW: DEFB 0 RFCB: DEFW FCB RRNO: DEFW 0 RRSZ: DEFW 0 RBUF1: DEFW RNDBUF RRW2: DEFB 0 RFCB2: DEFW FCB2 RRNO2: DEFW 0 RRSZ2: DEFW 0 RBUF2: DEFW RNDBUF ROREAD: DEFB 0 ROFCB: DEFW 0 ROURN: DEFW 0 ROURL: DEFB 0 ROURH: DEFB 0 ROUB: DEFW 0 ROFRP: DEFW 0 ROFRL: DEFB 0 RORNP: DEFW 0 ROWECR: DEFB 0 ROBUF: DEFS 128 MLEN: DEFB 0 ILEN: DEFB 0 ULC: DEFB 0 WRP: DEFB 0 INBUF: DEFB 0 DEFS 80 TMPDAT: DEFW 0 TMPD2: DEFB 0 IXSAVE: DEFW 0 IYSAVE: DEFW 0 ; ; Days to the end of a given month ; DATTAB: DEFW 31 ; Jan DEFW 59 ; Feb DEFW 90 ; Mar DEFW 120 ; Apr DEFW 151 ; May DEFW 181 ; Jun DEFW 212 ; Jul DEFW 243 ; Aug DEFW 273 ; Sep DEFW 304 ; Oct DEFW 334 ; Nov ; P10: DEFW 10000 ; ;----------------------------------------------------------------------- ; ; Error statements ; REM1: DEFB ' ++ Read unwritten error ++',CR,LF DEFB 'BDOS Function 33, Error Code 01',0 ; REM3: DEFB '++ Can''t close extent error ++',CR,LF DEFB 'BDOS Function 33, Error Code 03',0 ; REM4: DEFB '++ Read unwritten extent error ++',CR,LF DEFB ' BDOS Function 33, Error Code 04',0 ; REM5: DEFB '++ Unable to create directory entry' DEFB ' - Directory full ++',CR,LF DEFB ' BDOS Function 34, Error Code 05',0 ; REM6: DEFB '++ Unable to complete operation - this Disk is full ' DEFB '++',CR,LF,'++ to recover restore .BAK files and make ' DEFB 'more room ++',CR,LF DEFB ' BDOS Function 33 or 34, Error Code 06',0 ; CCOPYM: DEFB CR,LF,' HBBS subroutines v4 01/22/88',CR,LF,0 ;..... ; ; BDOS call preserving IX and IY ; SPBDOS: PUSH IX PUSH IY CALL BDOS POP IY POP IX RET ;..... ; PUT: LD A,0 LD (RRW),A LD (RRNO),HL JR RANDOM ; PUT2: LD A,0 LD (RRW2),A LD (RRNO2),HL JR RANDM2 ;..... ; GET: LD A,0FFH LD (RRW),A LD (RRNO),HL JR RANDOM ;..... ; GET2: LD A,0FFH LD (RRW2),A LD (RRNO2),HL ; RANDM2: PUSH IY PUSH IX LD HL,RRW2 CALL RO OR A JP NZ,RNDERR POP IX POP IY RET ;..... ; RANDOM: PUSH IY PUSH IX LD HL,RRW CALL RO OR A JP NZ,RNDERR POP IX POP IY RET ;..... ; RO: LD DE,ROREAD LD C,9 CALL MOVE LD HL,(ROURL) LD A,L AND 7FH OR A LD A,0 JP NZ,RONE DEC A ; RONE: LD (ROWECR),A EX DE,HL LD HL,(ROURN) CALL MLDL PUSH DE PUSH HL LD A,L AND 7FH LD C,A LD B,0 LD HL,ROBUF ADD HL,BC LD (ROFRP),HL LD B,A LD A,80H SUB B LD (ROFRL),A LD B,A LD A,(ROURH) OR A JP NZ,ROFLOK LD A,(ROURL) CP B JP NC,ROFLOK LD (ROFRL),A ; ROFLOK: LD A,(ROWECR) LD B,A LD A,(ROREAD) CPL AND B LD (ROWECR),A POP HL POP DE LD C,7 ; ROS: CALL SDLR DEC C JP NZ,ROS LD A,D OR E JP NZ,ROERO EX DE,HL LD HL,(ROFCB) LD BC,0021H ADD HL,BC LD (RORNP),HL LD (HL),E INC HL LD (HL),D LD C,SETDMA LD DE,ROBUF CALL SPBDOS LD A,(ROWECR) OR A JP NZ,ROMNF LD HL,(ROFCB) EX DE,HL LD C,RRDM ; Read random CALL SPBDOS CP 5 CALL C,ROCIE OR A RET NZ ; ROMNF: LD HL,(ROUB) EX DE,HL LD HL,(ROFRP) LD A,(ROFRL) LD C,A LD A,(ROREAD) OR A JP NZ,RORD1 EX DE,HL ; RORD1: CALL MOVE LD A,(ROREAD) OR A JP Z,ROWR1 EX DE,HL ; ROWR1: LD (ROUB),HL LD A,(ROREAD) OR A JP NZ,RORD3 LD C,WRDM ; Write random, zero fill LD HL,(ROFCB) EX DE,HL CALL SPBDOS OR A RET NZ ; RORD3: LD HL,(ROURL) LD A,(ROFRL) LD E,A LD D,0 CALL SUBHL LD A,H OR L RET Z LD (ROURL),HL LD C,L LD DE,80H CALL SUBHL JP M,ROLT12 LD C,80H ; ROLT12: LD A,C LD (ROFRL),A LD HL,ROBUF LD (ROFRP),HL LD HL,(RORNP) LD E,(HL) INC HL LD D,(HL) INC DE LD A,D OR E JP NZ,ROSRN LD A,6 RET ;..... ; ROSRN: LD (HL),D DEC HL LD (HL),E LD A,(ROWECR) OR A JP NZ,ROMNF LD A,(ROREAD) OR A JP NZ,RORD2 LD A,(ROFRL) CP 80H JP Z,ROMNF ; RORD2: LD C,RRDM ; Read random LD HL,(ROFCB) EX DE,HL CALL SPBDOS JP ROMNF ;... ; ROERO: LD A,4 RET ;... ; ROCIE: LD B,A LD A,(ROREAD) OR A LD A,B RET NZ XOR A RET ;..... ; MLDL: LD BC,0 PUSH BC LD A,H OR L JP Z,MLDLZ LD A,D OR E JP Z,MLDLZ LD A,D CP H JP C,MLDLNX EX DE,HL ; MLDLNX: LD B,D LD C,E LD D,H LD E,L DEC BC ; MLDLA: LD A,B OR C JP Z,MLDLX ADD HL,DE EX (SP),HL LD A,L ADC A,0 LD L,A LD A,H ADC A,0 LD H,A EX (SP),HL DEC BC JP MLDLA ; MLDLZ: LD HL,0 ; MLDLX: POP DE RET ;..... ; DIV16: PUSH AF PUSH BC LD A,H LD C,L LD HL,0 LD B,10H ; DIVLP: RL C RLA ADC HL,HL SBC HL,DE JR NC,NOADD2 ADD HL,DE ; NOADD2: CCF DJNZ DIVLP RL C RLA EX DE,HL LD H,A LD L,C POP BC POP AF RET ;..... ; SUBHL: LD A,L SUB E LD L,A LD A,H SBC A,D LD H,A RET ;..... ; SDLR: OR A EX DE,HL CALL SDLR2 EX DE,HL ; SDLR2: LD A,H RRA LD H,A LD A,L RRA LD L,A RET ;..... ; MOVE: PUSH BC LD B,0 LDIR POP BC RET ;..... ; FILLHL: LD A,(DE) ; LD HL,(DE) LD L,A INC DE LD A,(DE) LD H,A RET ;..... ; ; Returns 0 if string at HL matches string at DE for B bytes ; MATCH: LD A,(DE) SUB (HL) RET NZ INC DE INC HL DJNZ MATCH RET ;..... ; SPINP: PUSH AF LD A,1EH ; LD E,n LD (LDE),A LD A,'*' ; N = asterisk LD (N),A POP AF CALL INPUT PUSH AF LD A,5FH ; LD E,A LD (LDE),A XOR A ; NOP LD (N),A POP AF RET ;..... ; INPUT: OR A JR Z,IP LD A,0C9H ; RET ; IP: LD (ECHOC),A LD A,B LD (MLEN),A LD (ILEN),A LD A,C LD (ULC),A LD A,D LD (WRP),A LD HL,INBUF LD DE,INBUF+1 LD BC,80 XOR A LD (HL),A LDIR LD IX,INBUF ; INPUT1: CALL GETCH ;;;;; jp input2 CP ',' JR NZ,INPUT2 LD A,(ULC) OR A JR NZ,INPUT1 LD A,',' ; INPUT2: CP CR JP Z,ICR CP 8 JP Z,IBS ; CHAR: CP ' ' ; 20h JR C,INPUT1 LD E,A LD A,(WRP) CP 1 JR NZ,CHAR0 LD A,E CP ' ' ; 20h JR NZ,CHAR0 LD A,(ILEN) CP 0FH JR C,ICR ; CHAR0: LD A,(ILEN) CP 0 JP Z,TOOLNG DEC A LD (ILEN),A LD A,E CP '`' ; 60h JR C,CHAR1 PUSH AF LD A,(ULC) LD B,A POP AF SUB B ; CHAR1: LD (IX+0),A INC IX CALL ECHOC JP INPUT1 ; ICR: LD A,(ILEN) LD B,A LD A,(MLEN) SUB B LD HL,INBUF RET ;..... ; IBS: LD A,(MLEN) LD B,A LD A,(ILEN) CP B JP Z,INPUT1 INC A LD (ILEN),A DEC IX XOR A LD (IX+0),A LD A,(N) OR A JP NZ,NBS LD A,8 CALL ECHOC LD A,' ' ; 20h CALL ECHOC LD A,8 CALL ECHOC JP INPUT1 ;..... ; TOOLNG: CALL PRINT DEFB 7,0 JP INPUT1 ;..... ; NBS: LD A,8 LD (N),A CALL ECHOC LD A,' ' ; 20h LD (N),A CALL ECHOC LD A,8 LD (N),A CALL ECHOC LD A,'*' ; 2Ah LD (N),A JP INPUT1 ;..... ; @ECHO: PUSH AF LD A,0FFH LD (SLTEST),A POP AF CALL ECHO PUSH AF XOR A LD (SLTEST),A POP AF RET ;..... ; ECHOC: NOP ; ECHO: PUSH HL PUSH DE PUSH BC PUSH AF ; LDE: LD E,A ; N: NOP LD C,DIRCON ; Unadorned character output CALL SPBDOS POP AF PUSH AF LD E,A LD A,(SLTEST) OR A CALL NZ,LPRIN POP AF POP BC POP DE POP HL RET ;..... ; JPHL: JP (HL) ; GETCH: PUSH HL LD HL,(1) LD L,9 PUSH IX PUSH IY CALL JPHL POP IY POP IX PUSH AF CP 1AH CALL Z,CCOPY POP AF OR A POP HL RET ;..... ; CCOPY: LD A,(CHKZ) CP 1AH ; LL A,(DE) JR NZ,NOZ XOR A LD (CHKZ),A LD HL,CCOPYM CALL PRINTM RET ;..... ; NOZ: LD A,1AH LD (CHKZ),A RET ;..... ; CHKZ: DEFB 0 ; CAPS: CP 'a' ; See if lower case already RET C ; If yes, return SUB ' ' ; Else change to lower case RET ;..... ; ;----------------------------------------------------------------------- ; ; Date and time conversion routines. In each case IX is set to point at ; an ASCII input string and IY is set to point at a three-byte binary ; output string. ; ; The code could be tightened up a bit - for a start, most of the IY ; register manipulations are unnecessary. ; ;----------------------------------------------------------------------- ; ; Converts a time in ASCII-decimal form HH:MM:SS to a three-byte binary ; form {hour,minute,second}. ; CTIME: PUSH IY PUSH IX LD IX,TIME LD IY,BTIME JR CNVRT ; $+0e ; ; Converts a date in ASCII-numeric form MM/DD/YY or similar to a three- ; byte binary form {month,day,year}. At this stage there is no inherent ; ordering of the fields except that the output corresponds to the input. ; DD/MM/YY would be converted to {day,month,year} ; CDATE: PUSH IY PUSH IX LD IX,DATE ; MM/DD/YY LD IY,BDATE ; Month, day, year ; CNVRT: PUSH HL PUSH DE PUSH BC LD A,2 ; Tell conversion routine how many LD (CNVRT0+1),A ; digits to do CALL CNVRT0 ; Convert first field (ASCII-decimal to binary) INC IX ; Step over the delimiter (usually / or :) LD A,L ; Store the binary equivalent of the field LD (IY+0),A ; Into the time or date structure INC IY ; Step the output field pointer CALL CNVRT0 ; Convert second field INC IX LD A,L LD (IY+0),A INC IY CALL CNVRT0 ; Convert third field LD A,L LD (IY+0),A POP BC POP DE POP HL POP IX POP IY RET ;..... ; ; Converts a sequence of ASCII decimal digits to a binary number. ; ; IX points at string of digits and is incremented for each digit ; B will hold number of digits to be converted ; HL winds up with the binary number ; CNVRT0: LD B,2 LD HL,0 ; CNVRT1: ADD HL,HL ; *2 PUSH HL ADD HL,HL ; *4 ADD HL,HL ; *8 POP DE ADD HL,DE ; *10 LD A,(IX+0) SUB '0' LD E,A LD D,0 ADD HL,DE INC IX DJNZ CNVRT1 RET ;..... ; ; Routines for printing date and time. ; ; At first inspection (and subject to further checking) it seems that in ; the case of a date, IX points at a 3-byte sequence: month, day, year. ; The DATDIF routine seems to expect the dates in the same format. ; ; The code to print a date is the same as the code to print a time. ; ; Address Date Time ; ------- ---- ---- ; IX+0 month hour ; IX+1 day minute ; IX+2 year ; ; Changing the order in which the date fields are presented i.e., doing ; day first, then month via IX+1 and IX+0, will reverse the presentation ; of the hours and minutes in a time display! ; ; If my analysis is correct then the USA-unique date format is built ; deep into the PBBS internals i.e., here, and the changes required to ; handle international date format are not trivial. It is hard to see ; how to avoid releasing this source code to anyone outside the USA ; needing a readable date display. ; DNUM: DEFB '*' ; PTIME: LD A,':' ; 3Ah JR STDELIM ; PDATE: LD A,'/' ; 2Fh ; STDELIM:LD (THING1),A LD (THING2),A LD A,2 LD (DNUM),A LD A,(IX+0) CALL PA2ASC LD B,A LD A,(DNUM) ADD A,B LD (DNUM),A CALL @PRNT ; THING1: DEFB '/' DEFB 0 LD A,(IX+1) CALL PA2ASC LD B,A LD A,(DNUM) ADD A,B LD (DNUM),A CALL @PRNT ; THING2: DEFB '/' DEFB 0 LD A,(IX+2) CALL PA2ASC LD B,A LD A,(DNUM) ADD A,B RET ;..... ; PA2ASC: LD L,A LD H,0 LD DE,10 CALL DIV16 LD A,'0' ; 30h ADD A,L CALL @ECHO LD A,'0' ; 30h ADD A,E CALL @ECHO LD A,2 RET ;..... ; ; Date difference routine. Careful, I have not tracked this routine and ; the comments may wildly wrong but I think it computes the number of ; days from the date pointed to by IX to the date pointed to by IY. ; DATDIF: PUSH DE LD (IYSAVE),IY LD (IXSAVE),IX XOR A LD (TMPD2),A LD A,(IX+2) ; Year 1 LD B,A ; To B LD A,(IY+2) ; Year 2 CP B ; Check against year 1 CALL NZ,YEARDF ; Account for difference in year? CALL DATCLC LD (TMPDAT),HL PUSH IX POP IY CALL DATCLC LD DE,(TMPDAT) AND A EX DE,HL SBC HL,DE LD D,0 LD A,(TMPD2) LD E,A ADD HL,DE LD IX,(IXSAVE) LD IY,(IYSAVE) LD A,(IX+2) LD B,A LD A,(IY+2) CP B JR Z,DDXIT LD A,E LD DE,365 ADD HL,DE LD D,0 LD E,A AND A SBC HL,DE ; DDXIT: POP DE RET ;..... ; YEARDF: LD A,(IX+1) ; Load 'current' month LD B,A LD A,31 ; Calculate approximate number of days SUB B ; Remaining in this month ????? LD (TMPD2),A RET ; Not sure what's going on here! ;..... ; DATCLC: LD A,(IY+0) LD HL,0 LD DE,0 DEC A CP 0 JP Z,ADDDAY ADD A,A LD HL,DATTAB LD D,0 LD E,A ADD HL,DE DEC HL LD A,(HL) LD D,A DEC HL LD A,(HL) LD E,A ; ADDDAY: LD A,(IY+1) LD L,A LD H,0 ADD HL,DE RET ;..... ; PBFLG: DEFB 0 ; PB2ASC: XOR A LD (PBFLG),A LD (ECHOC),A LD B,5 LD DE,10000 LD (P10),DE ; PBJP1: CALL DIV16 LD A,L ADD A,'0' CP '0' JR NZ,PBJP1B LD A,(PBFLG) OR A JR NZ,PBJP1A JR PBJP2 ; PBJP1A: LD A,'0' ; PBJP1B: CALL @ECHO LD A,(PBFLG) INC A LD (PBFLG),A ; PBJP2: PUSH DE LD HL,(P10) LD DE,10 CALL DIV16 LD (P10),HL POP DE EX DE,HL DJNZ PBJP1 LD A,(PBFLG) OR A RET NZ LD A,'0' CALL @ECHO LD A,1 RET ;..... ; SLTEST: DEFB 0 SYSLOG: DEFB 0 ; @PRNT: LD A,0FFH LD (SLTEST),A ; PRINT: POP HL LD A,(HL) INC HL OR A JP NZ,PRINT1 XOR A LD (SLTEST),A JP (HL) ; PRINT1: PUSH HL PUSH AF LD E,A LD C,WRCON ; Embellished character output CALL SPBDOS POP AF LD E,A LD A,(SLTEST) OR A CALL NZ,LPRIN ; PRT0: JR PRINT ; LPRIN: LD A,(SYSLOG) OR A RET Z ; LD C,LSTOUT ; Character output to LST: device CALL SPBDOS RET ; PRINTM: LD A,(HL) OR A RET Z ; INC HL PUSH HL LD E,A LD C,WRCON ; Embellished output to CON: device CALL SPBDOS POP HL JP PRINTM ;..... ; ; Print the user's name ; PRINTN: LD A,20H LD (PRN06-1),A ; PRN01: LD A,B ; Test output character count OR A RET Z ; Exit if none left to print LD A,(HL) ; Load character to be displayed INC HL ; Point at next character OR A ; Test current character RET Z ; Exit if end-of-string DJNZ PRN02 ; Count down characters RET ; PRN02: PUSH HL ; Save character pointer PUSH BC ; In case we skip this character CP ' ' ; Is current character a space? JR Z,PRN04 LD E,A ; Display the character LD C,WRCON CALL SPBDOS POP BC ; Recover character count POP HL ; Recover character pointer JR PRN07 ; PRN03: XOR A LD (PRN06-1),A LD A,',' ; PRN04: LD C,WRCON LD E,A CALL SPBDOS POP BC POP HL JR PRN01 ; PRN05: PUSH HL PUSH BC CP ',' JR Z,PRN03 CP ' ' JR Z,PRN04 CP 27H JR Z,PRN04 CP '.' JR Z,PRN04 CP 27H JR Z,PRN04 CP '-' JR Z,PRN04 OR A CP 'A' JR C,PRN06 CP '[' ; 5Bh JR NC,PRN06 OR 20H ; Convert to lower case ; PRN06: LD C,WRCON LD E,A CALL SPBDOS POP BC POP HL ; PRN07: LD A,(HL) ; Load character INC HL ; Step pointer to next character OR A ; Test for end of string RET Z ; Exit if so DJNZ PRN05 ; Count down and continue if count INC B ; Why????? RET ;..... ; @PRNTL: LD A,0FFH LD (SLTEST),A CALL PRINTL XOR A LD (SLTEST),A RET ;..... ; PRINTL: LD A,(HL) OR A RET Z INC HL PUSH BC PUSH HL PUSH AF LD C,WRCON ; BDOS call to show character LD E,A ; Character to 'E' CALL SPBDOS ; Go call bdos POP AF ; Get the character back LD E,A ; Store in 'A' again LD A,(SLTEST) OR A CALL NZ,LPRIN POP HL POP BC DJNZ PRINTL RET ;..... ; ; Print the first name in lower case, allow for J.J. as one name ; PRINTS: CALL PRINTS3 CALL PRINTS4 ; PRINTS1:CALL PRINTS3 CP '.' JR NZ,PRINTS2 CALL PRINTS4 JR PRINTS ; PRINTS2:OR 20H CALL PRINTS4 JR PRINTS1 ; PRINTS3:LD A,(HL) OR A JP Z,PRINRET CP ' ' ; 20h JP Z,PRINRET RET ;... ; PRINRET:POP HL ; Yank CALL PRINTS3 off the stack RET ; Back to main program ;... ; PRINTS4:INC HL PUSH HL LD E,A LD C,WRCON CALL SPBDOS POP HL RET ;..... ; ; Moves the name into the DE buffer, normally the CALLERS file ; MOVNM: LD A,20H LD (MOVNM05-1),A ; MOVNM01:LD A,B OR A RET Z LD A,(HL) INC HL OR A RET Z DJNZ MOVNM02 RET ;... ; MOVNM02:PUSH HL PUSH BC CP ' ' ; 20h JR Z,MOVNM07 LD (DE),A INC DE POP BC POP HL ; MOVNM03:LD A,(HL) INC HL OR A RET Z DJNZ MOVNM04 RET ;... ; MOVNM04:PUSH HL PUSH BC CP ',' JR Z,MOVNM06 CP ' ' ; 20h JR Z,MOVNM07 CP 27H JR Z,MOVNM07 CP '.' ; 2Eh JR Z,MOVNM07 CP 27H JR Z,MOVNM07 CP '-' ; 2Dh JR Z,MOVNM07 OR A CP 'A' ; 41h JP C,MOVNM05 CP '[' ; 5Bh JP NC,MOVNM05 OR 20H ; 20h ; MOVNM05:LD (DE),A INC DE POP BC POP HL JR MOVNM03 ; MOVNM06:XOR A LD (MOVNM05-1),A ; MOVNM07:LD (DE),A INC DE POP BC POP HL JR MOVNM01 ;..... ; OPEN: CALL BFCB LD C,OPENF ; Open file LD DE,FCB CALL SPBDOS CP 0FFH RET NZ LD HL,005DH JP FERROR ;... ; OPEN1: CALL BFCB2 LD C,OPENF ; Open file LD DE,FCB2 CALL SPBDOS CP 0FFH RET NZ LD HL,FCB2+1 JP FERROR ;..... ; ; Opens a file ; OPEN2: CALL BFCB2 LD DE,FCB2 LD C,DELET ; Delete file PUSH DE CALL SPBDOS LD C,MAKE ; Make file POP DE CALL SPBDOS CP 0FFH RET NZ LD HL,FCB2+1 JP FERROR ;..... ; COPEN: CALL BFCB LD C,OPENF ; Open file LD DE,FCB CALL SPBDOS CP 0FFH RET NZ ; CREAT: LD C,MAKE ; Make file LD DE,FCB CALL SPBDOS CP 0FFH RET NZ CALL PRINT DEFB CR,LF,CR,LF DEFB '++ FATAL ERROR IN' DEFB ' CREATING NEW FILE' DEFB ' ++' DEFB CR,LF,CR,LF,0 JP 0000H ; Reboot ;..... ; SPOPN01:PUSH AF XOR A LD (FERROR),A POP AF RET ;..... ; SPOPEN: LD A,0C9H ; Ret LD (FERROR),A CALL OPEN CP 0FFH JR NZ,SPOPN01 XOR A LD (FERROR),A LD DE,FCB CALL CREAT XOR A LD HL,RNDBUF LD (HL),A LD DE,RNDBUF+1 LD BC,003FH LDIR LD HL,1 LD (RNDBUF),HL LD HL,0040H LD (RRSZ),HL LD HL,0 CALL PUT CALL CLOSE LD HL,005DH JP SPOPEN ;..... ; CLOSE: LD C,CLOSEF ; Close file LD DE,FCB CALL SPBDOS CP 0FFH RET NZ LD HL,005DH JP FERROR ;..... ; CLOSE2: LD C,CLOSEF ; Close file LD DE,FCB2 CALL SPBDOS CP 0FFH RET NZ LD HL,FCB2+1 ; FERROR: NOP LD B,8 CALL PRINTL PUSH HL CALL PRINT DEFB '.' DEFB 0 POP HL LD B,3 CALL PRINTL CALL PRINT DEFB ' <-- file ERROR.' DEFB 7,CR,LF,CR,LF,0 LD A,0FFH RET ;..... ; DEFB 'begin CP/M' ; Unused DEFB 0 ;..... ; ERROR: LD A,(ERRDRV) LD C,SELDSK ; Select disk LD E,A CALL SPBDOS LD A,(ERRUSR) LD C,SETUSR ; Set user number LD E,A CALL SPBDOS LD DE,ERRFIL ; CPM: PUSH DE LD A,(INTAR) LD (4),A PUSH AF RRCA RRCA RRCA RRCA AND 0FH LD C,SETUSR ; Set user number LD E,A CALL SPBDOS POP AF LD E,A POP HL PUSH HL LD A,(HL) CP 0 JP Z,JUMP1 ; LD A,CPLUS OR A JP NZ,CPM3CHN LD A,SETCCP OR A JR Z,NCHN LD HL,CCPLOC LD (CCPLC),HL JR NOTEXT ; NCHN: LD HL,(1) LD A,H SUB 16H LD H,A LD L,0 LD (CCPLC),HL LD A,EXTCL OR A JR Z,NOTEXT LD HL,MCLBUF PUSH HL POP DE INC DE INC DE INC DE INC DE LD (HL),E INC HL LD (HL),D DEC DE JR ISEXT ; NOTEXT: POP DE LD A,L ADD A,7 LD L,A LD A,ZCMD OR A JR NZ,ISZCMD LD A,(HL) ADD A,L LD L,A ; ISZCMD: EX DE,HL JR LLOOP ; ISEXT: POP HL ; LLOOP: LD A,(HL) INC HL EX DE,HL LD (HL),A CP 0 JR Z,JUMP INC HL EX DE,HL JR LLOOP ;..... ; JUMP: LD BC,(4) LD A,0C3H ; Restore loc 0 to a JP LD (0),A JP 0000H ; Reboot ;..... ; CCPLC EQU $-2 ; JUMP1: LD A,0C3H LD (0),A JP 0000H ; Reboot ; DEFB 'begin CPM+',0 ; Unused ; CPM3CHN:LD DE,0080H LD C,SETDMA ; Set DMA PUSH DE CALL SPBDOS POP DE LD B,0 POP HL LD C,(HL) INC HL INC C LDIR LD A,0C3H LD (0),A LD E,0 LD C,CHAIN ; Chain to program CALL SPBDOS ; And he'll never return, ... DEFB 'end CPM+, Routine' DEFB ' by Tom Morris' ; BFCB: LD DE,FCB ; BFCB01: INC HL LD A,(HL) DEC HL CP ':' ; 3Ah JP NZ,BFND LD A,(HL) AND 0FH INC HL INC HL JP BFSD ; BFND: XOR A ; BFSD: LD (DE),A INC DE LD C,8 CALL BFGT CP '.' ; 2Eh JP NZ,BFNT INC HL ; BFNT: LD C,3 CALL BFGT LD B,0 LD C,18H CALL BFFT RET ; BFGT: LD A,(HL) OR A JP Z,BFSFT CP '*' ; 2Ah JP Z,BFQFT CP '.' ; 2Eh JP Z,BFSFT LD (DE),A INC DE INC HL DEC C JP NZ,BFGT ; BFSKIP: LD A,(HL) OR A RET Z ; CP '.' ; 2Eh RET Z INC HL JP BFSKIP ; BFSFT: LD B,' ' ; 20h JP BFFT ; BFQFT: LD B,'?' ; 3F CALL BFFT JP BFSKIP ; BFFT: PUSH AF LD A,B ; BFFTL: LD (DE),A INC DE DEC C JP NZ,BFFTL POP AF RET ; BFCB2: LD DE,FCB2 JP BFCB01 ; FCB2: DEFB 0,0,0,0,0,0,0,0 ; 16 + 16 +4 DEFB 0,0,0,0,0,0,0,0 DEFB 0,0,0,0,0,0,0,0 DEFB 0,0,0,0,0,0,0,0 DEFB 0,0,0,0 ; RNDERR: CP 1 JP NZ,RE3 LD HL,REM1 JP REX ;..... ; RE3: CP 3 JP NZ,RE4 LD HL,REM3 JP REX ;... ; RE4: CP 4 JP NZ,RE5 LD HL,REM4 JP REX ;... ; RE5: CP 5 JP NZ,RE6 LD HL,REM5 JP REX ;... ; RE6: LD HL,REM6 ; REX: PUSH HL CALL PRINT DEFB CR,LF,0 POP HL CALL PRINTM CALL PRINT DEFB CR,LF,0 JP ERROR ; ENDBBS: LD HL,HBSEND RET ;..... ; ;;;;HBSEND: ;;;; DEFB 0 DEFB ' Some routines are copyright (c)1986 Russ Pencin' DEFB ' others are based on routines by Simon Ewins.' DEFB ' The jump CPM routine is a modified version of' DEFB ' Harry Kaemmerer''s copyrighted CPM routine.' ; ;------------------------------- end -----------------------------------