PAGE SBTTL "--- Z-STRING HANDLERS ---" ; ----------------------- ; POINT TO ZSTRING IN [I] ; ----------------------- SETSTR: LDA I+LO ; WORD-ALIGN THE ADDRESS ASL A STA MPCL LDA I+HI ROL A STA MPCM LDA #0 STA MPCFLG ; [MPC] IS CHANGING! ROL A STA MPCH ZSTEX: RTS ; ----------------------- ; PRINT Z-STRING AT [MPC] ; ----------------------- PZSTR: LDX #0 STX PSET ; ASSUME PERMANENT CHARSET STX ZFLAG ; CLEAR BYTE FLAG DEX ; = $FF STX TSET ; NO TEMPSET ACTIVE PZTOP: JSR GETZCH ; GET A Z-CHAR BCS ZSTEX ; END OF STRING IF CARRY IS SET STA ZCHAR ; ELSE SAVE CHAR HERE TAX ; SET FLAGS BEQ BLANK ; PRINT SPACE IF CHAR = 0 CMP #4 ; IS THIS AN F-WORD? BCC DOFREQ ; APPARENTLY SO CMP #6 ; PERHAPS A SHIFT CODE? BCC NEWSET ; YES, CHANGE CHARSETS JSR GETSET ; ELSE GET CHARSET TAX ; SET FLAGS BNE SET1 ; SKIP IF NOT CHARSET #0 ; PRINT A LOWER-CASE CHAR (CHARSET #0) LDA #$61-6 ; ASCII "a" MINUS Z-OFFSET TOASC: CLC ADC ZCHAR ; ADD Z-CHAR INDEX SHOVE: JSR COUT ; SHOW THE CHAR JMP PZTOP ; AND GRAB NEXT CHAR ; PRINT AN UPPER-CASE CHAR (CHARSET #1) SET1: CMP #1 ; MAKE SURE IT'S SET #1 BNE SET2 ; ELSE MUST BE SET #2 LDA #$41-6 ; ASCII "A" MINUS Z-OFFSET BNE TOASC ; SAME AS SET #0 ; PRINT FROM CHARSET #2 SET2: LDA ZCHAR ; RETRIEVE THE Z-CHAR SEC SBC #6 ; ZERO-ALIGN IT BEQ DIRECT ; IF ZERO, IT'S A "DIRECT" ASCII TAX ; OTHERWISE USE CODE AS AN INDEX LDA CHRTBL,X ; INTO THE CHARSET TABLE JMP SHOVE ; AND PRINT THE CHAR ; DECODE A "DIRECT" ASCII CHAR DIRECT: JSR GETZCH ; FETCH NEXT Z-CHAR ASL A ASL A ASL A ASL A ASL A ; SHIFT INTO POSITION STA ZCHAR ; AND SAVE HERE JSR GETZCH ; GRAB YET ANOTHER Z-CHAR ORA ZCHAR ; SUPERIMPOSE THE 2ND BYTE JMP SHOVE ; AND PRINT THE RESULT ; PRINT A SPACE BLANK: LDA #SPACE ; ASCII SPACE CHAR BNE SHOVE ; CHANGE CHARSET NEWSET: SEC ; CONVERT THE SHIFT CODE SBC #3 ; TO 1 OR 2 TAY JSR GETSET ; IS MODE TEMPORARY? BNE TOPERM ; YES, DO A PERMSHIFT STY TSET ; ELSE JUST A TEMPSHIFT JMP PZTOP ; AND CONTINUE TOPERM: STY PSET ; SET PERM CHARSET CMP PSET ; SAME AS BEFORE? BEQ PZTOP ; YES, CONTINUE LDA #0 STA PSET ; ELSE RESET CHARSET BEQ PZTOP ; BEFORE LOOPING BACK ; PRINT AN F-WORD DOFREQ: SEC SBC #1 ; ZERO-ALIGN THE CODE ASL A ; AND MULTIPLY TIMES 64 ASL A ; TO OBTAIN THE SEGMENT OFFSET ASL A ; INTO THE F-WORDS TABLE ASL A ASL A ASL A STA OFFSET ; SAVE OFFSET FOR LATER JSR GETZCH ; NOW GET THE F-WORD POINTER ASL A ; WORD-ALIGN IT CLC ; AND ADC OFFSET ; ADD THE SEGMENT OFFSET TAY ; TO GET THE OFFSET OF THE F-WORD LDA (FWORDS),Y ; FROM THE START OF THE F-WORDS TABLE STA I+HI ; SAVE MSB OF F-WORD ADDRESS INY LDA (FWORDS),Y ; ALSO SAVE LSB STA I+LO ; Z-ADDRESS OF F-WORD IS IN [I] ; SAVE THE STATE OF CURRENT Z-STRING LDA MPCH PHA LDA MPCM PHA LDA MPCL PHA LDA PSET PHA LDA ZFLAG PHA LDA ZWORD+HI PHA LDA ZWORD+LO PHA JSR SETSTR ; PRINT THE Z-STRING JSR PZSTR ; IN [I] ; RESTORE OLD Z-STRING PLA STA ZWORD+LO PLA STA ZWORD+HI PLA STA ZFLAG PLA STA PSET PLA STA MPCL PLA STA MPCM PLA STA MPCH LDX #$FF STX TSET ; DISABLE TEMP CHARSET INX ; = 0 STX MPCFLG ; [MPC] HAS CHANGED JMP PZTOP ; CONTINUE INNOCENTLY ; ---------------------- ; RETURN CURRENT CHARSET ; ---------------------- GETSET: LDA TSET BPL GS LDA PSET RTS GS: LDY #$FF STY TSET RTS ; ----------------- ; FETCH NEXT Z-CHAR ; ----------------- GETZCH: LDA ZFLAG ; WHICH BYTE IS THIS? BPL GTZ0 ; $FF = LAST SEC ; SET CARRY TO INDICATE RTS ; NO MORE CHARS GTZ0: BNE GETZ1 ; NOT FIRST CHAR, EITHER ; GET A Z-WORD INTO [ZWORD], RETURN 1ST CHAR IN TRIPLET INC ZFLAG ; UPDATE CHAR COUNT JSR GETBYT ; GET TRIPLET AT [MPC] STA ZWORD+HI ; INTO [ZWORD] JSR GETBYT STA ZWORD+LO LDA ZWORD+HI LSR A LSR A ; SHIFT 1ST CHAR INTO PLACE JMP GTEXIT ; AND RETURN IT GETZ1: SEC SBC #1 BNE GETZ2 ; LAST CHAR IN TRIPLET IF ZERO LDA #2 ; ELSE STA ZFLAG ; RESET CHAR INDEX LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET STA I+LO ; MOVE HERE FOR SHIFTING LDA ZWORD+HI ; GET TOP HALF ASL I+LO ; SHIFT THE TOP 3 BITS OF LOWER HALF ROL A ; INTO THE BOTTOM OF THE TOP HALF ASL I+LO ROL A ASL I+LO ROL A JMP GTEXIT GETZ2: LDA #0 ; SET FLAG TO INDICATE STA ZFLAG ; END OF TRIPLET LDA ZWORD+HI ; TEST TOP HALF OF TRIPLET BPL GETZ3 ; CONTINUE IF NOT END OF STRING LDA #$FF ; ELSE STA ZFLAG ; INDICATE LAST TRIPLET IN STRING GETZ3: LDA ZWORD+LO ; GET BOTTOM HALF OF TRIPLET GTEXIT: AND #%00011111 ; MASK OUT GARBAGE BITS CLC RTS ; --------------------------------- ; CONVERT [IN] TO Z-STRING IN [OUT] ; --------------------------------- CONZST: LDA #$05 ; FILL OUTPUT BUFFER TAX ; WITH PAD CHARS ($05) CZSL: STA OUT,X DEX BPL CZSL LDA #6 ; INIT STA CONCNT ; CHAR COUNT LDA #0 ; CLEAR STA CONIN ; SOURCE AND STA CONOUT ; OUTPUT INDEXES CONTOP: LDX CONIN ; FETCH SOURCE INDEX INC CONIN ; AND UPDATE LDA IN,X ; GRAB AN ASCII CHAR STA ZCHAR ; SAVE IT HERE BNE NEXTZ ; CONTINUE IF CHAR WAS NZ LDA #5 ; ELSE SHIP OUT BNE CSHIP ; A PAD CHAR NEXTZ: LDA ZCHAR JSR SAYSET ; WHICH CHARSET TO USE? BEQ CSET0 ; LOWER-CASE IF ZERO CLC ; ELSE DO A TEMP-SHIFT ADC #3 ; 4 = CHARSET 1, 5 = CHARSET 2 LDX CONOUT ; FETCH OUTPUT INDEX STA OUT,X ; SEND THE SHIFT CHAR INC CONOUT ; UPDATE INDEX DEC CONCNT ; AND CHAR COUNT BNE CTEST ; IF OUT OF CHARS JMP ZCRUSH ; CRUSH 'EM! CTEST: LDA ZCHAR ; TEST CHAR AGAIN JSR SAYSET CMP #2 BEQ CSET2 ; CHARSET #2 ; HANDLE CHARSET #1 (UPPER CASE ALPHA) LDA ZCHAR SEC SBC #$41-6 ; CONVERT TO Z-CHAR BPL CSHIP ; AND SEND TO OUTPUT ; HANDLE CHARSET #0 (LOWER CASE ALPHA) CSET0: LDA ZCHAR SEC SBC #$61-6 ; CONVERT TO Z-CHAR ; SHIP Z-CHAR TO OUTPUT BUFFER CSHIP: LDX CONOUT ; FETCH OUTPUT INDEX STA OUT,X INC CONOUT ; UPDATE INDEX DEC CONCNT ; DONE 6 CHARS YET? BNE CONTOP ; NO, LOOP BACK JMP ZCRUSH ; ELSE CRUSH ; HANDLE CHARSET #2 (MISCELLANEOUS) CSET2: LDA ZCHAR ; GRAB CHAR JSR CTABLE ; IS IT IN CHARSET #3 TABLE? BNE CSHIP ; YES, SEND IT TO OUTPUT ; SEND A "DIRECT" ASCII CHAR LDA #6 ; ASCII ALERT! LDX CONOUT STA OUT,X INC CONOUT ; UPDATE INDEX DEC CONCNT ; AND CHAR COUNT BEQ ZCRUSH ; BUFFER FULL! ; SEND 1ST HALF OF "DIRECT" LDA ZCHAR LSR A LSR A LSR A LSR A LSR A AND #%00000011 ; MASK GARBAGE LDX CONOUT STA OUT,X INC CONOUT DEC CONCNT BEQ ZCRUSH ; BUFFER FULL! ; SEND 2ND HALF OF "DIRECT" LDA ZCHAR ; GET CHAR YET AGAIN AND #%00011111 ; MASK JUNK JMP CSHIP ; AND SHIP IT OUT ; --------------------- ; IS [A] IN CHARSET #3? ; --------------------- ; EXIT: [A] = CHAR CODE IF FOUND, Z-FLAG CLEARED ; Z-FLAG SET IF NOT FOUND CTABLE: LDX #25 CNL: CMP CHRTBL,X BEQ CNOK DEX BNE CNL RTS ; Z-FLAG SET IF NO MATCH CNOK: TXA ; CHAR CODE IS INDEX CLC ADC #6 ; PLUS 6 RTS ; ----------------------------- ; RETURN CHARSET OF CHAR IN [A] ; ----------------------------- SAYSET: CMP #'a' BCC SAY1 CMP #'z'+1 BCS SAY1 LDA #0 ; IT'S CHARSET #0 RTS SAY1: CMP #'A' BCC SAY2 CMP #'Z'+1 BCS SAY2 LDA #1 ; IT'S CHARSET #1 RTS SAY2: LDA #2 ; IT'S CHARSET #2 RTS ; ---------------------- ; CRUSH Z-CHARS IN [OUT] ; ---------------------- ZCRUSH: LDA OUT+1 ; GET 2ND Z-CHAR ASL A ; SHIFT BITS INTO POSITION ASL A ASL A ASL A ROL OUT ; ALONG WITH 1ST Z-CHAR ASL A ROL OUT ORA OUT+2 ; SUPERIMPOSE 3RD Z-CHAR STA OUT+1 LDA OUT+4 ; GET 5TH Z-CHAR ASL A ; SHIFT BITS ASL A ASL A ASL A ROL OUT+3 ; ALONG WITH 4TH Z-CHAR ASL A ROL OUT+3 ORA OUT+5 ; SUPERIMPOSE 6TH Z-CHAR TAX ; SAVE HERE LDA OUT+3 ; GRAB 4TH Z-CHAR ORA #%10000000 ; SET HIGH BIT STA OUT+2 ; MOVE CRUSHED Z-WORD STX OUT+3 ; INTO PLACE RTS ; ----------------------- ; CHARSET #2 DECODE TABLE ; ----------------------- CHRTBL: DB 0 ; DUMMY BYTE FOR "DIRECT" DB $0D ; EOL DB "0123456789.,!?_#" DB $27 ; SINGLE QUOTE DB $22 ; DOUBLE QUOTE DB "/\-:()" END