Jump to content
  • 0
desertfish

scrolling the text screen in asm, how?

Question

Hi, for full-screen scrolling (in text mode) I'm implementing 4 routines in assembler. They're meant to scroll the whole text screen 1 position up, down, left or right.

For the C-64 this is fairly straightforward because the character screen matrix is simply avaiable as a block of memory that you can manipulate directly. But with the VERA this is not the case.

What would be the way to do it on the VERA? Is this best done via an intermediate line buffer of some sorts? For scrolling the screen up 1 line for instance, I think I will do something like this:

        lda  #%00010000
        sta  cx16.VERA_ADDR_H       ; enable auto increment by 1, bank 0.
        lda  #1
        sta  cx16.VERA_ADDR_M       ; start at (0, 1)

-       jsr  _copy_line_to_buffer
        ; now copy the linebuffer back to the line above this one
        dec  cx16.VERA_ADDR_M
        jsr  _copy_buffer_to_line
        ; next line to copy
        inc  cx16.VERA_ADDR_M
        inc  cx16.VERA_ADDR_M
        dec  NUM_LINES_TO_SCROLL
        bne  -

That buffer is required because those copy subroutines make use of the VERA auto increment to first copy one single line of text into the buffer, and the second one copies the line of text in the buffer back to the VERA using the autoincrement.  

Is this reasonable or is there a more optimal way to do it? I feel I am perhaps too focused on using that autoincrement mode

Edited by desertfish

Share this post


Link to post
Share on other sites

14 answers to this question

Recommended Posts

  • 0
34 minutes ago, desertfish said:

Hi, for full-screen scrolling (in text mode) I'm implementing 4 routines in assembler. They're meant to scroll the whole text screen 1 position up, down, left or right.

For the C-64 this is fairly straightforward because the character screen matrix is simply avaiable as a block of memory that you can manipulate directly. But with the VERA this is not the case.

What would be the way to do it on the VERA? Is this best done via an intermediate line buffer of some sorts? For scrolling the screen up 1 line for instance, I think I will do something like this:


        lda  #%00010000
        sta  cx16.VERA_ADDR_H       ; enable auto increment by 1, bank 0.
        lda  #1
        sta  cx16.VERA_ADDR_M       ; start at (0, 1)

-       jsr  _copy_line_to_buffer
        ; now copy the linebuffer back to the line above this one
        dec  cx16.VERA_ADDR_M
        jsr  _copy_buffer_to_line
        ; next line to copy
        inc  cx16.VERA_ADDR_M
        inc  cx16.VERA_ADDR_M
        dec  NUM_LINES_TO_SCROLL
        bne  -

That buffer is required because those copy subroutines make use of the VERA auto increment to first copy one single line of text into the buffer, and the second one copies the line of text in the buffer back to the VERA using the autoincrement.  

Is this reasonable or is there a more optimal way to do it? I feel I am perhaps too focused on using that autoincrement mode

VERA has two data ports, DATA0 and DATA1. You can read and write to either of these ports, and they can be set to different addresses. So copying video memory is a matter of setting one port to your read address and one to your write address, setting the correct Increment value for each, then simply reading and writing n times. 


To set DATA1 to your read address:
Set $9F25 to 1
Set $9F20-$9F21 to your start address 
Set $9F22 bits 4-7 to your desired increment (2 to move data horizontally. 9 to move it vertically)
Set $9F22 bit 3 to 1 when moving text right or down and 0 when moving text up or left.

Then set DATA0 to your write address:
Set $9F25 to 0
Set $9F20-$9F21 to your write address.
Set $9F22 bits 4-7 to your desired increment (2 to move data horizontally. 9 to move it vertically)
Set $9F22 bit 3 to 1 to move the text right or down. 

Then you can just read from 1 and write to 0. 

Why do DATA1 first? I like to leave VERA in the state where DATA0 is active. I'm betting most people won't bother to set ADDRSEL, so there could be cases where something writes to the screen without checking ADDRSEL first and then writes using the wrong register. So always reset ADDRSEL to 0 after setting ADDR1. 

Also, don't forget that the screen buffer is actually 128 columns wide and 64K (256 lines) tall, so you can put a lot of stuff in memory outside of the visible space, then scroll by manipulating the HSCROLL and MAPBASE registers. 

 

 

 

Edited by TomXP411

Share this post


Link to post
Share on other sites
  • 0

A line buffer is just adding overhead. VERA has two data ports specifically for use cases like this. So, you can use for port 0 for reading the next line, and port 1 for writing it to the line above.

Assuming that the text is at the top of VRAM (as it is by default), you can do it with a very simple and fast loop.

stz $9F25 ; set VRAM address 0 to start of second line

stz $9F20

lda #$01

sta $9F21

lda #$10 ; stride of 1 byte

sta $9f22

lda #1

sta $9F25 ; Set VRAM address 1 to start of first line

stz $9F20

stz $9F21

lda #$10 ; stride of 1 byte

sta $9f22

ldx #$00 ; set XY to number of bytes in text field before last line ($3B00, or 15,104 = 128x59x2)

ldy #$3B

copy_loop:

lda $9F23

sta $9F24

dex

cpx #$FF

bne check_end

dey

bra copy_loop

check_end:

cpx #0

bne copy_loop

cpy #0

bne copy_loop

clear_bottom:

ldx #128

clear_loop:

stz $9F24

dex

bne clear_loop

Share this post


Link to post
Share on other sites
  • 0

Awesome guys, thanks a lot!!

8 minutes ago, SlithyMatt said:

128x59x2

Ah yeah, what's up with that 128 bytes with of the text mode memory?   I couldn't find info on that.  I falsely assumed that byte 80*2 would be the first byte of the second line, where in reality, that only starts with 128*2

Share this post


Link to post
Share on other sites
  • 0
1 minute ago, desertfish said:

Ah yeah, what's up with that 128 bytes with of the text mode memory?

VERA doesn't actually support an 80-character wide mode. The default mode is 128x64 character tiles, but the viewable part is only 640x480, so you only see the upper left corner of the tile map at scroll position 0,0. So there are actually 48 hidden characters at the end of every line, and 4 hidden lines past the visible bottom. If you change the scroll position, you can see these parts of the tile map.

Share this post


Link to post
Share on other sites
  • 0
11 minutes ago, desertfish said:

Awesome guys, thanks a lot!!

Ah yeah, what's up with that 128 bytes with of the text mode memory?   I couldn't find info on that.  I falsely assumed that byte 80*2 would be the first byte of the second line, where in reality, that only starts with 128*2

it's because binary numbers... there is no even binary number for decimal 80, and color data is packed with character data. So the simplest way to address a line in VERA is in multiples of 256. 

This also makes it super easy to address a character cell: $9f20 selects the column and $9F21 selects the row. 

 

Edited by TomXP411
  • Thanks 1

Share this post


Link to post
Share on other sites
  • 0

Nice effect,

One question : Would that not be possible to do as well with (H-, V-)Scroll registers of Vera? That should be even massively or better, without CPU overhead.  You would need to insert just one line or one column to the hidden part, and VERA will do the rest for you. That should be much faster than copying data. (very specific to scrolling btw.). You can also put that into an interrupt routine, reakting only on vscync and therefore avoiding the tearing. 

 

Share this post


Link to post
Share on other sites
  • 0

I haven't investigated the scrolling capabilities of VERA yet !  But will do eventually.

The goal for now is that the routines operate the same on the Cx16 as their counterparts were already doing on the C64 🙂  

Also, when scrolling far enough, the screen buffer eventually runs out of space anyway doesn't it?  So when that happens the full buffer contents has to be moved anyway I think?

(For the C64 this happens after soft-scrolling 7 pixels)

Share this post


Link to post
Share on other sites
  • 0

VERA's layers wrap around, and you can scroll for up to 4096 pixels in both directions.

So, if you have a 128×64 tile map (such as for the default 80×60 text layer), after scrolling horizontally beyond (128 - 80) * 8 = 384 pixels, your first column would start appearing on the right side of the screen, and when you reach hscroll of 128 * 8 = 1024, the first column would be back a the left edge of the screen. The same would happen at hscroll values of 2048 and 3072 and by the time you reach 4096, you run out of bits for scroll registers so you're back at the scroll value of 0 🙂.

 

Share this post


Link to post
Share on other sites
  • 0

Exactly, only the numbers are different (64 tiles vertically for 80×60 text mode, which means the tile map repeats every 512 pixels). You may be wondering why scrolling is supported up to 4096 pixels... it's because at the maximum tile map size (256) and maximum tile size (16 px), total size of the layer is 256 * 16 = 4096 pixels.

Share this post


Link to post
Share on other sites
  • 0

But but ... wasnt the VIC Chips already capable of hardware scrolling ? 

BTW: Hardware scrolling on VERA is smooth (one pixel at a time if you want), vs Sofwarescrolling can only do a whole character and looks stuttering. With a proper alignment to the vsync you should have a butter smooth scrolling. One of the games in development here demonstrates it (kind of a jump and run).

Share this post


Link to post
Share on other sites
  • 0

C64's VIC-II chip has 8 pixel horizontal and vertical smooth scrolling in hardware.  Scrolling further than that requires CPU heavy lifting to actually copy the 40x25 character screen matrix in memory and resetting the hardware scroll back to 0 so that the sequence starts again.   Bottom line, every multiple of 8 pixels requires CPU grunt.

(to make matters worse, the 64's cpu is just barely fast enough to scroll a full screen worth of characters and color information like this in 1/60th of a second)

For demoscene effects all sorts of trickery is used to exploit undocumented VIC features. This allows for more extensive hardware scrolling but is applicable only in very limited scenarios. 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...

Important Information

Please review our Terms of Use