;INTERACTIVE TEXT PRESENTER ;JULY 2, 1988 ;TO TURN THIS INTO A PROGRAM, TACK TEXT FILE ON TO END OF IT AND ;THEN TACK A ZERO BYTE ON TO END OF TEXT FILE. ; ;E.G. PIP PROG.COM=HELPER.COM,FILE.TXT,0.DAT ; ;WHERE 0.DAT IS A 1-SECTOR FILE CONTAINING A 0 FOLLOWED BY A ^Z .Z80 ASEG BDOS EQU 5 ;CHARACTER THAT INTRODUCES COMMANDS ;MUST NOT BE USED FOR OTHER PURPOSES IN TEXT FILE. ;CAN BE ANY 7-BIT CHAR OTHER THAN 0 OR ^Z CMARK EQU '~' ORG 100H LD (SPSAVE),SP LD SP,TSTACK LD A,23 LD (LINES),A ;CLEAR STACKS AND GO TO TOP OF TEXT START: LD HL,USTACK LD (USTAKP),HL LD HL,LSTACK LD (LSTAKP),HL LD DE,TEXT ;OUTPUTTING TEXT. READ NEXT CHAR AND CHECK FOR COMMAND MAIN: LD A,(DE) INC DE OR A JP Z,EXIT AND 7FH CP CMARK JR Z,DOCMD CP '^' JR Z,PUTCTL MAIN1: CALL PUTCHR CP 10 JR NZ,MAIN ;AUTO-PAUSE EVERY 23 LINES LD HL,LINES DEC (HL) JR NZ,MAIN CALL PAUSE JR MAIN ;CONVERT NEXT CHARACTER TO CONTROL EQUIVALENT PUTCTL: LD A,(DE) INC DE CP '^' JR Z,MAIN1 AND 31 JR MAIN1 ;PROCESS COMMAND DOCMD: LD A,(DE) INC DE CP CMARK JR Z,MAIN1 ;LITERAL CALL TOUPPR ;QUIT-LEAVE PROGRAM CP 'Q' JP Z,EXIT ;LABEL-IGNORE IT HERE CP 'L' JR NZ,DOCM1 CALL SKIPNL JR MAIN ;SWITCH DOCM1: CP 'S' JP Z,DOSWIT ;PAUSE-FORCE PAUSE UNLESS WE JUST FINISHED AN AUTO-PAUSE CP 'P' JR NZ,DOCM2 LD A,(LINES) CP 23 JR Z,DOCM3 CALL PAUSE DOCM3: JR MAIN ;TOP-RESTART DOCM2: CP 'T' JP Z,START ;USE-PICK UP DESTINATION, STACK CURRENT POSITION AND BRANCH CP 'U' JR NZ,DOCM4 CALL GETLBL LD HL,(USTAKP) LD (HL),E INC HL LD (HL),D INC HL LD (USTAKP),HL JR DOCM5 ;GOTO-PICK UP LABEL AND BRANCH DOCM4: CP 'G' JR NZ,DOCM6 CALL GETLBL DOCM5: CALL DOGOTO JR CMDEND ;RETURN-UNSTACK POSITION AND RESUME READING DOCM6: CP 'R' JR NZ,DOCM7 LD HL,(USTAKP) DEC HL LD D,(HL) DEC HL LD E,(HL) LD (USTAKP),HL JR CMDEND ;CASE OR DEFAULT-IF WE SEE THEM HERE, WE NEED TO SKIP TILL END OF ;CURRENT SWITCH SECTION DOCM7: CP 'C' JP Z,SKSWIT CP 'D' JP Z,SKSWIT ;END-RESUME AFTER IT CP 'E' JR NZ,DOCM8 CALL SKIPNL JR CMDEND ;ECHO LAST RESPONSE DOCM8: CP 'O' JR NZ,DOCM9 CALL OTRESP JR CMDEND ;BEGIN LOOP DOCM9: CP 'B' JR NZ,DOCM10 DEC DE ;STACK POSITION OF COMMAND DEC DE LD HL,(LSTAKP) LD (HL),E INC HL LD (HL),D INC HL LD (LSTAKP),HL INC DE INC DE JR CMDEND ;REPEAT LOOP (AGAIN) DOCM10: CP 'A' JR NZ,DOCM11 LD HL,(LSTAKP) DEC HL LD D,(HL) DEC HL LD E,(HL) LD (LSTAKP),HL JR CMDEND ;EXIT FROM LOOP DOCM11: CP 'X' JR NZ,CMDEND LD HL,CNEST LD (HL),1 SKLOOP: CALL SKIPCM CP 'B' JR NZ,SKLOP1 INC (HL) JR SKLOOP SKLOP1: CP 'A' JR NZ,SKLOOP DEC (HL) JR NZ,SKLOP1 CMDEND: JP MAIN ;PROCESS SWITCH COMMAND. FIRST GET RESPONSE DOSWIT: CALL GPRMPT LD HL,CNEST LD (HL),1 ;SKIP OVER TEXT UNTIL WE SEE A CASE COMMAND THAT MATCHES RESPONSE ;OR A DEFAULT COMMAND. SKIP OVER NESTED SWITCH SECTIONS DOSW1: CALL SKIPCM CP 'S' JR NZ,DOSW3 INC (HL) JR DOSW1 DOSW3: CP 'E' JR NZ,DOSW4 DEC (HL) JR NZ,DOSW1 ;IF WE SEE END COMMAND WITHOUT MATCHING ANYTHING, RESUME DISPLAY DOSW6: CALL SKIPNL JP MAIN DOSW4: CP 'D' JR NZ,DOSW5 LD A,(HL) CP 1 JR NZ,DOSW1 JR DOSW6 DOSW5: CP 'C' JR NZ,DOSW1 LD A,(HL) CP 1 JR NZ,DOSW1 ;SEE IF RESPONSE MATCHES THIS CASE PUSH HL LD HL,RESPNS CALL MATSTR POP HL JR NZ,DOSW1 JP MAIN ;SKIP TO END OF CURRENT SWITCH SECTION, DEALING WITH NESTED ;SWITCH SECTIONS SKSWIT: LD HL,CNEST LD (HL),1 SKSW1: CALL SKIPCM CP 'S' JR NZ,SKSW2 INC (HL) JR SKSW1 SKSW2: CP 'E' JR NZ,SKSW1 DEC (HL) JR NZ,SKSW1 CALL SKIPNL JP MAIN ;LEAVE PROGRAM EXIT: LD SP,(SPSAVE) RET ;SKIP PAST END OF CURRENT LINE SKIPNL: LD A,(DE) INC DE ;CHECK FOR RUNNING OFF THE END OR A JP Z,EXIT CP 10 JR NZ,SKIPNL RET ;OUTPUT A CHARACTER PUTCHR: PUSH AF PUSH DE LD E,A LD C,2 CALL BDOS POP DE POP AF RET ;SKIP TEXT UNTIL A COMMAND SEEN. RETURN COMMAND LETTER SKIPCM: LD A,(DE) INC DE OR A JP Z,EXIT CP CMARK JR NZ,SKIPCM LD A,(DE) INC DE TOUPPR: CP 'a' JR C,TOUPP1 CP '{' JR NC,TOUPP1 AND 5FH TOUPP1: RET ;SEARCH FOR A LABEL IN TEXT, STARTING AT TOP DOGOTO: LD DE,TEXT DOGO1: CALL SKIPCM CP 'L' JR NZ,DOGO1 LD HL,GOLAB CALL MATSTR JR NZ,DOGO1 RET ;EXTRACT TARGET LABEL FROM TEXT GETLBL: LD HL,GOLAB GETLB1: LD A,(DE) LD (HL),A INC DE INC HL CP 13 JR NZ,GETLB1 INC DE RET ;COMPARE TEXT WITH STRING POINTED TO BY HL. RETURN Z IF MATCH, ;NZ IF NO MATCH. IN EITHER CASE, POINT TO START OF LINE AFTER ;MATCHING TEXT MATSTR: LD A,(DE) CALL TOUPPR LD B,A LD A,(HL) CALL TOUPPR CP B JR NZ,MATST1 INC HL INC DE CP 13 JR NZ,MATSTR INC DE XOR A RET MATST1: CALL SKIPNL LD A,1 OR A RET ;SHOW "MORE" MESSAGE, WAIT FOR ANY KEY. ;USES BACKSPACES INSTEAD OF RETURNS TO AVOID MESSING UP ;TABBED TEXT. RESETS LINE COUNT WHEN DONE. PAUSE: PUSH DE LD DE,P1STR LD C,9 CALL BDOS PAUS1: LD C,6 LD E,255 CALL BDOS OR A JR Z,PAUS1 PUSH AF LD DE,P2STR LD C,9 CALL BDOS POP AF POP DE CP 3 JP Z,EXIT LD A,23 LD (LINES),A RET P1STR: DB '[any key]',8,8,8,8,8,8,8,8,8,'$' P2STR: DB ' ',8,8,8,8,8,8,8,8,8,'$' ;GET RESPONSE TO PROMPT GPRMPT: PUSH DE LD DE,RESBUF LD C,10 CALL BDOS LD A,(RESCNT) LD E,A LD D,0 LD HL,RESPNS ADD HL,DE LD (HL),13 LD A,10 CALL PUTCHR LD A,23 ;RESET LINE COUNT LD (LINES),A POP DE RET ;ECHO MOST RECENT RESPONSE OTRESP: LD HL,RESPNS OTRES1: LD A,(HL) CP 13 RET Z PUSH HL CALL PUTCHR POP HL INC HL JR OTRES1 ;VARIABLES ;RESPONSE BUFFER (SET UP FOR BDOS READ BUFFER FUNCTION) RESBUF: DB 16 RESCNT: DS 1 RESPNS: DS 16 ;STACK FOR "USE" COMMAND NESTING USTAKP: DS 2 USTACK: DS 16 ;STACK FOR LOOP NESTING LSTAKP: DS 2 LSTACK: DS 16 ;SCREEN LINE COUNTER LINES: DS 1 ;NESTING LEVEL FOR CASE SKIPPING CNEST: DS 1 ;TARGET LABEL FOR GOTO AND USE COMMANDS GOLAB: DS 16 ;PLACE TO KEEP CCP STACK SPSAVE: DS 2 ;LOCAL STACK DS 32 TSTACK: ;ACTUAL TEXT GETS TAGGED ON HERE. FORCE IT TO BEGIN AT NEAREST ;RECORD BOUNDARY SO PIP DOESN'T LEAVE JUNK IN BETWEEN IFE $ MOD 128 TEXT EQU $ ELSE TEXT EQU ($+128) AND NOT 127 ENDIF END