Skip to navigation

Elite on the BBC Micro and NES

Text: TT26

[NES version, Bank 2]

Name: TT26 [Show more] Type: Subroutine Category: Text Summary: Print a character at the text cursor, with support for verified text in extended tokens Deep dive: Extended text tokens
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * TT42 calls TT26 * DASC_b2 calls via DASC * DETOK2 calls via DASC * JMTB calls via DASC * MT26 calls via DASC * TT41 calls via DASC

Arguments: A The character to print
Returns: X X is preserved C flag The C flag is cleared
Other entry points: DASC DASC does exactly the same as TT26 and prints a character at the text cursor, with support for verified text in extended tokens
.DASC .TT26 STA SC+1 ; Store A in SC+1, so we can retrieve it later SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 LDA SC+1 ; Restore A from SC+1 STX SC ; Store X in SC, so we can retrieve it below LDX #%11111111 ; Set DTW8 = %11111111, to disable the effect of {19} if STX DTW8 ; it was set (as {19} capitalises one character only) CMP #' ' ; If the character in A is one of the following: BEQ DA8 ; CMP #'.' ; * Space BEQ DA8 ; * Full stop CMP #':' ; * Colon BEQ DA8 ; * Apostrophe (ASCII 39) CMP #39 ; * Open bracket BEQ DA8 ; * Line feed CMP #'(' ; * Carriage return BEQ DA8 ; * Hyphen CMP #10 ; BEQ DA8 ; then jump to DA8 to skip the following instructions CMP #12 ; and set bit 6 of QQ17 to print the next letter in BEQ DA8 ; upper case (so these characters don't act like the CMP #'-' ; initial capital letter in Sentence Case, for example) BEQ DA8 LDA QQ17 ; Set bit 6 of QQ17 so we print the next letter in ORA #%01000000 ; lower case STA QQ17 INX ; Increment X to 0, so DTW2 gets set to %00000000 below BEQ dasc1 ; Jump to dasc1 to skip the following (this BEQ is ; effectively a JMP as X is always zero) .DA8 LDA QQ17 ; Clear bit 6 of QQ17 so we print the next letter in AND #%10111111 ; upper case STA QQ17 .dasc1 STX DTW2 ; Store X in DTW2, so DTW2 is now: ; ; * %00000000 if this character is a word terminator ; ; * %11111111 if it isn't ; ; so DTW2 indicates whether or not we are currently ; printing a word LDX SC ; Retrieve the original value of X from SC LDA SC+1 ; Retrieve the original value of A from SC+1 (i.e. the ; character to print) BIT DTW4 ; If bit 7 of DTW4 is set then we are currently printing BMI P%+5 ; justified text, so skip the next instruction JMP CHPR ; Bit 7 of DTW4 is clear, so jump down to CHPR to print ; this character, as we are not printing justified text ; If we get here then we are printing justified text, so ; we need to buffer the text until we reach the end of ; the paragraph, so we can then pad it out with spaces BIT DTW4 ; If bit 6 of DTW4 is set, then this is an in-flight BVS P%+6 ; message and we should buffer the carriage return ; character {12}, so skip the following two instructions CMP #12 ; If the character in A is a carriage return, then we BEQ DA1 ; have reached the end of the paragraph, so jump down to ; DA1 to print out the contents of the buffer, ; justifying it as we go ; If we get here then we need to buffer this character ; in the line buffer at BUF LDX DTW5 ; DTW5 contains the current size of the buffer, so this STA BUF,X ; stores the character in A at BUF + DTW5, the next free ; space in the buffer LDX SC ; Retrieve the original value of X from SC so we can ; preserve it through this subroutine call INC DTW5 ; Increment the size of the BUF buffer that is stored in ; DTW5 SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 CLC ; Clear the C flag RTS ; Return from the subroutine .DA63S JMP DA6+3 ; Jump down to DA6+3 (this is used by the branch ; instruction below as it's too far to branch directly) .DA6S JMP DA6 ; Jump down to DA6 (this is used by the branch ; instruction below as it's too far to branch directly) .DA1 ; If we get here then we are justifying text and we have ; reached the end of the paragraph, so we need to print ; out the contents of the buffer, justifying it as we go TXA ; Store X and Y on the stack PHA TYA PHA .DA5 LDX DTW5 ; Set X = DTW5, which contains the size of the buffer BEQ DA63S ; If X = 0 then the buffer is empty, so jump down to ; DA6+3 via DA63S to print a newline CPX #(LL+1) ; If X < LL+1, i.e. X <= LL, then the buffer contains BCC DA6S ; fewer than LL characters, which is less than a line ; length, so jump down to DA6 via DA6S to print the ; contents of BUF followed by a newline, as we don't ; justify the last line of the paragraph ; Otherwise X > LL, so the buffer does not fit into one ; line, and we therefore need to justify the text, which ; we do one line at a time LSR SC+1 ; Shift SC+1 to the right, which clears bit 7 of SC+1, ; so we pass through the following comparison on the ; first iteration of the loop and set SC+1 to %01000000 .DA11 LDA SC+1 ; If bit 7 of SC+1 is set, skip the following two BMI P%+6 ; instructions LDA #%01000000 ; Set SC+1 = %01000000 STA SC+1 LDY #(LL-1) ; Set Y = line length, so we can loop backwards from the ; end of the first line in the buffer using Y as the ; loop counter .DAL1 LDA BUF+LL ; If the LL-th byte in BUF is a space, jump down to DA2 CMP #' ' ; to print out the first line from the buffer, as it BEQ DA2 ; fits the line width exactly (i.e. it's justified) ; We now want to find the last space character in the ; first line in the buffer, so we loop through the line ; using Y as a counter .DAL2 SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 DEY ; Decrement the loop counter in Y BMI DA11 ; If Y <= 0, loop back to DA11, as we have now looped BEQ DA11 ; through the whole line LDA BUF,Y ; If the Y-th byte in BUF is not a space, loop back up CMP #' ' ; to DAL2 to check the next character BNE DAL2 ; Y now points to a space character in the line buffer ASL SC+1 ; Shift SC+1 to the left BMI DAL2 ; If bit 7 of SC+1 is set, jump to DAL2 to find the next ; space character ; We now want to insert a space into the line buffer at ; position Y, which we do by shifting every character ; after position Y along by 1, and then inserting the ; space STY SC ; Store Y in SC, so we want to insert the space at ; position SC LDY DTW5 ; Fetch the buffer size from DTW5 into Y, to act as a ; loop counter for moving the line buffer along by 1 .DAL6 SETUP_PPU_FOR_ICON_BAR ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 LDA BUF,Y ; Copy the Y-th character from BUF into the Y+1-th STA BUF+1,Y ; position DEY ; Decrement the loop counter in Y CPY SC ; Loop back to shift the next character along, until we BCS DAL6 ; have moved the SC-th character (i.e. Y < SC) INC DTW5 ; Increment the buffer size in DTW5 LDA #' ' ; Set A to the ASCII for space ; ; This instruction has no effect because A already ; contains ASCII " ". This is because the last character ; that is tested in the above loop is at position SC, ; which we know contains a space, so we know A contains ; a space character when the loop finishes ; We've now shifted the line to the right by 1 from ; position SC onwards, so SC and SC+1 both contain ; spaces, and Y is now SC-1 as we did a DEY just before ; the end of the loop - in other words, we have inserted ; a space at position SC, and Y points to the character ; before the newly inserted space ; We now want to move the pointer Y left to find the ; next space in the line buffer, before looping back to ; check whether we are done, and if not, insert another ; space .DAL3 CMP BUF,Y ; If the character at position Y is not a space, jump to BNE DAL1 ; DAL1 to see whether we have now justified the line DEY ; Decrement the loop counter in Y BPL DAL3 ; Loop back to check the next character to the left, ; until we have found a space BMI DA11 ; Jump back to DA11 (this BMI is effectively a JMP as ; we already passed through a BPL to get here) .DA2 ; This subroutine prints out a full line of characters ; from the start of the line buffer in BUF, followed by ; a newline. It then removes that line from the buffer, ; shuffling the rest of the buffer contents down LDX #LL ; Call DAS1 to print out the first LL characters from JSR DAS1 ; the line buffer in BUF LDA #12 ; Print a newline JSR CHPR LDA DTW5 ; Subtract #LL from the end-of-buffer pointer in DTW5 SBC #LL ; STA DTW5 ; The subtraction works as CHPR clears the C flag TAX ; Copy the new value of DTW5 into X BEQ DA6+3 ; If DTW5 = 0 then jump down to DA6+3 to print a newline ; as the buffer is now empty ; If we get here then we have printed our line but there ; is more in the buffer, so we now want to remove the ; line we just printed from the start of BUF LDY #0 ; Set Y = 0 to count through the characters in BUF INX ; Increment X, so it now contains the number of ; characters in the buffer (as DTW5 is a zero-based ; pointer and is therefore equal to the number of ; characters minus 1) JSR SetupPPUForIconBar ; If the PPU has started drawing the icon bar, configure ; the PPU to use nametable 0 and pattern table 0 .DAL4 LDA BUF+LL+1,Y ; Copy the Y-th character from BUF+LL to BUF STA BUF,Y INY ; Increment the character pointer DEX ; Decrement the character count BNE DAL4 ; Loop back to copy the next character until we have ; shuffled down the whole buffer JMP DA5 ; Jump back to DA5 .DAS1 ; This subroutine prints out X characters from BUF, ; returning with X = 0 LDY #0 ; Set Y = 0 to point to the first character in BUF .DAL5 LDA BUF,Y ; Print the Y-th character in BUF using CHPR, which also JSR CHPR ; clears the C flag for when we return from the ; subroutine below INY ; Increment Y to point to the next character DEX ; Decrement the loop counter BNE DAL5 ; Loop back for the next character until we have printed ; X characters from BUF RTS ; Return from the subroutine .DA6 JSR DAS1 ; Call DAS1 to print X characters from BUF, returning ; with X = 0 STX DTW5 ; Set the buffer size in DTW5 to 0, as the buffer is now ; empty PLA ; Restore Y and X from the stack TAY PLA TAX LDA #12 ; Set A = 12, so when we skip BELL and fall through into ; CHPR, we print character 12, which is a newline .DA7 EQUB $2C ; Skip the next instruction by turning it into ; $2C $A9 $07, or BIT $07A9, which does nothing apart ; from affect the flags ; Fall through into CHPR (skipping BELL) to print the ; character and return with the C flag cleared