STTL "--- GAME I/O: APPLE II ---" PAGE ; -------------- ; INTERNAL ERROR ; -------------- ; ENTRY: ERROR CODE IN [A] ; EXIT: HA! ERRM: DB "Internal error " ENUMB: DB "00. " ERRML EQU $-ERRM ZERROR: LDY #1 ; CONVERT ERROR BYTE IN [A] ZERR0: LDX #0 ; TO ASCII AT "ENUMB" ZERR1: CMP #10 BCC ZERR2 SBC #10 INX BNE ZERR1 ZERR2: ORA #'0' STA ENUMB,Y TXA DEY BPL ZERR0 LDX #ERRM LDY #ERRML JSR DLINE ; PRINT ERROR MESSAGE JMP ZQUIT1 ; ---- ; QUIT ; ---- ZQUIT: JSR ZCRLF ; FLUSH BUFFER ZQUIT1: LDX #ENDM LDY #ENDML JSR DLINE ; "END OF STORY" FREEZE: JMP FREEZE ; AND STOP ENDM: DB "End of session." DB EOL ENDML EQU $-ENDM ; ------- ; RESTART ; ------- ZSTART: LDX #0 STX WTOP ; RESET FULL SCREEN FOR CLEAR LDA SCRIPTF ; PRINTING? BEQ REX ; NO DEX ; = $FF STX PSTAT ; MAKE TO CONTINUE PRINTING AFTER RESTART REX: JSR SIDE1 ; NEED SIDE 1 AGAIN JMP WARM ; AND DO WARMSTART ; -------------------------- ; RETURN TOP RAM PAGE IN [A] ; -------------------------- MEMTOP: LDA #$FB ; FOR NOW, ASSUME LAST "BUFFER" RTS ; OF AUX MEMORY ; -------------------------------- ; RETURN RANDOM BYTES IN [A] & [X] ; -------------------------------- RANDOM: INC RNUM1 DEC RNUM2 LDA RNUM1 ; GENERATED BY MONITOR GETBYT ADC RAND1 TAX LDA RNUM2 SBC RAND2 STA RAND1 STX RAND2 RTS ; ------------------- ; Z-PRINT A CHARACTER ; ------------------- ; ENTRY: ASCII CHAR IN [A] ; COMMENT: SCRIPTING IS HANDLED IN UNBUFR AND FLUSH, ; SO CAN OUTPUT TO PRINTER AS A LINE. TABLE AND SCREEN ; OUTPUT IS SET UP HERE, HANDLED A BYTE AT A TIME ; (DIROUT CHANGES 6/24/85) COUT: STA IOCHAR ; HOLD IT A SEC LDX TABLEF ; OUTPUT TO TABLE? BEQ COUT4 ; NO JMP TBLRTN ; YES, DO IT (TBL ONLY) COUT4: LDX SCREENF ; OUTPUT TO SCREEN? BNE COUT5 ; YES LDX SCRIPTF ; OUTPUT TO PRINTER? BNE COUT5 ; YES RTS ; NO, SO DONE COUT5: LDA IOCHAR ; RETRIEVE CHAR LDX BUFFLG ; UNBUFFERED OUTPUT? BNE UNBUFR ; YES, PLACE ON SCREEN IMMED. CMP #$0D ; IF ASCII EOL, BNE COUT0 JMP ZCRLF ; DO IT COUT0: CMP #SPACE ; IGNORE ALL OTHER BCC CEX ; CONTROLS ; LDX INVFLG ; CHECK IF NORMAL ; BPL COUT3 ; OR INVERSE ORA #%10000000 ; SET HIGH BIT FOR NORMAL COUT3: LDX CHRCNT ; GET LINE POINTER STA LBUFF,X ; ADD CHAR TO BUFFER LDA SPLITF ; are we in screen 1 BNE COUT2 ; yes LDY LENGTH ; GET LINE LENGTH COUNTER INC LENGTH ; ELSE UPDATE CPY XSIZE ; END OF SCREEN LINE? BCC COUT2 JMP FLUSH ; YES, FLUSH THE LINE COUT2: INC CHRCNT CEX: RTS ; -------------------------- ; DIRECT, UNBUFFERED DISPLAY ; -------------------------- UNBUFR: STA IOCHAR ; HOLD IN CASE NEED TO PRINT LDA EHZ ; CHECK IF BEYOND SCREEN CMP #80 BCS UNBEX ; YES, LEAVE LDA SPLITF ; CHECK WHICH WINDOW BEQ UNBBOT ; BOTTOM WINDOW LDA CVT ; CHECK IF WITHIN WINDOW CMP WTOP BCS UNBEX ; NO, JUST LEAVE BCC UNBDIS ; YES, GO DISPLAY UNBBOT: LDA CVT CMP WTOP BCC UNBEX ; NOT WITHIN WINDOW, LEAVE UNBDIS: LDA SCREENF ; DISPLAY TO SCREEN? BEQ UNBPRN ; NO, CHECK IF PRINTING LDA IOCHAR ORA #%10000000 ; SET BIT 7 FOR NORMAL DISPLAY IF WANTED JSR CHAR ;SEND CHAR TO PRINTER UNBPRN: LDA SCRIPT ; SCRIPTING INTERNALLY ENABLED? BEQ UNBEX ; NO LDA SCRIPTF ; SCRIPTING ON ? BEQ UNBEX ; NO LDA CSW+LO ; SAVE NORMAL OUTPUT HOOK PHA LDA CSW+HI PHA LDA EHZ ; + CURRENT CURSOR POSITION PHA LDA ALTCSW+LO STA CSW+LO LDA ALTCSW+HI STA CSW+HI LDA IOCHAR ; GET CHAR JSR MCOUT ; PRINT IT @ CURRENT EHZ PLA STA EHZ ; IIe USES CHZ ALSO PLA STA CSW+HI PLA STA CSW+LO UNBEX: RTS ; --------------- ; OUTPUT TO TABLE ; --------------- TBLRTN: TAX ; HOLD CHAR A SEC. ;PUT BYTE IN TABLE AT CURRENT OFFSET LDA DIRITM+LO ; ADD IN OFFSET CLC ADC DIRTBL+LO STA I+LO LDA DIRITM+HI ADC DIRTBL+HI STA I+HI LDY #0 TXA ; PICK UP ASCII CHAR STA (I),Y ; STORE IT IN TBL @ BYTE ALIGNED @ ;SET ITM OFFSET TO NEXT POSITION, INCREMENT COUNTER INC DIRITM+LO ; INC OFFSET TO NEXT BYTE BNE TBLRTS INC DIRITM+HI TBLRTS: RTS ; ------------------- ; FLUSH OUTPUT BUFFER ; ------------------- ; ENTRY: LENGTH OF BUFFER IN [X] FLUSH: LDA #$A0 ; SPACE STX OLDEND ; SAVE CURRENT END OF LINE FL0: CMP LBUFF,X ; FIND LAST SPACE CHAR BEQ FL1 ; IN THE LINE DEX BNE FL0 ; IF NONE FOUND, LDX XSIZE ; FLUSH ENTIRE LINE FL1: STX OLDLEN ; SAVE OLD LINE POS HERE STX CHRCNT ; MAKE IT THE NEW LINE LENGTH JSR ZCRLF ; PRINT LINE UP TO LAST SPACE ; START NEW LINE WITH REMAINDER OF OLD LDX OLDLEN ; GET OLD LINE POS LDY #0 ; START NEW LINE AT BEGINNING FL2: INX CPX OLDEND ; CONTINUE IF BCC FL3 ; INSIDE OR BEQ FL3 ; AT END OF LINE STY LENGTH ; ELSE SET NEW LINE LENGTH STY CHRCNT RTS FL3: LDA LBUFF,X ; GET CHAR FROM OLD LINE STA LBUFF,Y ; MOVE TO START OF NEW LINE INY ; UPDATE LENGTH OF NEW LINE BNE FL2 ; (ALWAYS) ; --------------- ; CARRIAGE RETURN ; --------------- ZZCRLF: LDX TABLEF ; OUTPUT TO TABLE? BEQ ZCRLF ; NO LDA #$0D JMP TBLRTN ; YES, DO IT (TBL ONLY) ZCRLF: LDX CHRCNT LDA #$8D ; INSTALL EOL AT STA LBUFF,X ; END OF CURRENT LINE INC CHRCNT ; UPDATE LINE LENGTH LDA SCREENF ; CHECK IF DISPLAYING TO SCREEN BEQ ZCRLFX ; NO, GO HANDLE IF PRINTING LDA SPLITF ; AT SPLIT SCREEN BNE ZCRLFX ; YES, SKIP ALL THIS INC LINCNT ; NEW LINE GOING OUT ZCRLF0: LDX LINCNT ; IS IT TIME TO CPX WBOTM ; PRINT "MORE" YET? BNE ZCRLFX ; NO, CONTINUE LDA WTOP STA LINCNT ; RESET LINE COUNTER INC LINCNT ; to leave this line there INC LINCNT ; to leave one line from previous screen ; there BIT ANYKEY ; CLEAN STROBE SO GET CLEAN READING LDA ZBEGIN+ZLMRG+1 ; SET LEFT MARGIN STA EHZ LDA #>MORE LDX #'S CHKFNC: LDA ZBEGIN+ZCRCNT+1 ; IF NULL IGNORE ORA ZBEGIN+ZCRCNT+0 BEQ CHKOUT LDA ZBEGIN+ZCRCNT+1 ; DECR COUNTER SEC SBC #1 STA ZBEGIN+ZCRCNT+1 LDA ZBEGIN+ZCRCNT+0 SBC #0 STA ZBEGIN+ZCRCNT+0 LDA ZBEGIN+ZCRCNT+1 ; IF NULL NOW, CALL FCN ORA ZBEGIN+ZCRCNT+0 BNE CHKOUT LDA ZBEGIN+ZCRFUNC+1 ; SET UP FUNCTION STA J+LO LDA ZBEGIN+ZCRFUNC+0 STA J+HI JSR INTCLL ; DO FUNCTION CALL CHKOUT: RTS ; ---------------------- ; UPDATE THE STATUS LINE ; ---------------------- ; NOT APPLICABLE IN EZIP. ZUSL: RTS ; ------ ; VERIFY ; ------ ; VERIFY GAME CODE ON DISK ZVER: JSR ZCRLF ; DISPLAY VERSION NUMBER, GET SIDE 1 LDX #3 LDA #0 STA IOCHAR ; COFFEE FLAG ZVR: STA K+LO,X ; CLEAR [K], [L] STA MPC,X ; [MPC] AND [MPCFLG] DEX BPL ZVR LDA #64 ; POINT [MPC] TO Z-ADDRESS $00040 STA MPCL ; 1ST 64 BYTES AREN'T CHECKED LDA ZBEGIN+ZLENTH ; GET MSB STA I+HI ; AND LDA ZBEGIN+ZLENTH+1 ; LSB OF Z-CODE LENGTH IN BYTES ASL A ; MULTIPLY BY ROL I+HI ; FOUR ROL K+LO ASL A STA I+LO ROL I+HI ; TO GET # BYTES ROL K+LO ; IN GAME LDA #0 ; START AT BEGINNING STA DBLOCK+LO STA DBLOCK+HI JMP READIN ; READ FIRST BLOCK IN VSUM: LDA MPCL ; NEW PAGE? BNE VSUM2 ; NO, CONTINUE READIN: LDA #>IOBUFF ; FAKE READ OUT SO STA DBUFF+HI ; IT DOESN'T MOVE BUFFER LDA #MAIN STA DSKBNK ; SET FOR MAIN BANK JSR GETDSK ; GO READ A PAGE LDA IOCHAR ; CHECK COFFEE FLAG BNE VSUM2 ; ALL DONE LDA SIDEFLG CMP #2 ; IF ON SIDE 2 BNE VSUM2 LDA #>COFMSG ; FIRST SECTOR, TELL THEM LDX #BIT CMP K+LO BNE VSUM LDA ZBEGIN+ZCHKSM+1 ; GET LSB OF CHECKSUM CMP L+LO ; DOES IT MATCH? BNE BADVER ; NO, PREDICATE FAILS LDA ZBEGIN+ZCHKSM ; ELSE CHECK MSB CMP L+HI ; LOOK GOOD? BNE BADVER ; IF MATCHED, JMP PREDS ; GAME IS OKAY BADVER: JMP PREDF COFMSG: DB EOL DB "Please be patient, this takes a while" DB EOL COFML EQU $-COFMSG ; ------ ; BUFOUT ; ------ ; ENTER: ARG1 = BUFFERED (1) OR NONBUFFERED (0) OUTPUT CHOICE ; EXIT: FLAG (BUFFLG) IS SET TO TELL COUT WHICH TO DO ZBUFOUT: LDX ARG1+LO BNE ZBUF1 ; SET TO BUFFERED OUTPUT JSR CLRBUF ; CLEAR BUFFER LDX #1 STX BUFFLG ; SET FUTURE OUTPUT TO BE UNBUFFERED RTS ZBUF1: DEX BNE ZBUFEX ; INVALID STX BUFFLG ; SET TO BUFFERED ZBUFEX: RTS ; CLEAR OUTPUT BUFFER BEFORE DOING ANYTHING FANCY CLRBUF: JSR LINOUT ; CLEAR BUFFER (DON'T RESET LINE COUNT) LDX #0 STX CHRCNT RTS ; ------ ; DIROUT ; ------ ; ARG1 CONTAINS VALUE OF WHICH DEVICE TO SELECT ; OR DESELECT, ARG2 = THE TABLE ADDR FOR TABLE OUTPUT ; MULTIPLE DEVICE USAGE IS POSSIBLE. ZDIRT: LDX ARG1+LO BMI DIRRES ; NEGATIVE VALUE, DESELECTING DEX BEQ DIR1 ; 1 = SET OUTPUT TO SCREEN DEX BEQ DIR2 ; 2 = SCRIPTING DEX BEQ DIR3 ; 3 = TABLE DEX BEQ DIR4 ; 4 = RECORDING DEVICE RTS ; INVALID VALUE DIRRES: INX BEQ DRES1 ; -1 = RESET TO SCREEN INX BEQ DRES2 INX BEQ DRES3 INX BEQ DRES4 RTS ; INVALID VALUE, JUST LEAVE DIR1: INX ; 1, TURN SCREEN OUTPUT ON STX SCREENF RTS DRES1:; JSR CLRBUF STX SCREENF ; 0, TURN SCREEN OFF RTS DIR2: INX STX SCRIPTF ; SET SCRIPT FLAG ON LDA ZBEGIN+ZSCRIP+1 ; SET GAME FLAG ALSO ORA #%00000001 STA ZBEGIN+ZSCRIP+1 LDA PSTAT ; CHECK IF PRINTER ALREADY INIT'D BNE DIR2A JSR PCHK ; NO, GO DO IT DIR2A: RTS ; YES, READY TO LEAVE DRES2: STX SCRIPTF ; TURN PRINTER OFF LDA ZBEGIN+ZSCRIP+1 ; AND TURN OFF GAME FLAG TOO AND #%11111110 STA ZBEGIN+ZSCRIP+1 RTS DIR3: INX STX TABLEF ; TURN TABLE OUTPUT FLAG ON LDA ARG2+HI ; SET UP TBL CLC ADC ZCODE LDX ARG2+LO ; TO STORE CHARS IN STX DIRTBL+LO STA DIRTBL+HI LDA #2 STA DIRITM+LO LDA #0 STA DIRITM+HI RTS DRES3: LDA TABLEF ; IF OFF ALREADY BEQ OUT3 ; LEAVE AS IS STX TABLEF ; TURN TBL OUTPUT OFF LDA DIRITM+LO ; MARK END OF CHARS IN TBL CLC ; WITH A NULL CHAR ADC DIRTBL+LO STA I+LO LDA DIRITM+HI ADC DIRTBL+HI STA I+HI ; ALIGNED AT EOL LDA #0 TAY STA (I),Y ; PLACE 0 IN TBL LDY #1 ; GET CHAR COUNT LDA DIRITM+LO ; (2 LESS THAN [DIRITM]) SEC SBC #2 STA (DIRTBL),Y BCS RESET0 DEC DIRITM+HI RESET0: LDA DIRITM+HI DEY STA (DIRTBL),Y ; STORE CHAR COUNT IN TBL LDA #0 ; CLEAR COUNT FOR NEXT TIME STA DIRFLG ; SET OUTPUT TO SCREEN OUT3: RTS DIR4: DRES4: RTS ; NOT YET IMPLEMENTED ; ------ ; CURSET ; ------ ; SET CURSOR AT LINE (ARG1) AS OFFSET FROM TOP OF WINDOW ; AND AT COLUMN (ARG2) ZCURST: JSR CLRBUF ; CLEAR OUT ANY NON DISPLAYED TEXT 1ST LDX ARG1+LO ; GET LINE DEX ; ZERO ALIGN IT STX CVT LDX ARG2+LO ; GET COLUMN DEX ; ZERO ALIGN IT STX EHZ ; STX CHZ ; IIe SEEMS TO USE BOTH JMP BASCAL ; MOVE THE CURSOR ; ------ ; CURGET ; ------ ZCURGT: LDA ARG1+LO STA I+LO LDA ARG1+HI CLC ADC ZCODE ; ABSOLUTE STA I+HI LDY CVT ; GET CURSOR POSITION LDX EHZ INX ; 1 ALIGN IT INY TYA ; SLIP IT INTO PLACE LDY #1 ; TO RETURN IT STA (I),Y DEY ; ZERO TOP BYTE TYA STA (I),Y INY INY STA (I),Y INY TXA STA (I),Y RTS ; ----- ; DIRIN ; ----- ; NOT YET IMPLEMENTED, BUT RESERVED ZDIRIN: RTS ; ------ ; HLIGHT ; ------ ZLIGHT: JSR CLRBUF ; flush the ole buffer LDA ARG1+LO ; GET CHOICE OF MODE BNE ZL1 LDA #$FF ; NORMAL DISPL STA INVFLG ZLIEX: RTS ; MONO SPACE IS ONLY OPTION SO JUST IGNORE IT ZL1: CMP #1 ; INVERSE? BNE ZLIEX ; NO OTHER OPTIONS ON APPLE LDA #$3F ; SET INVERSE DISPLAY STA INVFLG RTS ; ----- ; ERASE ; ----- ZERASE: LDA ARG1+LO CMP #1 BNE ZEROUT ; INVALID JSR CLRBUF JMP CLEOL ; CLEAR TO END OF LINE ZEROUT: RTS ; ----- ; CLEAR ; ----- ZCLR: JSR CLRBUF ; LDA CHZ ; SAVE CURSOR JIC CLEARING OTHER WINDOW STA OLDCHZ LDA EHZ STA OLDEHZ LDA CVT STA OLDCVT LDA ARG1+LO ; CHECK WHAT TO DO BEQ CLR0 ; BOTTOM SCREEN CMP #1 BEQ CLR1 ; TOP SCREEN CMP #$FF BNE ZEROUT ; INVALID ; UNSPLIT SCREEN & CLEAR IT JSR NORL ; RESET TO FULL JMP CLS ; & CLEAR IT CLR0: LDA WTOP ; SET COUNT STA LINCNT ; FOR "MORE" JSR CLS ; CLEAR & HOME LDX #0 JMP SETOLD CLR1: LDA WTOP ; SAVE SCROLLING TOP PHA LDX #0 ; TOP OF SCREEN STX WTOP STA WBOTM ; MAKE BOTTOM OF TOP SCREEN JSR CLS LDA #$18 ; RESET TOP & BOTTOM STA WBOTM PLA STA WTOP LDX #1 ; SET SO NEXT TIME INTO WINDOW TOP LEFTS SETOLD: LDA #0 STA OLD0CVT,X STA OLD0CHZ,X STA OLD0EHZ,X CPX SPLITF BEQ CLROUT ; LEAVE CURSOR TOP LEFT LDA OLDCHZ ; STA CHZ LDA OLDEHZ STA EHZ LDA OLDCVT STA CVT JMP BASCAL CLROUT: RTS ; ------ ; PRINTT ; ------ ; PRINT A TABLE TO SCREEN, ARG1 = # OF BYTES ; ARG2 = WIDTH, ARG3 (DEF = 1) = HEIGHT OLDCHZ EQU I+LO ; EASIER TO READ OLDEHZ EQU I+HI OLDCVT EQU L+LO ZPRNTT: LDA SPLITF ; check if in window 0 BEQ PTTj ; don't clear buf in w0 (cuz we wrap) ; ; make sure the buffer is empty, thanks ; JSR CLRBUF PTTj: LDA ARG1+LO ; USE GETBYT AS TBL COULD STA MPCL ; BE ANYWHERE LDA ARG1+HI STA MPCM LDA #0 STA MPCH JSR VLDMPC LDA ARG2+LO ; ONLY A BYTE AS MAX CMP #0 BEQ PTTDUN ; QUIT NOW IF NULL STA J+HI ; SCREEN WIDTH IS 80 STA J+LO DEC NARGS LDA NARGS CMP #1 BEQ NOHIGHT ; DEFAULT HEIGHT IS 1 LDA ARG3+LO ; & SCREEN LENGTH MAX IS 25 NOHIGHT: STA K+LO LDA EHZ STA OLDEHZ LDA CVT STA OLDCVT PTTLP: JSR GETBYT ; GET A BYTE JSR COUT DEC J+LO BNE PTTLP DEC K+LO ; IF DONE ALL LINES BEQ PTTDUN ; LEAVE LDA OLDEHZ STA EHZ LDX OLDCVT INX ; TO NEXT LINE STX OLDCVT STX CVT JSR BASCAL ; PLACE CURSOR ON NEXT LINE LDA J+HI ; RESET COUNT STA J+LO JMP PTTLP ; GO DO NEXT LINE PTTDUN: RTS ; ------------ ; SET NEW FONT ; ------------ ; FONT 1 (NORMAL) AND 3 (MOUSETEXT - ON IIC'S ONLY) ONLY ; FWRD (PIXEL HEIGHT & WIDTH) DOESN'T CHANGE ZFONT: LDA ARG1+LO ; GET FONT CHOICE LDX SPLITF ; get which window CMP FONT,X ; see if it is a change BEQ ZFDONE ; nope, so just return JSR CLRBUF ; got to clear the buffer! LDA ARG1+LO ; GET FONT CHOICE, again JSR CHFONT ; go change it BCS ZFBAD ; bad choice ZFDONE: LDX SPLITF ; get old font for returning LDA FONT,X PHA LDA ARG1+LO ; and save the new one STA FONT,X ; REMEMBER NEW FONT FOR NEXT TIME PLA LDX #0 JMP PUTVAL ; RETURN PREVIOUS FONT ZFBAD: JMP RET0 ; TELL IT DOESN'T WORK ; ; entry point for local calls ; [A] has font # to change to ; CHFONT: LDX SIG BNE CFBAD ; NOT A IIC CMP #1 BEQ NORML CMP #3 BNE CFBAD FONT3: LDA #$3F ; SET INVERSE ON STA INVFLG LDA #$1B ; AND MOUSETEXT ON JSR MCOUT ; GO THRU THE CHANNELS FOR ANY OUTPUT TYPE JMP CHFOUT NORML: LDA #$18 ; TURN OFF MOUSE TEXT JSR MCOUT LDA #$FF STA INVFLG CHFOUT: CLC ; clear carry to show goodness RTS CFBAD: SEC ; set carry to show naughtiness RTS ; ------------------------------ ; FETCH A LINE OF INPUT FOR READ ; ------------------------------ ; ENTRY: ABS ADDR OF READ BUFFER IN [ARG1] ; EXIT: # CHARS READ IN [A] INPUT: JSR CLRBUF ; FLUSH [LBUFF] LDA #0 ; RESET LINE COUNT STA I+HI ; clear local variables STA I+LO STA J+HI STA J+LO STA BRKCHR ; init break char LDY WTOP STY LINCNT ; RESET LINE COUNT TAY ; get length stuff LDA (RDTBL1),Y ; get maximum size of buffer CMP #79 ; IF OVER 78, CUT DOWN TO 78 BCC MAX ; LEAVE IT AS IT IS, IT IS LESS LDA #78 MAX: STA CHRMAX ; and save it INY LDA (RDTBL1),Y ; get current offset into buffer TAX ; get so we can inc it INX ; and not INX ; count the 2 info-bytes STX CHARCNT ; save how many chars out there JSR CHKTME ; START TIME LIMIT INLOOP: LDA I+HI ; is there a time? BEQ INPL1 ; nope JSR TIMIN ; do timed input BCC INPL2 ; got a char, process it JMP LEXBAD ; timed out with nothing there! INPL1: JSR GETKEY ; let apple do the walking INPL2: JSR ISTCHR ; CHECK IF IT'S AN ACCEPTABLE TERMINATOR KEY BCS NOTYET STA BRKCHR CMP #EOL ; IF EOL PUT TO SCREEN BEQ ENDLIN JMP ENDIN ; ELSE JUST END NOTYET: TAY ; check for functions keys that aren't BMI CBAD ; terminators and feep if it is CMP #EOL ; EOL? BEQ ENDLIN ; LINE DONE IF SO CMP #BACKSP ; BACKSPACE? BEQ BACKUP ; SPECIAL HANDLING LDY CHARCNT ; where do we put char? CPY CHRMAX ; are we filled up? BCS CBAD ; boy, am i full CMP #$80 ; DON'T SHOW FCN KEYS BCS LEX SHOWIT: STA SVCHAR ; save it CMP #$80 ; don't display function keys BCS NOSHOW ; okay, i won't ; LDX INVFLG ; BPL SHOW1 ; INVRSE ORA #$80 ; ELSE MAKE IT NORMAL SHOW1: JSR CHAR ; SEND TO SCREEN ; ; now save it for posterity ; NOSHOW: LDA SVCHAR ; get it to work on CMP #'A' ; IF CHAR IS UPPERCASE ALPHA, BCC LEX ; CONVERT TO LOWER CASE CMP #'Z'+1 BCS LEX ADC #$20 ; converting away LEX: STA (RDTBL1),Y ; ADD CHAR TO INPUT BUFFER INC CHARCNT ; NEXT POSITION IN LINE JMP INLOOP ; NO, GET ANOTHER CHAR ; HANDLE BACKSPACE BACKUP: LDA CHARCNT ; if == 2 then empty CMP #2 ; and if not, then we still have room BEQ CBAD ; JMP to beeping DEC CHARCNT ; get rid of char LDA #$08 ; BACKSP STRANGE SO DO 082008 JSR CHAR LDA #$A0 JSR CHAR LDA #$08 JSR CHAR JMP INLOOP CBAD: JSR BEEP ; ELSE SCREAM WITH PAIN JMP INLOOP ; AND WAIT FOR SOMETHING BETTER ; HANDLE END OF LINE ENDLIN: STA BRKCHR LDA #$8D JSR CHAR ; SEND EOL TO SCREEN INC LINCNT ; take into account the at EOL ; ; now, build lbuff so we can send it to the printer if necessary ; but only build it if it is necessary, really! ; LDA SCRIPT ; find out if we are scripting BEQ ENDIN ; i guess not LDA ZBEGIN+ZSCRIP+1 ; check for printing AND #$01 ; check bit flag BEQ ENDIN ; no printing, continue on LDY CHARCNT ; start at end of buffer LDA #0 ; to print (put in by clearp) STA (RDTBL1),Y LDX CHARCNT ; fill in backwards DEX STX LINLEN ; say how many chars for printing DEX ; we don't need to count info-bytes here SLOOP: LDA (RDTBL1),Y ; get char STA LBUFF,X ; store char DEY ; point to next get place DEX ; point to next lbuff place BPL SLOOP ; go to some more SDONE: JSR CLEARP ; CLEAR OFF FCN KEYS BEFORE PRINTING JSR PPRINT ; SCRIPT [LBUFF] IF ENABLED ENDIN: LDY CHARCNT ; how many chars in buffer LDA #00 ; to show end of line STA (RDTBL1),Y ; and save it DEY ; DON'T INCLUDE LENGTH BYTES DEY ; IN COUNT TYA ; SAVE INBUF LENGTH LDY #1 STA (RDTBL1),Y ; and tell the world about it! LEXBAD: RTS ; INTO [A] ; CHKTME RTN - CALLED BY INPUT & ZINPUT CHKTME: LDA NARGS ; CHECK IF TIME LIMIT CMP #2 BEQ CHKT1 ; NO LDA ARG3+LO ; GET DELAY WANTED STA I+HI LDA NARGS ; IS THERE A FCN? CMP #4 BNE CHKT1 ; NO LDA ARG4+LO ; YES, SET IT STA J+LO LDA ARG4+HI STA J+HI CHKT1: RTS ; just set things up, please ; ZINPUT ENTRY (DIFFERENT ARG #'S SO SETUP AHEAD) TIMEK: BIT ANYKEY ; CLEAR STROBE TIMEST: JSR STCUR ; start the cursor LDA I+LO ; don't reset if not zero BNE TIME0 ; so keep goin' then LDA I+HI STA I+LO TIME0: LDX #8 ; .09 SEC (time to do other stuff) TIME1: LDA #$30 ; .O1 SEC JSR MWAIT DEX BNE TIME1 BIT KBD ; CHECK FOR KEYSTROKE BMI TIME2 ; OK, HE'S THERE, CONTINUE DEC I+LO ; 10TH'S OF SECONDS TO WAIT BEQ TIMEOUT ; SOME TIME LEFT BNE TIME0 ; so gwon back and try again! (JMP) ; TIME OUT, CHECK FOR A FCN TIMEOUT: JSR ERCUR ; after erasing cursor LDA J+HI ; IS THERE A FCN BEQ TIMEBAD ; NO FCN, LEAVE WITH NOTHING TIME3: JSR INTCLL ; INTERNALLY CALL THE FCN LDA VALUE+LO ; CHECK RESULTS BNE TIMEBAD ; ELSE TRY AGAIN (END EZIP) LDA LINCNT CMP WTOP ; check against start BEQ TIMEST ; if anything printed out, reprint input JSR FLUSHRD JMP TIMEST TIMEBAD: SEC RTS TIME2: CLC ; GOT A KEY RTS ; ; send out the input chars type in so far ; FLUSHRD: ldy #1 ; start at 1 to skip junk in front FRLOOP: iny ; next char? cpy CHARCNT ; see if we are full beq FREND ; nope, still some more lda (RDTBL1),Y ; get the char CMP #$80 ; don't display function keys BCS FRLOOP ; okay, i won't ora #$80 ; make normal jsr CHAR ; and send it out jmp FRLOOP FREND: lda WTOP sta LINCNT rts ; ; display the cursor in the current spot ; STCUR: LDX INVFLG ; save old invers TXA ; and get it EOR #$C0 ; set/clear inverse bits STA INVFLG ; and save it LDA #$A0 ; just an inverse space char JSR CHAR ; display it LDA #$08 ; gwon back JSR CHAR ; and wait STX INVFLG ; and reset it RTS ; just erase the cusor char, but leave cursor in its old place ; ERCUR: PHA ; save a LDA #$A0 ; get space char JSR CHAR ; and put it out there LDA #$08 ; get backspace JSR CHAR ; moving cursor back PLA ; retrieve [A] RTS ; ; timed key input loop ; ; carry set if timed out ; char in [A], if there is one! TIMIN: JSR TIMEK ; check for keystroke BCC TM1 ; SOMEBODY'S THERE BCS TMBAD ; ELSE ABORT TM1: JSR GOTKEY ; GET ASCII INTO [A] AND [IOCHAR] BEQ TIMIN ; 0 means no good char JSR ERCUR ; erase the cursor, please CLC ; clear to show goody BCC TMRET ; and go away TMBAD: SEC ; set carry to show timeout TMRET: RTS ; and away we go ; ------------------------ ; IS IT A TERMINATOR CHAR? ; ------------------------ ISTCHR: PHA LDA TCHARS+HI ; check if there is a tchars table ORA TCHARS+LO ; == 0 if not BEQ ISDUN ; nope PLA LDX ALLFLG ; ARE ALL FCN KEYS (<127) TERMINATORS BEQ ISCHK ; 0 = NO, GO CHECK LIST CMP #$80 ; YES, SO CHECK IF PAST 127 BCS ISFND ; YUP BCC ISNOT ISCHK: LDY #0 ISLP: CMP (TCHARS),Y ; IS CHAR WE HAVE A TCHAR? BEQ ISFND ; YES PHA LDA (TCHARS),Y ; NULL = END OF STRING BEQ ISDUN PLA INY BNE ISLP ; SHOULD ALWAYS LOOP ISDUN: PLA ; RETRIEVE CHAR ISNOT: SEC RTS ; NOT FOUND ISFND: CLC RTS ; ------------------------ ; CLEAR LBUFF FOR PRINTING ; ------------------------ CLEARP: LDY #0 LDX #0 CLRLP: LDA LBUFF,Y CMP #$80 BCS CLSKIP ; DON'T PRINT FCN KEYS CMP #00 ; (X) EOL BECOMES 00 IN XZIP BNE CLRLP0 LDA #$8D ; PRINTER NEEDS $8D CLRLP0: STA LBUFF,X INX CLSKIP: INY CPY LINLEN BNE CLRLP ; CHECK ALL CHARS STX PRLEN ; X = NEW LENGTH FOR PRINT RTS ; ----- ; INPUT ; ----- ZINPUT: LDA ARG1+LO CMP #1 ; KEYBOARD? BNE ZINPEX ; NO, INVALID JSR CLRBUF LDA WTOP ; RESET LINE COUNT STA LINCNT INC LINCNT ; save command line for later LDA #0 STA CHRCNT STA I+HI ; init locals too STA I+LO STA J+HI STA J+LO DEC NARGS BEQ ZINP3 ; NO TIME LIMIT LDA ARG2+LO ; GET DELAY WANTED STA I+HI DEC NARGS BEQ ZINP4 ; NO FCN LDA ARG3+LO STA J+LO LDA ARG3+HI STA J+HI ZINP4: JSR TIMIN ; CALL timed input rotine BCS ZINPEX ; NOBODY HOME BCC ZINPRK ; send char on home ZINP3: JSR GETKEY ; OK, FIND WHICH CHAR WAS PRESSED ZINPRK: LDX #0 JMP PUTBYT ; RETURN CHAR ZINPEX: JMP RET0 ; OOPS INTCLL: ; ; can't do this in re-entrant code!!! ; ; LDA #>ZIRET ; SET ZRETURN TO RETURN HERE ; STA PATCHI+HI ; LDA #PUTVAL ; REPAIR ZRETURN ; STA PATCHI+HI ; LDA #)@%^&*( TO ,-.0256789 GK1: LDX #ENDKEY ; GET LENGTH OF LIST GK2: CMP HAVE,X ; CHECK AGAINST LIST OF UNWANTED KEYS BEQ GK3 ; FOUND IT DEX BPL GK2 ; CHECK THEM ALL BMI GK4 ; NOT FOUND, CONTINUE OTHER CHECKS GK3: LDA WANT,X ; GET KEY TO USE INSTEAD JMP OKj ; JMP GK4: CMP #SPACE ; NO CTRL CHARS ACCEPTABLE BCC BADKEY ; IF < SPACE, BAD ; please allow '+' ; CMP #$2B ; + ; BEQ BADKEY CMP #$3C ; BCC OK CMP #$7C ; | BEQ OK CMP #$3F ; ? BEQ OK MASK0: CMP #'z'+1 ;PICK OUT LETTERS NOW BCS BADKEY ;IF > BAD CMP #'a' BCS OK ;IF > OK CMP #'A' BCC BADKEY CMP #'Z'+1 BCC OK ;IF < OK BADKEY: JSR BEEP ;BAD KEY, GIVE WARNING NOISE LDA WTFLAG ; 1 - means don't wait BNE BDj ; so don't JMP GKEY0 ;TRY AGAIN BDj: LDA #0 ; make char a 0 OK: CMP #'0' ; check for number keys BCC OKj ; nope, < 0 CMP #'9'+1 ; more than a nine? BCS OKj ; ayyup ; ; here we check for the apple keys being down too ; LDX APKEY1 ; check for open apple BMI OKj1 ; pressed, so pretend it is a function key LDX APKEY2 ; how about the other one BPL OKj ; not pressed, so use as number key ; ; transform number key into a function key OKj1: CLC ; get ready for add ADC #84 ; transforms '1'-'9' to 133-141 CMP #132 ; but '0' wants to be a 142! BNE OKj ; but it's not it CLC ; again, don't want carry ADC #10 ; voila! OKj: STA IOCHAR ;HOLD ON TO IT ADC RNUM1 ;FUTZ WITH RANDOM STA RNUM1 EOR RNUM2 STA RNUM2 PLA ; RESTORE TAY ; EVERYTHING PLA TAX LDA IOCHAR ; GET CHAR INTO [A] RTS ; AND RETURN IT HAVE: DB $0B,$0A,$08,$15 ; turns ctrl-(left side of keyboard) to function keys ; DB $11,$01,$1A,$17,$13,$18,$05,$04,$03,$12,$06,$16,$14,$07,$02,$19 DB $3C,$5F,$3E,$40,$25,$5E,$26 WANT: DB 129,130,131,132 ; DB 133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148 DB $2C,$2D,$2E,$32,$35,$36,$37 ENDKEY EQU $-WANT-1 ; INPUT: routine locals! CHARCNT: DB 0 ; where into buffer goes char SVCHAR: DB 0 ; where to save the char before printing IRET: DB 0 ; FLAG TELLS IF RETURNLESS CALL OLD0CHZ: DB 0 ; HOLDS WHERE CURSOR WAS WHEN LEFT OLD1CHZ: DB 0 ; A WINDOW SO CAN RETURN THERE OLD0EHZ: DB 0 ; WHEN REENTER THE WINDOW OLD1EHZ: DB 0 ; (MUST BE IN THIS ORDER!) OLD0CVT: DB 0 OLD1CVT: DB 0 OLDWL: DB 0 ; SAVE WLEFT & WWDTH WHILE IN SCREEN 1 OLDWD: DB 0 MTEMP: DB 00,00 ; temp spot for math routines TYPE: DB 0 ; PARTIAL OR NORMAL (WHOLE) SAVE/RESTORE ASSVLU: DB 0 ; how many args to this subroutine BRKCHR: DB 0 ; READ BREAK CHAR RDFLAG: DB 0 ; 0 - only read 1 - do lex on it FONT: DB 1,1 ; KEEP TRACK OF CURRENT FONT FOR CHANGES ; remember for each window MORE: DB "[MORE]" MOREL EQU $-MORE SLOTM: DB EOL DB "Printer Slot 1-7: " SLOTML EQU $-SLOTM STRYM: DB "The story is loading ..." STRYML EQU $-STRYM END