Skip to navigation

Revs on the BBC Micro

Screen mode: SetCustomScreen

Name: SetCustomScreen [Show more] Type: Subroutine Category: Screen mode Summary: Switch to 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: * MainDrivingLoop (Part 1 of 5) calls SetCustomScreen

Returns: screenSection screenSection is set to -2, so the interrupt handler at ScreenHandler does not do anything straight away, but leaves the palette mapped to black, so the screen is blank
.SetCustomScreen SEI \ Disable interrupts so we can update the 6845 registers \ First we switch screen mode to the custom screen mode \ used for the race, which is based on mode 5 but is \ shorter at 26 character rows rather than 40 \ \ We do this by first reprogramming registers R0 to R13 \ of the 6845 CRTC chip using the values in the \ screenRegisters table (see the screenRegisters \ variable for details), and then programming register 0 \ of the Video ULA to the same value as standard mode 5 LDX #13 \ We are about to write values into registers R0 to R13 \ so set a register counter in X to count down from 13 \ to 0 .cust1 STX VIA+&00 \ Put register number X into SHEILA &00, so we can now \ set the value of this 6845 register LDA screenRegisters,X \ Set register X to the X-th value of screenRegisters STA VIA+&01 DEX \ Decrement the register counter BPL cust1 \ Loop back until we have set registers R0 to R13 to the \ values in the screenRegisters table DEX \ Set screenSection = -2, as the above loop finishes STX screenSection \ with X = -1 CLI \ Re-enable interrupts LDA #154 \ Call OSBYTE with A = 154 to set register 0 of the LDX #%11000100 \ Video ULA to the value in X, which sets the following, JSR OSBYTE \ reading from bit 7 to bit 0: \ \ %1 = master cursor size = large cursor \ %10 = width of cursor in bytes = 2 \ %0 = 6845 clock rate select = low frequency clock \ %01 = number of characters per line = 20 \ %0 = teletext output select = on-chip serialiser \ %0 = flash colour select = first colour selected \ \ These values are the same as in standard mode 5, and \ this call finishes the switch to our custom screen \ mode 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 7 and adding &10 \ to send &07, &17, &27 ... &E7, &F7 \ \ This maps all four logical colours (the top nibble) to \ &7 EOR 7 (the bottom nibble, EOR 7), which maps them \ to colour 0, or black LDA #&07 \ Set A = &07 as the first byte to send .cust2 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 cust2 \ Loop back until the addition overflows after we send \ &F7 to the ULA SEI \ Disable interrupts so we can update the VIAs LDA IRQ1V \ Store the current address from the IRQ1V vector in STA irq1Address \ irq1Address, so the IRQ handler can jump to it after LDA IRQ1V+1 \ implementing the custom screen mode STA irq1Address+1 LDA #2 \ This instruction appears to have no effect, as we are \ about to overwrite A and the processor flags .cust3 BIT VIA+&4D \ Read the 6522 System VIA interrupt flag register IFR \ (SHEILA &4D), which has bit 1 set if vertical sync \ has occurred on the video system BEQ cust3 \ Loop back to cust3 to keep reading the System VIA \ until the vertical sync occurs LDA #%01000000 \ Set 6522 User VIA auxiliary control register ACR STA VIA+&6B \ (SHEILA &6B) bits 7 and 6 to disable PB7 (which is one \ of the pins on the user port) and set continuous \ interrupts for timer 1 ORA VIA+&4B \ Set 6522 System VIA auxiliary control register ACR STA VIA+&4B \ (SHEILA &6B) bit 6 to set continuous interrupts for \ timer 1 LDA #%11000000 \ Set 6522 User VIA interrupt enable register IER STA VIA+&6E \ (SHEILA &4E) bits 6 and 7 (i.e. enable the Timer1 \ interrupt from the User VIA) STA VIA+&4E \ Set 6522 System VIA interrupt enable register IER \ (SHEILA &4E) bits 6 and 7 (i.e. enable the Timer1 \ interrupt from the System VIA) LDA #&D4 \ Set 6522 User VIA T1C-L timer 1 low-order counter to STA VIA+&64 \ (SHEILA &64) to &D4 (so this sets the low-order \ counter but does not start counting until the \ high-order counter is set) LDA #&11 \ Set 6522 User VIA T1C-H timer 1 high-order counter STA VIA+&65 \ (SHEILA &45) to &11 to start the T1 counter \ counting down from &1164 (4452) at a rate of 1 MHz LDA #&01 \ Set 6522 System VIA T1L-L timer 1 low-order latches STA VIA+&46 \ to &01 (so this sets the low-order counter but does \ not start counting until the high-order counter is \ set) LDA #&3D \ Set 6522 System VIA T1C-H timer 1 high-order counter STA VIA+&45 \ to &3D, to start the T1 counter counting down from \ &3D01 LDA #&1E \ Set 6522 System VIA T1L-L timer 1 low-order latches STA VIA+&46 \ to &1E (so this sets the low-order counter but does \ not start counting until the high-order counter is \ set) STA VIA+&66 \ Set 6522 User VIA T1L-L timer 1 low-order latches \ to &1E (so this sets the low-order counter but does \ not start counting until the high-order counter is \ set) LDA #&4E \ Set 6522 System VIA T1L-H timer 1 high-order latches STA VIA+&47 \ to &4E (so this sets the timer to &4E1E (19998) but \ does not start counting until the current timer has \ run down) STA VIA+&67 \ Set 6522 User VIA T1L-H timer 1 high-order latches \ to &4E (so this sets the timer to &4E1E (19998) but \ does not start counting until the current timer has \ run down) LDA #HI(ScreenHandler) \ Set the IRQ1V vector to ScreenHandler, so the STA IRQ1V+1 \ ScreenHandler routine is now the interrupt handler LDA #LO(ScreenHandler) STA IRQ1V CLI \ Re-enable interrupts RTS \ Return from the subroutine