.ShowScrollText PHA ; Store the value of A on the stack so we can retrieve ; it later to check which scroll text to show LDA QQ11 ; If this is not the space view, then jump to scro1 to BNE scro1 ; set up the space view for the demo JSR ClearScanner ; This is already the space view, so remove all ships ; from the scanner and hide the scanner sprites JMP scro4 ; Jump to scro4 to move on to the scroll text part, as ; the view is already set up .scro1 ; If we get here then we need to set up the space view ; for the demo JSR FadeToBlack_b3 ; Fade the screen to black over the next four VBlanks LDY #NOST ; Set Y to the number of stardust particles in NOST ; (which is 20 in the space view), so we can use it as a ; counter as we set up the stardust below STY NOSTM ; Set the number of stardust particles to NOST (which is ; 20 for the normal space view) STY RAND+1 ; Set RAND+1 to NOST to seed the random number generator LDA nmiCounter ; Set the random number seed to a fairly random state STA RAND ; that's based on the NMI counter (which increments ; every VBlank, so will be pretty random) .scro2 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 ; We now set up the coordinates of stardust particle Y JSR DORND ; Set A and X to random numbers ORA #8 ; Set A so that it's at least 8 STA SZ,Y ; Store A in the Y-th particle's z_hi coordinate at ; SZ+Y, so the particle appears in front of us STA ZZ ; Set ZZ to the particle's z_hi coordinate JSR DORND ; Set A and X to random numbers STA SX,Y ; Store A in the Y-th particle's x_hi coordinate at ; SX+Y, so the particle appears in front of us JSR DORND ; Set A and X to random numbers STA SY,Y ; Store A in the Y-th particle's y_hi coordinate at ; SY+Y, so the particle appears in front of us DEY ; Decrement the counter to point to the next particle of ; stardust BNE scro2 ; Loop back to scro2 until we have randomised all the ; stardust particles LDX #NOST ; Set X to the maximum number of stardust particles, so ; we loop through all the particles of stardust in the ; following LDY #152 ; Set Y to the starting index in the sprite buffer, so ; we start configuring from sprite 152 / 4 = 38 (as each ; sprite in the buffer consists of four bytes) .scro3 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 ; We now set up the sprite for stardust particle Y LDA #210 ; Set the sprite to use pattern number 210 for the STA pattSprite0,Y ; largest particle of stardust (the stardust particle ; patterns run from pattern 210 to 214, decreasing in ; size as the number increases) TXA ; Take the particle number, which is between 1 and 20 LSR A ; (as NOST is 20), and rotate it around from %76543210 ROR A ; to %10xxxxx3 (where x indicates a zero), storing the ROR A ; result as the sprite attribute AND #%11100001 ; STA attrSprite0,Y ; This sets the flip horizontally and flip vertically ; attributes to bits 0 and 1 of the particle number, and ; the palette to bit 3 of the particle number, so the ; reset stardust particles have a variety of reflections ; and palettes INY ; Add 4 to Y so it points to the next sprite's data in INY ; the sprite buffer INY INY DEX ; Decrement the loop counter in X BNE scro3 ; Loop back until we have configured 20 sprites JSR STARS_b1 ; Call STARS1 to process the stardust for the front view .scro4 LDA #0 ; Remove the laser from our ship, so we can't fire it STA LASER ; during the scroll text STA QQ12 ; Set QQ12 = 0 to indicate that we are not docked LDA #$10 ; Clear the screen and set the view type in QQ11 to $10 JSR ChangeToView_b0 ; (Space view with the normal font loaded) LDA #$FF ; Set showIconBarPointer = $FF to indicate that we STA showIconBarPointer ; should show the icon bar pointer LDA #240 ; Set A to the y-coordinate that's just below the bottom ; of the screen, so we can hide the sight sprites by ; moving them off-screen STA ySprite5 ; Set the y-coordinates for the five laser sight sprites STA ySprite6 ; to 240, to move them off-screen STA ySprite7 STA ySprite8 STA ySprite9 ; We are going to draw the scroll text into the pattern ; buffers, so now we calculate the addresses of the ; first available tiles in the buffers LDA #0 ; Set the high byte of SC(1 0) to 0 STA SC+1 LDA firstFreePattern ; Set SC(1 0) = firstFreePattern * 8 ASL A ROL SC+1 ; We use this to calculate the address of the pattern ASL A ; for the first free pattern in the pattern buffers ROL SC+1 ; below ASL A ROL SC+1 STA SC STA SC2 ; Set SC2(1 0) = pattBuffer1 + SC(1 0) LDA SC+1 ; = pattBuffer1 + firstFreePattern * 8 ADC #HI(pattBuffer1) ; STA SC2+1 ; So SC2(1 0) contains the address of the pattern of the ; first free tile in pattern buffer 1, as each pattern ; in the buffer contains eight bytes LDA SC+1 ; Set SC(1 0) = pattBuffer0 + SC(1 0) ADC #HI(pattBuffer0) ; = pattBuffer0 + firstFreePattern * 8 STA SC+1 ; ; So SC2(1 0) contains the address of the pattern of the ; first free tile in pattern buffer 0 ; We now clear the patterns in both pattern buffers for ; the free tile and all the other tiles to the end of ; the buffers LDX firstFreePattern ; Set X to the number of the first free pattern so we ; start clearing patterns from this point onwards LDY #0 ; Set Y to use as a byte index for zeroing the pattern ; bytes in the pattern buffers .scro5 LDA #0 ; Set A = 0 so we zero the pattern STA (SC),Y ; Zero the Y-th pixel row of pattern X in both of the STA (SC2),Y ; pattern buffers and increment the index in Y INY STA (SC),Y ; Zero the Y-th pixel row of pattern X in both of the STA (SC2),Y ; pattern buffers and increment the index in Y INY STA (SC),Y ; Zero the Y-th pixel row of pattern X in both of the STA (SC2),Y ; pattern buffers and increment the index in Y INY STA (SC),Y ; Zero the Y-th pixel row of pattern X in both of the STA (SC2),Y ; pattern buffers and increment the index in Y INY STA (SC),Y ; Zero the Y-th pixel row of pattern X in both of the STA (SC2),Y ; pattern buffers and increment the index in Y INY STA (SC),Y ; Zero the Y-th pixel row of pattern X in both of the STA (SC2),Y ; pattern buffers and increment the index in Y INY STA (SC),Y ; Zero the Y-th pixel row of pattern X in both of the STA (SC2),Y ; pattern buffers and increment the index in Y INY STA (SC),Y ; Zero the Y-th pixel row of pattern X in both of the STA (SC2),Y ; pattern buffers and increment the index in Y INY BNE scro6 ; If Y just incremented to 0, increment the high bytes INC SC+1 ; of SC(1 0) and SC2(1 0) so they point to the next page INC SC2+1 ; in memory .scro6 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 INX ; Increment the pattern number in X BNE scro5 ; Loop back until we have cleared all patterns up to and ; including pattern 255 LDA #0 ; Set ALPHA and ALP1 to 0, so our roll angle is 0 STA ALPHA STA ALP1 STA DELTA ; Set our ship's speed to zero so the scroll text stays ; where it is LDA nmiCounter ; Set the random number seed to a fairly random state CLC ; that's based on the NMI counter (which increments ADC RAND+1 ; every VBlank, so will be pretty random) STA RAND+1 JSR DrawScrollInNMI ; Configure the NMI handler to draw the scroll text ; screen, which will clear the screen as we just blanked ; out all the patterns in the pattern buffers PLA ; Retrieve the argument that we stored on the stack at BNE scro7 ; the start of the routine, which contains the scroll ; text that we should be showing and if it is non-zero, ; jump to scro7 to skip playing the combat part of the ; demo, as we are either showing the results of combat ; practice, or we are showing the credits ; If we get here then A = 0 and we are show the first ; scroll text before starting the combat demo LDX languageIndex ; Set (Y X) to the address of the text for the first LDA scrollText1Lo,X ; scroll text for the chosen language LDY scrollText1Hi,X TAX LDA #2 ; Draw the first scroll text at scrollText1, which has JSR DrawScrollText ; six lines (so we set A = 2, as it needs to contain ; the number of lines minus 4) ; We are now ready to start the combat part of the ; combat demo LDA #$00 ; Set the view type in QQ11 to $00 (Space view with STA QQ11 ; no fonts loaded) JSR SetLinePatterns_b3 ; Load the line patterns for the new view into the ; pattern buffers LDA #37 ; Tell the NMI handler to send pattern entries from STA firstPattern ; pattern 37 in the buffer JSR DrawScrollInNMI ; Configure the NMI handler to draw the scroll text ; screen, which will draw the scroll text on-screen LDA #60 ; Tell the NMI handler to send pattern entries from STA firstPattern ; pattern 60 in the buffer JMP PlayDemo_b0 ; Play the combat demo, returning from the subroutine ; using a tail call .scro7 CMP #2 ; If we called this routine with A = 2 then jump to BEQ scro14 ; scro14 to show the credits scroll text ; Otherwise A = 1, so we show the second scroll text, ; including the time taken for combat practice, so we ; start by calculating the time taken and storing the ; results in K5, so the GRIDSET routine can draw the ; correct characters for the time taken ; ; Specifically, the second scroll text in scrollText2 ; expects the characters to be set as follows: ; ; * $83 is the first digit of the minutes ; ; * $82 is the second digit of the minutes ; ; * $81 is the first digit of the seconds ; ; * $80 is the second digit of the seconds ; ; while GRIDSET expect to find these values at the ; following locations: ; ; * Character $83 refers to location K5+3 ; ; * Character $82 refers to location K5+2 ; ; * Character $81 refers to location K5+1 ; ; * Character $80 refers to location K5 ; ; Finally, the number of seconds that we need to display ; is in (nmiTimerHi nmiTimerLo), so we need to convert ; this into minutes and seconds, and then set the values ; in K5 to the correct ASCII characters that represent ; the digits of this time LDA #'0' ; Set all the digits to 0 except the second digit of the STA K5+1 ; seconds (as we will set this later) STA K5+2 STA K5+3 LDA #100 ; Set nmiTimer = 100 so (nmiTimerHi nmiTimerLo) will not STA nmiTimer ; change during the following calculation (as nmiTimer ; has to tick down to zero for that to happen, so this ; gives us 100 VBlanks to complete the calculation ; before (nmiTimerHi nmiTimerLo) changes) ; We start with the first digit of the minute count (the ; "tens" digit) SEC ; Set the C flag for the following subtraction .scro8 LDA nmiTimerLo ; Set (A X) = (nmiTimerHi nmiTimerLo) - $0258 SBC #$58 ; = (nmiTimerHi nmiTimerLo) - 600 TAX LDA nmiTimerHi SBC #$02 BCC scro9 ; If the subtraction underflowed then we know that ; (nmiTimerHi nmiTimerLo) < 600, so jump to scro9 to ; move on to the next digit ; If we get here then (nmiTimerHi nmiTimerLo) >= 600, ; so the time in (nmiTimerHi nmiTimerLo) is at least ; ten minutes, so we increment the first digit of the ; minute count in K5+3, update the time in ; (nmiTimerHi nmiTimerLo) to (A X), and loop back to ; try subtracting another 10 minutes STA nmiTimerHi ; Set (nmiTimerHi nmiTimerLo) = (A X) STX nmiTimerLo ; ; So this updates (nmiTimerHi nmiTimerLo) with the new ; value, which is ten minutes less than the original ; value INC K5+3 ; Increment the first digit of the minute count in K5+3 ; to bump it up from, say, "0" to "1" BCS scro8 ; Loop back to scro8 to try subtracting another ten ; minutes (this BCS is effectively a JMP as we just ; passed through a BCC) .scro9 ; Now for the second digit of the minute count (the ; "ones" digit) SEC ; Set the C flag for the following subtraction LDA nmiTimerLo ; Set (A X) = (nmiTimerHi nmiTimerLo) - $003C SBC #$3C ; = (nmiTimerHi nmiTimerLo) - 60 TAX LDA nmiTimerHi SBC #$00 BCC scro10 ; If the subtraction underflowed then we know that ; (nmiTimerHi nmiTimerLo) < 60, so jump to scro10 to ; move on to the next digit ; If we get here then (nmiTimerHi nmiTimerLo) >= 60, ; so the time in (nmiTimerHi nmiTimerLo) is at least ; one minute, so we increment the second digit of the ; minute count in K5+2, update the time in ; (nmiTimerHi nmiTimerLo) to (A X), and loop back to ; try subtracting another minute STA nmiTimerHi ; Set (nmiTimerHi nmiTimerLo) = (A X) STX nmiTimerLo ; ; So this updates (nmiTimerHi nmiTimerLo) with the new ; value, which is one minute less than the original ; value INC K5+2 ; Increment the second digit of the minute count in K5+2 ; to bump it up from, say, "0" to "1" BCS scro9 ; Loop back to scro8 to try subtracting another minute ; (this BCS is effectively a JMP as we just passed ; through a BCC) .scro10 ; Now for the first digit of the second count (the ; "tens" digit) ; ; By this point we know that (nmiTimerHi nmiTimerLo) is ; less than 60, so we can ignore the high byte as it is ; zero by now SEC ; Set the C flag for the following subtraction LDA nmiTimerLo ; Set A to the number of seconds we want to display .scro11 SBC #10 ; Set A = nmiTimerLo - 10 BCC scro12 ; If the subtraction underflowed then we know that ; nmiTimerLo < 10, so jump to scro12 to move on to the ; final digit ; If we get here then nmiTimerLo >= 10, so the time in ; nmiTimerLo is at least ten seconds, so we increment ; the first digit of the seconds count in K5+1 and loop ; back to try subtracting another ten seconds INC K5+1 ; Increment the first digit of the seconds count in K5+1 ; to bump it up from, say, "0" to "1" BCS scro11 ; Loop back to scro8 to try subtracting another ten ; seconds (this BCS is effectively a JMP as we just ; passed through a BCC) .scro12 ; By this point A contains the number of seconds left ; after subtracting the final ten seconds, so it is ; ten less than the value we want to display ADC #'0'+10 ; Set the character for the second digit of the seconds STA K5 ; count in K5 to the value in A, plus the ten that we ; subtracted before we jumped here, plus ASCII "0" to ; convert it into a character ; Now that the practice time is set up, we can show the ; second scroll text to report the results LDX languageIndex ; Set (Y X) to the address of the text for the second LDA scrollText2Lo,X ; scroll text for the chosen language LDY scrollText2Hi,X TAX LDA #6 ; We are now going to draw the second scroll text ; at scrollText2, which has ten lines, so we set ; A = 6 to pass to DrawScrollText, as it needs to ; contain the number of lines minus 4 .scro13 JSR DrawScrollText ; Draw the scroll text at (Y X), which will either be ; the second scroll text at scrollText2 or the third ; credits scroll text at creditsText3, depending on how ; we get here JSR FadeToBlack_b3 ; Fade the screen to black over the next four VBlanks JMP StartGame_b0 ; Jump to StartGame to reset the stack and go to the ; docking bay (i.e. show the Status Mode screen) .scro14 ; If we get here then we show the credits scroll text, ; which is in three parts LDX languageIndex ; Set (Y X) to the address of the text for the first LDA creditsText1Lo,X ; credits scroll text for the chosen language LDY creditsText1Hi,X TAX LDA #6 ; Draw the first credits scroll text at creditsText1, JSR DrawScrollText ; which has ten lines (so we set A = 6, as it needs to ; contain the number of lines minus 4) JSR WaitForNMI ; Wait until the next NMI interrupt has passed (i.e. the ; next VBlank) LDX languageIndex ; Set (Y X) to the address of the text for the second LDA creditsText2Lo,X ; credits scroll text for the chosen language LDY creditsText2Hi,X TAX LDA #5 ; Draw the second credits scroll text at creditsText2, JSR DrawScrollText ; which has nine lines (so we set A = 5, as it needs to ; contain the number of lines minus 4) JSR WaitForNMI ; Wait until the next NMI interrupt has passed (i.e. the ; next VBlank) LDX languageIndex ; Set (Y X) to the address of the text for the third LDA creditsText3Lo,X ; credits scroll text for the chosen language LDY creditsText3Hi,X TAX LDA #3 ; We are now going to draw the third credits scroll text ; at creditsText3, which has seven lines, so we set ; A = 3 to pass to DrawScrollText, as it needs to ; contain the number of lines minus 4 BNE scro13 ; Jump to scro13 to draw the third credits scroll text ; at creditsText3 (this BNE is effectively a JMP as A is ; never zeroName: ShowScrollText [Show more] Type: Subroutine Category: Combat demo Summary: Show a scroll text and start the combat demo Deep dive: The NES combat demoContext: See this subroutine in context in the source code References: This subroutine is called as follows: * ShowScrollText_b6 calls ShowScrollText
Arguments: A The scroll text to show: * 0 = show the first scroll text and start combat practice * 1 = show the second scroll text, including the time taken for combat practice * 2 = show the credits scroll text
[X]
Subroutine ChangeToView_b0 (category: Drawing the screen)
Call the ChangeToView routine in ROM bank 0
[X]
Subroutine ClearScanner (category: Dashboard)
Remove all ships from the scanner and hide the scanner sprites
[X]
Subroutine DORND (category: Maths (Arithmetic))
Generate random numbers
[X]
Subroutine DrawScrollInNMI (category: Combat demo)
Configure the NMI handler to draw the scroll text screen
[X]
Subroutine DrawScrollText (category: Combat demo)
Display a Star Wars scroll text
[X]
Subroutine FadeToBlack_b3 (category: Drawing the screen)
Call the FadeToBlack routine in ROM bank 3
[X]
Configuration variable NOST = 20
The number of stardust particles in normal space (this goes down to 3 in witchspace)
[X]
Subroutine PlayDemo_b0 (category: Combat demo)
Call the PlayDemo routine in ROM bank 0
[X]
Macro SETUP_PPU_FOR_ICON_BAR (category: PPU)
If the PPU has started drawing the icon bar, configure the PPU to use nametable 0 and pattern table 0
[X]
Subroutine STARS_b1 (category: Stardust)
Call the STARS routine in ROM bank 1
[X]
Subroutine SetLinePatterns_b3 (category: Drawing the screen)
Call the SetLinePatterns routine in ROM bank 3
[X]
Subroutine StartGame_b0 (category: Start and end)
Switch to ROM bank 0 and call the StartGame routine
[X]
Subroutine WaitForNMI (category: Utility routines)
Wait until the next NMI interrupt has passed (i.e. the next VBlank)
[X]
Variable attrSprite0 in workspace Sprite buffer
Attributes for sprite 0
[X]
Variable creditsText1Hi (category: Combat demo)
Lookup table for the high byte of the address of the creditsText1 text for each language
[X]
Variable creditsText1Lo (category: Combat demo)
Lookup table for the low byte of the address of the creditsText1 text for each language
[X]
Variable creditsText2Hi (category: Combat demo)
Lookup table for the high byte of the address of the creditsText2 text for each language
[X]
Variable creditsText2Lo (category: Combat demo)
Lookup table for the low byte of the address of the creditsText2 text for each language
[X]
Variable creditsText3Hi (category: Combat demo)
Lookup table for the high byte of the address of the creditsText3 text for each language
[X]
Variable creditsText3Lo (category: Combat demo)
Lookup table for the low byte of the address of the creditsText3 text for each language
[X]
Variable firstFreePattern in workspace ZP
Contains the number of the first free pattern in the pattern buffer that we can draw into next (or 0 if there are no free patterns)
[X]
Variable firstPattern in workspace ZP
The number of the first pattern for which we send data to the PPU in the NMI handler (potentially for both bitplanes, if both are configured to be sent)
[X]
Variable languageIndex in workspace WP
The language that was chosen on the Start screen as an index into the various lookup tables
[X]
Variable nmiCounter in workspace WP
A counter that increments every VBlank at the start of the NMI handler
[X]
Variable nmiTimerHi in workspace ZP
High byte of a counter that's incremented by 1 every time nmiTimer wraps
[X]
Variable nmiTimerLo in workspace ZP
Low byte of a counter that's incremented by 1 every time nmiTimer wraps
[X]
Variable pattBuffer0 in workspace Cartridge WRAM
The pattern buffer for bitplane 0 (1 bit per pixel) that gets sent to the PPU during VBlank
[X]
Variable pattBuffer1 in workspace Cartridge WRAM
The pattern buffer for bitplane 1 (1 bit per pixel) that gets sent to the PPU during VBlank
[X]
Variable pattSprite0 in workspace Sprite buffer
Pattern number for sprite 0
[X]
Label scro1 is local to this routine
[X]
Label scro10 is local to this routine
[X]
Label scro11 is local to this routine
[X]
Label scro12 is local to this routine
[X]
Label scro13 is local to this routine
[X]
Label scro14 is local to this routine
[X]
Label scro2 is local to this routine
[X]
Label scro3 is local to this routine
[X]
Label scro4 is local to this routine
[X]
Label scro5 is local to this routine
[X]
Label scro6 is local to this routine
[X]
Label scro7 is local to this routine
[X]
Label scro8 is local to this routine
[X]
Label scro9 is local to this routine
[X]
Variable scrollText1Hi (category: Combat demo)
Lookup table for the high byte of the address of the scrollText1 text for each language
[X]
Variable scrollText1Lo (category: Combat demo)
Lookup table for the low byte of the address of the scrollText1 text for each language
[X]
Variable scrollText2Hi (category: Combat demo)
Lookup table for the high byte of the address of the scrollText2 text for each language
[X]
Variable scrollText2Lo (category: Combat demo)
Lookup table for the low byte of the address of the scrollText2 text for each language
[X]
Variable showIconBarPointer in workspace WP
Controls whether to show the icon bar pointer
[X]
Variable ySprite5 in workspace Sprite buffer
Screen y-coordinate for sprite 5
[X]
Variable ySprite6 in workspace Sprite buffer
Screen y-coordinate for sprite 6
[X]
Variable ySprite7 in workspace Sprite buffer
Screen y-coordinate for sprite 7
[X]
Variable ySprite8 in workspace Sprite buffer
Screen y-coordinate for sprite 8
[X]
Variable ySprite9 in workspace Sprite buffer
Screen y-coordinate for sprite 9