.ScrollPlayerView LDY lastPanKeyPressed \ Set Y to the direction of the last pan key that was \ pressed (which may not still be held down) \ \ So this contains the direction of any scrolling that \ we still need to apply, as follows: \ \ * 0 = pan right \ \ * 1 = pan left \ \ * 2 = pan up \ \ * 3 = pan down \ \ We use this as an index into various tables, to look \ up the correct values for the direction in which we \ want to scroll \ We now scroll the screen in the correct direction to \ pan the player's scrolling landscape view \ \ Note that we scroll the screen in the opposite \ direction to the pan direction, so if we are panning \ right we move the screen to the left, for example \ \ The screen address of the player's scrolling landscape \ view is stored in viewScreenAddr(1 0), so this is the \ address of the screen just below the energy icon and \ scanner row \ \ We therefore start the scrolling process by updating \ the screen address in viewScreenAddr(1 0) to point to \ the new address after scrolling \ \ Scrolling is done in individual steps, as follows: \ \ * When scrolling horizontally, we scroll by one \ column that's one character block wide (i.e. one \ byte, two pixels wide) \ \ * When scrolling vertically, we scroll by one row \ that's one character block tall (i.e. eight bytes, \ eight pixels tall) \ \ The amount of change that we need to apply to \ viewScreenAddr(1 0) for each of the four directions is \ given in the tables scrollScreenHi and scrollScreenLo, \ as 16-bit signed values, so we just need to look up \ the correct value and apply it to viewScreenAddr(1 0) \ \ For example, we advance viewScreenAddr(1 0) by eight \ bytes when panning right, as we need to scroll the \ screen to the left, so the start of the screen in \ memory moves on by eight bytes (one character block) \ \ This would scroll the screen to the left by two pixels \ as each character block is two pixels wide \ \ Similarly, we reduce viewScreenAddr(1 0) by 320 bytes \ when panning up, as we need to scroll the screen down, \ so the start of the screen in memory moves on by eight \ bytes (one character row of 40 character blocks with \ eight bytes per character block) \ \ This would scroll the screen to down by eight pixels \ as each character row is eight pixels wide LDA viewScreenAddr \ Apply the change in scrollScreen(Hi Lo) for the CLC \ current pan direction in Y to the screen address of ADC scrollScreenLo,Y \ the player's scrolling landscape, which is stored in STA viewScreenAddr \ viewScreenAddr(1 0) LDA viewScreenAddr+1 \ ADC scrollScreenHi,Y \ We start by calculating this: \ \ (A viewScreenAddr) = viewScreenAddr(1 0) \ + (scrollScreenHi+Y scrollScreenLo+Y) CMP #&80 \ If the high byte in A >= &80 then the new address is BCC scro1 \ past the end of screen memory, so subtract &20 from SBC #&20 \ the high byte so the address wraps around within the \ range of screen memory between &6000 and &8000 \ \ If the high byte is in range, jump to scro1 to check \ the high byte against the start of screen memory JMP scro2 \ Jump to scro2 to skip the next check, as we know it \ doesn't apply .scro1 CMP #&60 \ If the high byte in A < &60 then the new address is BCS scro2 \ before the start of screen memory, so add &20 to the ADC #&20 \ high byte so the address wraps around within the range \ of screen memory between &6000 and &8000 .scro2 STA viewScreenAddr+1 \ Store the high byte of the result, so we now have: \ \ viewScreenAddr(1 0) = viewScreenAddr(1 0) \ + (scrollScreenHi+Y scrollScreenLo+Y) \ \ with the address wrapped around as required \ We now reprogram the 6845 CRTC chip to scroll the \ screen in hardware (so-called "hardware scrolling") \ by setting 6845 registers R12 and R13 to the new \ address for the start of screen memory \ \ The registers actually require the address to be set \ in terms of character rows, so we need to set R12 and \ R12 to the address divided by 8 (see below) JSR GetIconRowAddress \ Set iconRowAddr(1 0) to the address in screen memory \ of the icon and scanner row at the top of the screen \ \ This calculates the address from viewScreenAddr(1 0), \ so the value returned will be the new start of screen \ memory, after the scroll is completed \ \ It also sets A to the high byte of the address of \ screen memory in iconRowAddr(1 0) STA screenAddrHi \ Set (screenAddrHi A) = iconRowAddr(1 0) / 8 LDA iconRowAddr \ LSR screenAddrHi \ So (screenAddrHi A) contains the new address of screen ROR A \ memory, divided by 8, which is suitable for passing to LSR screenAddrHi \ the 6845 CRTC to change the address of screen memory ROR A LSR screenAddrHi ROR A LDX #13 \ Set 6845 register R13 = A, for the low byte STX SHEILA+&00 \ STA SHEILA+&01 \ We do this by writing the register number (13) to \ SHEILA &00, and then the value (A) to SHEILA &01 LDX #12 \ Set 6845 register R12 = &0F, for the high byte STX SHEILA+&00 \ LDA screenAddrHi \ We do this by writing the register number (12) to STA SHEILA+&01 \ SHEILA &00, and then the value (screenAddrHi) to \ SHEILA &01 \ This sets 6845 registers (R12 R13) = (screenAddrHi A) \ to point to the start of screen memory in terms of \ character rows. There are 8 pixel lines in each \ character row, so to get the actual address of the \ start of screen memory, we multiply by 8: \ \ (screenAddrHi A) * 8 \ \ which is iconRowAddr(1 0), as set above \ \ So this whole thing sets the start of screen memory to \ the address of iconRowAddr(1 0), which scrolls the \ screen by the required amount DEC scrollCounter \ Decrement the scroll counter, as we have just scrolled \ the screen by one more step \ We now set viewScreenAddr(1 0) to the new address of \ the start of the player's landscape view, so that's \ the address of the top-left corner of the view, just \ below the energy icon and scanner bar at the top of \ the screen \ \ We now need to set toAddr(1 0) to the address in \ screen memory that we need to update now that the \ screen has been scrolled \ \ Scrolling the screen leads to the following update \ requirements: \ \ * When scrolling the screen to the left, we need to \ update the column on the right \ \ * When scrolling the screen to the right, we need to \ update the column on the left \ \ * When scrolling the screen down, we need to update \ the row along the top \ \ * When scrolling the screen up, we need to update \ the row along the bottom \ \ We want to set toAddr(1 0) to the address of the area \ in screen memory that we need to update, and the \ offset within screen memory of this area for each of \ the four directions is given in the tables at \ updateOffsetHi and updateOffsetLo, as 16-bit signed \ values, so we just need to look up the correct offset \ and apply it to viewScreenAddr(1 0) to get the address \ of the area of screen memory we need to update LDA viewScreenAddr \ Set toAddr(1 0) to the screen address of the player's CLC \ scrolling landscape, plus the offset for the current ADC updateOffsetLo,Y \ pan direction from updateOffset(Hi Lo) STA toAddr \ LDA viewScreenAddr+1 \ We start by calculating this: ADC updateOffsetHi,Y \ \ (A toAddr) = viewScreenAddr(1 0) \ + (updateOffsetHi+Y updateOffsetLo+Y) CMP #&80 \ If the high byte in A >= &80 then the new address is BCC scro3 \ past the end of screen memory, so subtract &20 from SBC #&20 \ the high byte so the address wraps around within the \ range of screen memory between &6000 and &8000 .scro3 STA toAddr+1 \ Store the high byte of the result, so we now have: \ \ toAddr(1 0) = viewScreenAddr(1 0) \ + (updateOffsetHi+Y updateOffsetLo+Y) \ \ with the address wrapped around as required \ By this point we have done the following to implement \ the required screen scrolling: \ \ * Updated viewScreenAddr(1 0) to the new address of \ the player's scrolling landscape \ \ * Updated the 6845 to scroll the screen by changing \ the address of screen memory \ \ * Decremented the counter in scrollCounter \ \ * Set toAddr(1 0) to the address of the area in \ screen memory that we now need to update \ \ We can now fall through into ShowScreenBuffer to copy \ the contents of the screen buffer into the area we \ need to update, so that the scroll reveals the correct \ part of the viewName: ScrollPlayerView [Show more] Type: Subroutine Category: Graphics Summary: Scroll the screen and copy data from the screen buffer into screen memory to implement the player's scrolling landscape viewContext: See this subroutine in context in the source code References: This subroutine is called as follows: * IRQHandler calls ScrollPlayerView
[X]
Subroutine GetIconRowAddress (category: Scanner/energy row)
Calculate the address in screen memory of the icon and scanner row at the top of the screen
[X]
Configuration variable SHEILA = &FE00
Memory-mapped space for accessing internal hardware, such as the video ULA, 6845 CRTC and 6522 VIAs (also known as SHEILA)
[X]
Variable iconRowAddr in workspace Main variable workspace
The screen address of the icon and scanner row along the top of the screen
[X]
Variable lastPanKeyPressed in workspace Zero page
The direction of the last pan key that was pressed (which may not still be held down)
[X]
Variable screenAddrHi in workspace Zero page
The high byte of the screen memory address in the ScrollPlayerView routine
[X]
Label scro1 is local to this routine
[X]
Label scro2 is local to this routine
[X]
Label scro3 is local to this routine
[X]
Variable scrollCounter in workspace Main variable workspace
A counter for the number of columns or rows we still need to scroll in the player's scrolling landscape view when the player pans
[X]
Variable scrollScreenHi (category: Screen buffer)
The amount to change the start of screen memory in order to scroll the player's landscape view through each direction (high byte)
[X]
Variable scrollScreenLo (category: Screen buffer)
The amount to change the start of screen memory in order to scroll the player's landscape view through each direction (low byte)
[X]
Variable updateOffsetHi (category: Screen buffer)
The offset within screen memory for the player's landscape view of the area to update following a scroll (high byte)
[X]
Variable updateOffsetLo (category: Screen buffer)
The offset within screen memory for the player's landscape view of the area to update following a scroll (low byte)
[X]
Variable viewScreenAddr in workspace Main variable workspace
The screen address of the player's scrolling landscape view, which is just below the icon and scanner row at the top of the screen