aoineko-fr / MSXgl

The MSX Game Library in C language
119 stars 13 forks source link

smooth scroll code #3

Open aguaviva opened 2 years ago

aguaviva commented 2 years ago

Your lib inspired me to write a smooth scroll code, it is not as fast as I'd like but I thought about sharing it with you in case you are interested

https://pastebin.com/hiFKPSE7

aoineko-fr commented 2 years ago

Hello aguaviva,

Yes, I'm very interested in scrolling systems... I'm actually adding this in MSXgl. At first, I'm focusing on tile by tile scrolling. On MSX2, I will use the VDP registers to make a smooth scrolling. On MSX1, I will have to find more complicated solutions.

I really like your generic approach, but I'm afraid that even in assembler, it will be too slow. However, if we limit it to a part of the screen, it might be viable. Anyway, I'm interested to see how far you will get with this method.

For my part, I'm thinking of exploring pre-computed solutions.

artrag commented 2 years ago

Hi aoineko, I can provide you the best algorithms for horizontal scrolling both for msx 1 and msx2, but their integration in a general purpose framework isn't a easy task. For horizontal scrolling in screen 8, I can point to two sdcc projects: This is for megarom setup https://github.com/artrag/SDCC-msx2-side-scrolling-platform-game and this is for msxdos setup https://github.com/artrag/SDCC-msx-2-scrolling-test

In plain asm I can propose you this in screen 5 (with two-laiers and 8 directions) https://github.com/artrag/Parallax_scrolling_MSX2 and this https://github.com/artrag/Total-Parody-Promo

On msx1, screen 2, I can point to you this (8 directions) https://github.com/artrag/scroll_8_ways and this other (just 2 directions) https://github.com/artrag/Uridium-msx1

aoineko-fr commented 2 years ago

Thanks Artrag, I have almost finished my scrolling module for tile-based screen modes. I will look at how you did it and even if I don't use the code as is, it can still be a source of inspiration.

artrag commented 2 years ago

I've seen the demo, are you using sprites to mask borders? How many do you leave for the game? If you need support for bitmap modes let me know

aoineko-fr commented 2 years ago

Yes. The SCROLL_MASK define control the use of sprites mask to hide tiles appearance on horizontal scrolling (MSX2 only).

In the sample program (32x20 tiles), scrolling take about 60% of a 50 Hz frame (only every 8 frames with a 1 pixel speed) according to border color method. The Scroll_Update() function should be rewrite in assembler for optimization but main part of the time is VRAM copy so I don't expect great improvement.

For bitmap mode scrolling do you use special method or just VDP commands based one?

artrag commented 2 years ago

Mine is a tricky algorithm involving the parallel work of z80 and vdp without recurring to sprites for masking the borders. Moreover be aware that you cannot change R18 while vdp commands are being executed, without causing glitches in the copy.

In a nutshell, this is the general idea: the tile data are stored in ROM/RAM (in pages of a ROM mapper) and plotted by the z80 column by column in the border where the new pixels appear; the z80 is also in charge of blanking the corresponding column of pixels in the opposite border. In the meanwhile, the vdp is in charge of moving a whole slice of 16*176 pixels (or 16x196 according to the mode/time you have). The devil is in the details, but I'm here if you need more info.

artrag commented 2 years ago

Yes. The SCROLL_MASK define control the use of sprites mask to hide tiles appearance on horizontal scrolling (MSX2 only).

In the sample program (32x20 tiles), scrolling take about 60% of a 50 Hz frame (only every 8 frames with a 1 pixel speed) according to border color method. The Scroll_Update() function should be rewrite in assembler for optimization but main part of the time is VRAM copy so I don't expect great improvement.

For bitmap mode scrolling do you use special method or just VDP commands based one?

If you slice the update of the tiles in the PNT in 8 steps (having a double buffer), you can spread the CPU load an all frames, having a max cpu usage of about the 7-8%