Skip to navigation

Revs on the BBC Micro

Screen mode: ScreenHandler

Name: ScreenHandler [Show more] Type: Subroutine Category: Screen mode Summary: The IRQ handler for the custom screen mode Deep dive: Hidden secrets of the custom screen mode
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * SetCustomScreen calls ScreenHandler

The screen handler starts a new screen with screenSection = -1, and then increments it through 0, 1, 2, 3, 4 and 5, at which point this handler stops doing anything.
Other entry points: ScreenHandler-3 Jump to the original IRQ handler
JMP (irq1Address) \ Jump to the original address from IRQ1V to pass \ control to the next interrupt handler .ScreenHandler LDA VIA+&6D \ Set A to the 6522 User VIA interrupt flag register IFR \ (SHEILA &46D) AND #%01000000 \ Extract bit 6, which is set when 6522 User VIA timer 1 \ runs down to zero BEQ ScreenHandler-3 \ If the Timer1 interrupt has not fired, jump up to \ ScreenHandler-3 as we do not need to do anything at \ this point STA VIA+&6D \ Set bit 6 of the 6522 User VIA interrupt flag register \ IFR (SHEILA &6D) to clear the timer 1 interrupt (the \ timer will already have restarted as we set it to \ continuous interrupts in SetCustomScreen) TXA \ Store X on the stack so we can preserve it through the PHA \ interrupt handler CLD \ Clear the D flag to switch arithmetic to normal LDA screenSection \ If screenSection = 0, jump to hand1 BEQ hand1 BMI hand4 \ If screenSection is negative, jump to hand4 CMP #2 \ If screenSection < 2, i.e. screenSection = 1, jump to BCC hand5 \ hand5 BEQ hand7 \ If screenSection = 2, jump to hand7 CMP #3 \ If screenSection = 3, jump to hand9 BEQ hand9 BCS hand11 \ If screenSection >= 3, i.e. screenSection = 4, jump \ to hand11 .hand1 \ If we get here, then screenSection = 0, so we set the \ screen mode to 4 and the palette for the top two lines \ of text (where the race information is printed) LDA #%10001000 \ Set the Video ULA control register (SHEILA &20) to STA VIA+&20 \ %10001000, which is the same as switching to mode 4 LDX #15 \ We now send the 16 palette bytes at paletteSection0 to \ the Video ULA palette in SHEILA &21, so set a loop \ counter in X .hand2 LDA paletteSection0,X \ Set the X-th byte of paletteSection0 to the Video ULA STA VIA+&21 \ palette DEX \ Decrement the loop counter BPL hand2 \ Loop back until we have sent all 16 bytes .hand3 LDA #&C4 \ Set (X A) = &0FC4 to latch into the User VIA timer 1, LDX #&0F \ so on the next timer loop it counts down from &0FC4 \ (4036) BNE hand13 \ Jump to hand13 to latch (X A) into User VIA timer 1 \ and return from the subroutine (this BNE is \ effectively a JMP as X is never zero) .hand4 \ If we get here, then screenSection is negative CMP #&FF \ If screenSection <> -1, then jump to hand14 to BNE hand14 \ return from the interrupt handler \ If we get here, then screenSection = -1 INC screenSection \ Set screenSection = 0 BEQ hand3 \ Jump to hand3 to set timer 1 counting down from &0FC4 \ and return from the interrupt handler (this BNE is \ effectively a JMP as screenSection is always zero) .hand5 \ If we get here, then screenSection = 1, so we change \ the palette so everything is blue, as this is the \ portion of cloudless sky between the text at the top \ of the screen and the car and track at the bottom LDA #%11000100 \ Set the Video ULA control register (SHEILA &20) to STA VIA+&20 \ %11000100, which is the same as switching to mode 5 CLC \ Clear the C flag for the additions in the following \ loop \ We now send the following bytes to the Video ULA \ palette in SHEILA &21, by starting at 3 and adding &10 \ to send &03, &13, &23 ... &E3, &F3 \ \ This maps all four logical colours (the top nibble) to \ &3 EOR 7 (the bottom nibble, EOR 7), which maps them \ to colour 4, or blue LDA #&03 \ Set A = &03 as the first byte to send .hand6 STA VIA+&21 \ Send A to SHEILA &21 to send the palette byte in A to \ the Video ULA ADC #&10 \ Set A = A + &10 BCC hand6 \ Loop back until the addition overflows after we send \ &F3 to the ULA LDA #&3C \ Set screenTimer2 = &153C - screenTimer1 SEC \ SBC screenTimer1 \ starting with the low bytes STA screenTimer2 LDA #&15 \ And then the high bytes SBC screenTimer1+1 STA screenTimer2+1 LDA screenTimer1 \ Set (X A) = screenTimer1 to latch into the User VIA LDX screenTimer1+1 \ timer 1, so on the next timer loop it counts down from \ screenTimer1 BCS hand13 \ Jump to hand13 to latch (X A) into User VIA timer 1 \ and return from the subroutine (this BCS is \ effectively a JMP as the C flag is still set from \ above) .hand7 \ If we get here, then screenSection = 2 LDX #15 \ We now send the 16 palette bytes at paletteSection2 to \ the Video ULA palette in SHEILA &21, so set a loop \ counter in X .hand8 LDA paletteSection2,X \ Set the X-th byte of paletteSection2 to the Video ULA STA VIA+&21 \ palette DEX \ Decrement the loop counter BPL hand8 \ Loop back until we have sent all 16 bytes LDA screenTimer2 \ Set (X A) = screenTimer2 to latch into the User VIA LDX screenTimer2+1 \ timer 1, so on the next timer loop it counts down from \ screenTimer2 BNE hand13 \ Jump to hand13 to latch (X A) into User VIA timer 1 \ and return from the subroutine (this BNE is \ effectively a JMP as X is never zero) .hand9 \ If we get here, then screenSection = 3 LDX #3 \ We now send the 3 palette bytes at paletteSection3 to \ the Video ULA palette in SHEILA &21, so set a loop \ counter in X .hand10 LDA paletteSection3,X \ Set the X-th byte of paletteSection2 to the Video ULA STA VIA+&21 \ palette DEX \ Decrement the loop counter BPL hand10 \ Loop back until we have sent all 16 bytes LDA #&00 \ Set (X A) = &1E00 to latch into the User VIA timer 1, LDX #&1E \ so on the next timer loop it counts down from &1E00 \ (7680) BNE hand13 \ Jump to hand13 to latch (X A) into User VIA timer 1 \ and return from the subroutine (this BNE is \ effectively a JMP as X is never zero) .hand11 \ If we get here, then screenSection = 4 LDX #3 \ We now send the 3 palette bytes at paletteSection4 to \ the Video ULA palette in SHEILA &21, so set a loop \ counter in X .hand12 LDA paletteSection4,X \ Set the X-th byte of paletteSection2 to the Video ULA STA VIA+&21 \ palette DEX \ Decrement the loop counter BPL hand12 \ Loop back until we have sent all 16 bytes STX screenSection \ Set screenSection = -1, as the above loop finishes \ with X = 255 JSR AnimateTyres \ Animate the tyres on either side of the screen LDA #&FF \ Set 6522 User VIA T2C-H timer 2 high-order counter STA VIA+&69 \ (SHEILA &69) to &FF to start the T2 counter \ counting down from &FFxx at a rate of 1 MHz LDA #&16 \ Set (X A) = &0B16 to latch into the User VIA timer 1, LDX #&0B \ so on the next timer loop it counts down from &0B16 \ (2838) .hand13 STX VIA+&67 \ Set 6522 User VIA T1L-H and T1L-L to set both timer 1 STA VIA+&66 \ latches (so this sets the timer to (X A) but does not \ start counting until the current timer has run down) INC screenSection \ Increment the screen section counter to move on to the \ next section .hand14 PLA \ Restore X from the stack TAX LDA &FC \ Set A to the interrupt accumulator save register, \ which restores A to the value it had on entering the \ interrupt RTI \ Return from interrupts, so this interrupt is not \ passed on to the next interrupt handler, but instead \ the interrupt terminates here