Scroll 1px problem, need your help

By Metalion

Paragon (1628)

Metalion さんの画像

26-12-2022, 21:13

Hi everyone,

I am making a 1px bidirectional scroll, in a small SCREEN2 window. It's done quite simply by loading a new charset for every 1px move. To do that, I have prepared 8 charsets, each being a 1px right shift of the previous one.

I have some trouble making it work correctly, and I cannot get my head around what's going wrong. It seems to work fine except that it jumps briefly every 8 pixels to an incorrect position.

I load the charset like this:

	ld	a,(x_pos)
	and	7
	jr	z,$+5
	dec	a	; needed because of the
	xor	7	; right shifted charsets
	call	load_charset

Initially, I loaded a new map each time the x_pos reached zero. But that transition actually varies depending on the scroll direction. When going right, a new map is needed between +0 and +7. When going left, it's between +7 and +0. So I bluntly tested loading a new map at each step, but the problem is still there:

- going left: at some point the map jumps left 8 px, then jumps back at the correct position
- going right: at some point the map jumps right 8 px, then jumps back at the correct position

I cannot get my head around this problem.
Could someone point me in the right direction ?
Thanks.

ログイン/登録して投稿

By santiontanon

Paragon (1830)

santiontanon さんの画像

26-12-2022, 21:18

Could it be the time in between copying the new tileset and copying the new name table? there might be a point in between where things do not match?

By PingPong

Enlighted (4155)

PingPong さんの画像

26-12-2022, 22:54

Metalion wrote:

Hi everyone,

I am making a 1px bidirectional scroll, in a small SCREEN2 window. It's done quite simply by loading a new charset for every 1px move. To do that, I have prepared 8 charsets, each being a 1px right shift of the previous one.

I have some trouble making it work correctly, and I cannot get my head around what's going wrong. It seems to work fine except that it jumps briefly every 8 pixels to an incorrect position.

I load the charset like this:

	ld	a,(x_pos)
	and	7
	jr	z,$+5
	dec	a	; needed because of the
	xor	7	; right shifted charsets
	call	load_charset

Initially, I loaded a new map each time the x_pos reached zero. But that transition actually varies depending on the scroll direction. When going right, a new map is needed between +0 and +7. When going left, it's between +7 and +0. So I bluntly tested loading a new map at each step, but the problem is still there:

- going left: at some point the map jumps left 8 px, then jumps back at the correct position
- going right: at some point the map jumps right 8 px, then jumps back at the correct position

I cannot get my head around this problem.
Could someone point me in the right direction ?
Thanks.

Umh, if i understand correctly, you load a new charset at every x_pos change. So with x=0 you load charset 0, x=1 you load charset 1 and so on. Right?
If it's correct i do not understand the dec a , xor 7 instruction.

Is this proposal (not tested) fine for you?

ld a, (x_pos)
and 7            ; get the offset
call load_charset

ld a,(x_pos)
and 7
jr  z, update_name_table ; need to update nametable by taking into account x_pos
ret   ; exit
update_name_table:
; here a is x_pos *8. take into account of this when calculating the address from which load 

the load_charset and update_name_table should happen outside the active area or you see some glitch because the raster beam will catch you . a full nametable update cost you a large part of vblank period so be careful

By Metalion

Paragon (1628)

Metalion さんの画像

27-12-2022, 09:34

PingPong wrote:

Umh, if i understand correctly, you load a new charset at every x_pos change. So with x=0 you load charset 0, x=1 you load charset 1 and so on. Right?
If it's correct i do not understand the dec a , xor 7 instruction.

Yes that's correct.
I load a new charset at every x_pos change.

The dec a, xor 7 instruction is there to reverse the actual result of and 7, because my charsets are right shifted: charset_+1 is charset_+0 shifted 1px to the right, charset_+2 is charset_+1 shifted 1px to the right, ...

Let's say we're starting with x_pos=144, and we're shifting the image 1px to the left:
- x_pos = 145
- (x_pos) and 7 = 1
- shifting image 1px to the left means I need to use the charset_+7, since they are right shifted.
- a=1, dec a, xor 7 will give 7

PingPong wrote:

the load_charset and update_name_table should happen outside the active area or you see some glitch because the raster beam will catch you . a full nametable update cost you a large part of vblank period so be careful

Actually, I only update 135 tiles (and only the patterns), so it costs me around 32000 cycles. Yet, you are right in warning about that, because my scroll window is located at y=16, so it might be the case that the raster beam catches my update. However, it's not the problem I'm facing here, because, going 1px at a time, I can see that the "8px jump" is a static result, not a transitory state.

PingPong wrote:

Is this proposal (not tested) fine for you?

Your proposal is exactly what I do now, except for the dec a, xor 7 bit.

By thegeps

Paragon (1249)

thegeps さんの画像

27-12-2022, 10:49

how many chars in each charset? Isn't possible to have preshifted chars all together in VRAM?

By Metalion

Paragon (1628)

Metalion さんの画像

27-12-2022, 11:04

I think I understand better the problem now.
Here's a representation of my right shifted charsets.

If I'm scrolling left from (x_pos) and 7 = 0, I do need to load the charset_+7 BUT I also need to shift the map 1 char to the left: char B in pos 01 (charset_+0) needs to be replaced by char C (charset_+7). I was shifting the map 1 char ONLY when (x_pos) and 7 = 0.

So it means that:
- scrolling left: I need to shift the map 1 char to the left, when switching from charset_+0 to charset_+7
- scrolling right: I need to shift the map 1 char to the right, when switching from charset_+7 to charset_+0 (that bothers me, because that's what I was doing already ... so it should have been working, at least in this case)

That's annoying, because I do not know the scroll direction when I handle the scroll routine.

thegeps wrote:

how many chars in each charset? Isn't possible to have preshifted chars all together in VRAM?

Each charset is 135 tiles.
I pre-shift them in RAM, and then load the charset at each incrementation.

By thegeps

Paragon (1249)

thegeps さんの画像

27-12-2022, 12:17

so you load 135*8=1080 bytes each frame? or you do it 3 times to cover the whole screen? how big is the portion you need to scroll? (I know, many questions, but I'm curious)

By Metalion

Paragon (1628)

Metalion さんの画像

27-12-2022, 14:33

thegeps wrote:

so you load 135*8=1080 bytes each frame?

Yes, I load 1080 bytes each frame, only for the patterns. The colors stay the same, although there is still some work to do, in order to make sure that each shifted charset has the same colors when they are on screen.

The window where I do the bi-directional scrolling is an enemy radar (much like the one in MG2), so it is in fact a scaled down version (1 pixel = 1 tile) of the game screen. It's only displayed in the first third of the screen, so I'm only updating the first bank.

By thegeps

Paragon (1249)

thegeps さんの画像

27-12-2022, 16:16

You need to perform a char scroll when (x-pos) and 7=0.
So save the last x-pos value and when (x-pos) and 7=0 perform a subtract old x-pos from new x-pos and you know if do that to left or right.
Probably the acrual scroll-to-right is messed because the wrong scroll-to-left