News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_abalore

1 pixel horizontal hardware scroll without using R3

Started by abalore, 14:44, 28 May 24

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

abalore

Quick experiment of 1 pixel horizontal hardware scroll without using R3

With a single screen buffer

ervin

That's sorcery.
I'm fascinated to know how you did that.
:)

abalore

It uses the 16 colors to create 4 bitplanes, so the graphics are only 2 colors.

BUT with clever design of the background, only 8 colors are needed to achieve the effect (still 2 color background), but you have 8 remaining colors for the foregroung sprites.

abalore

Further experiments testing the concept of 2 color background with 8 color foreground


norecess464

My personal website: https://norecess.cpcscene.net
My current project is Sonic GX, a remake of Sonic the Hedgehog for the awesome Amstrad GX-4000 game console!

lightforce6128

Really exciting! Smooth scrolling, the CPU does not need to do much (and can do other things instead), and - as far as I can see - it is compatible to a wide variety of different screens.

But this 8-color thing, this brought me to thinking for a longer time. Finally I think I have it, but did not find the time to test this with a small program. I will try this later.

By further dividing the color bits, I think it is possible to achieve a 2-color background and an 8-color foreground provided that the scrolling has constant speed and direction. Here are some of my thoughts about this:

Spoiler: ShowHide

  • One bit selects between foreground and background.
  • If foreground is selected, the remaining three bits select one out of eight colors.
  • If background is selected, the second bit selects one out of two background colors.
  • The third bit encodes a set pixel in the background with offset 0.
  • The fourth bit encodes a set pixel in the background with offset 2.

This needs to be combined with a double buffer to create the missing offsets of 1 and 3. Set background pixels with different colors need to have a bit of space in between. This means the two background colors cannot be used freely. Nevertheless, background design can be improved with two colors, and dithering is possible at least from line to line. Applying rasters can help to get even more colors for the background.


andycadley

The problem with overlapping the meaning of the bits like that is you have to do full masked sprites and preserve the background (keeping clean separation let's you cheat with XOR or do simplified AND/OR drawing). 

And the moment you have all that sprite masking you can probably just run with a full 16-colour screen.

abalore

Here is the source code, since I'm not going to go further on this by now:

The BASIC loader is on the disc image I previously posted.

Assembled with WinAPE

Herman

Quote from: abalore on 16:06, 28 May 24It uses the 16 colors to create 4 bitplanes, so the graphics are only 2 colors.

BUT with clever design of the background, only 8 colors are needed to achieve the effect (still 2 color background), but you have 8 remaining colors for the foregroung sprites.

Quote from: andycadley on 08:33, 30 May 24The problem with overlapping the meaning of the bits like that is you have to do full masked sprites and preserve the background (keeping clean separation let's you cheat with XOR or do simplified AND/OR drawing).

And the moment you have all that sprite masking you can probably just run with a full 16-colour screen.

Didn't Nigel "Chuckie Egg" Alderton do something like this in his CPC version of Ghost'n Goblins?

(Including hardware scrolling, although not 1 pixel at a time, but in bigger steps).

I found it fascinating at the time.

abalore

Quote from: Herman on 14:03, 31 May 24
Quote from: abalore on 16:06, 28 May 24It uses the 16 colors to create 4 bitplanes, so the graphics are only 2 colors.

BUT with clever design of the background, only 8 colors are needed to achieve the effect (still 2 color background), but you have 8 remaining colors for the foregroung sprites.

Quote from: andycadley on 08:33, 30 May 24The problem with overlapping the meaning of the bits like that is you have to do full masked sprites and preserve the background (keeping clean separation let's you cheat with XOR or do simplified AND/OR drawing).

And the moment you have all that sprite masking you can probably just run with a full 16-colour screen.

Didn't Nigel "Chuckie Egg" Alderton do something like this in his CPC version of Ghost'n Goblins?

(Including hardware scrolling, although not 1 pixel at a time, but in bigger steps).

I found it fascinating at the time.

As far as I know, Ghosts and Goblins uses R3 scrolling (2 mode 0 pixels at a time)

andycadley

Mission Genocide does something similar with its sprites IIRC, hence the rather limited colours (2 bits for the backgrounds, 2 bits for the foreground). Obviously that's also combined with a hardware vertical scroll.

abalore

I think we are wandering off the point, the purpose of the technique is to do accelerated 1 pixel horizontal scrolling.

The other techniques mentioned are for fast XOR sprite drawing.

Two color only background can be useful in a number of scenarios, like a sports game. The point of the technique is that it uses only 1 screen buffer, so 16K more bytes are available for other stuff.

andycadley

Quote from: abalore on 16:23, 31 May 24I think we are wandering off the point, the purpose of the technique is to do accelerated 1 pixel horizontal scrolling.

The other techniques mentioned are for fast XOR sprite drawing.

Two color only background can be useful in a number of scenarios, like a sports game. The point of the technique is that it uses only 1 screen buffer, so 16K more bytes are available for other stuff.
The point was more that, if you don't follow the way you're segregating the palette because you want more colours, it undermines the entire trick behind it.

lightforce6128

Quote from: lightforce6128 on 06:12, 30 May 24... By further dividing the color bits, I think it is possible to achieve a 2-color background and an 8-color foreground provided that the scrolling has constant speed and direction.

I have to correct this: With this configuration the background allows to use 3 colors (not 2), and the foreground allows to use 11 colors (not only 8, the background colors can be used here as well). By putting some constraints on the background design, even 5 colors can be used for the background, and then only 8 for the foreground.

I also did a short comparison between saving the background for sprites and using XOR:

;; save background, and mask and draw one sprite byte
LD A, (HL) : LD (DE), A
AND A, 123 : OR A, 234 : LD (HL), A  ;; either full masking at sprite borders (6 NOPs)
LD (HL), B                           ;; or writing an often used byte in sprite center (2 NOPs)
INC E : INC L
;; restore background
LDI
;; => this takes 13-17 NOPs per byte


;; XOR one sprite byte, both for drawing and restoring
LD A, (HL)
XOR A, 123  ;; either a rarely used byte mask (2 NOPs)
XOR A, B    ;; or an often used byte mask (1 NOPs)
LD (HL), A
INC L
;; => this takes 13-14 NOPs per byte

So there is a difference, but not as big as I did expect. But unrolling sprite code like this will consume much memory. Storing the sprite data in a more compact way will increase the needed time.

abalore

Quote from: lightforce6128 on 01:44, 11 June 24
Quote from: lightforce6128 on 06:12, 30 May 24... By further dividing the color bits, I think it is possible to achieve a 2-color background and an 8-color foreground provided that the scrolling has constant speed and direction.

I have to correct this: With this configuration the background allows to use 3 colors (not 2), and the foreground allows to use 11 colors (not only 8, the background colors can be used here as well). By putting some constraints on the background design, even 5 colors can be used for the background, and then only 8 for the foreground.

I also did a short comparison between saving the background for sprites and using XOR:

;; save background, and mask and draw one sprite byte
LD A, (HL) : LD (DE), A
AND A, 123 : OR A, 234 : LD (HL), A  ;; either full masking at sprite borders (6 NOPs)
LD (HL), B                           ;; or writing an often used byte in sprite center (2 NOPs)
INC E : INC L
;; restore background
LDI
;; => this takes 13-17 NOPs per byte


;; XOR one sprite byte, both for drawing and restoring
LD A, (HL)
XOR A, 123  ;; either a rarely used byte mask (2 NOPs)
XOR A, B    ;; or an often used byte mask (1 NOPs)
LD (HL), A
INC L
;; => this takes 13-14 NOPs per byte

So there is a difference, but not as big as I did expect. But unrolling sprite code like this will consume much memory. Storing the sprite data in a more compact way will increase the needed time.

Good investigation! I usually don't aim to compact stuff since my target at this moment is cartridge games where there is plenty of room available.

andycadley

Yeah, not surprised that with "compiled" sprites most of the cost for proper masking is removed. Like you say, if you store the sprites in a more compact format and do masking on the fly, it probably gets more expensive quickly and then the XOR routine gets better.

You also have to be a little careful with restoring the background when you do it that way as the order of overlapped sprites starts to matter. You can avoid it somewhat by storing the XOR of the background and sprite instead, but it again adds potential cost. If you have a lot of sprites, just storing a "clean" background buffer can end up being the cheaper option.

abalore

Yes, my way to proceed in cartridge games is compiled sprites and clean background buffer (as in Alcon)

Powered by SMFPacks Menu Editor Mod