Skip to navigation

Lander on the Acorn Archimedes

Drawing the screen: SwitchScreenBank

Name: SwitchScreenBank [Show more] Type: Subroutine Category: Drawing the screen Summary: Switch screen banks and clear the newly hidden screen bank to black Deep dive: Screen memory in the Archimedes
Context: See this subroutine in context in the source code References: This subroutine is called as follows: * Entry calls SwitchScreenBank * LoseLife calls SwitchScreenBank * MainLoop calls SwitchScreenBank
.SwitchScreenBank LDRB R0, screenBankNumber \ Flip the current screen bank number in EORS R0, R0, #1 \ screenBankNumber between bank 0 and bank 1 STRB R0, screenBankNumber \ which means: \ \ * 0 = draw bank 1, show bank 2 \ \ * 1 = draw bank 2, show bank 1 LDRNE R1, screenBank2Addr \ Set screenAddr as follows: LDREQ R1, screenBank1Addr \ STR R1, screenAddr \ * If screenBankNumber = 0, set it to the \ address of bank 2 in screenBank2Addr \ \ * If screenBankNumber = 1, set it to the \ address of bank 1 in screenBank1Addr \ \ So screenAddr points to the screen that is \ no longer being shown, i.e. the bank that \ we should now draw into TEQ R0, #0 \ Set R1 = screenBankNumber + 1 MOVEQ R1, #1 \ MOVNE R1, #2 \ So this sets R1 as follows: \ \ * If screenBankNumber = 0, R1 = 1 \ \ * If screenBankNumber = 1, R1 = 2 \ \ So R1 is the number of the opposite bank \ to the one in screenAddr, i.e. the bank \ that we should now show on-screen MOV R0, #113 \ Set the display hardware to display the SWI OS_Byte \ screen bank in R1, so the correct bank is \ shown on-screen \ \ This call returns the old bank number in \ R1, so R1 now contains the number of the \ screen bank that is not being displayed MOV R0, #112 \ Set the VDU driver screen bank to the bank SWI OS_Byte \ number in R1, so this directs VDU calls \ (such as the text routines that update the \ score bar) so they update the hidden \ screen bank MOV R0, #19 \ Wait for the vertical sync SWI OS_Byte \ We now clear the screen bank that isn't \ being shown, i.e. the bank at screenAddr STMFD R13!, {R9, R11-R12, R14} \ Store the registers that we want to use on \ the stack so they can be preserved MOV R0, #0 \ Set R0 to R9 to zero so we can use them to MOV R1, #0 \ clear the screen bank to black (as black MOV R2, #0 \ is represented by zero in screen memory) MOV R3, #0 MOV R4, #0 MOV R5, #0 MOV R6, #0 MOV R7, #0 MOV R8, #0 MOV R9, #0 LDR R11, screenAddr \ Set R11 = screenAddr \ \ So R11 contains the address of the screen \ bank we want to clear, pointing just below \ the two lines of text at the top of the \ screen ADD R12, R11, #&12C00 \ Set R12 = screenAddr + 320 * 240 \ \ So R12 points to the end of screen memory \ for the bank at screenAddr, as the address \ in R11 skips the first 16 pixel rows of \ the 320 * 256 screen \ We now zero screen memory from R12 down to \ R11, which clears the screen bank that we \ are no longer showing on-screen .bank1 STMDB R12!, {R0-R9} \ Zero 40 x 32-bit words of screen memory, STMDB R12!, {R0-R9} \ decreasing the address in R12 as we go STMDB R12!, {R0-R9} STMDB R12!, {R0-R9} CMP R12, R11 \ If R12 hasn't yet reached the start of the BNE bank1 \ bank's screen memory in R11, loop back to \ keep zeroing screen memory until it is all \ cleared to black, leaving just the two \ lines of text at the top LDMFD R13!, {R9, R11-R12, PC} \ Retrieve the registers that we stored on \ the stack and return from the subroutine