News:

Printed Amstrad Addict magazine announced, check it out here!

Main Menu
avatar_ivarf

Uridium on the CPC with hardwarescrolling

Started by ivarf, 14:33, 21 May 14

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

arnoldemu

#25
I took a look at the scrolling code in Mission Genocide. They patch the firmware's interrupt handler, so that at the end it calls their functions. So in a way it's using the firmware!

I will clean up the code and present it in a way that is more easy to understand and including commenting.

Identical scroll code is used in warhawk.

Screen is 32 chars wide, 28 chars tall (scroll part), has a panel at the bottom which is 4 chars tall I think (will check). So they avoid the problem area. Rupture technique is used for smoother vertical scroll (using CRTC R5). It's single buffered too.

I can't tell but the sprite routines may be the same too. I didn't really check that.

It is interesting to see that Firebird titles seem to use rupture technique more than other companies.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

AMSDOS

Quote from: Carnivac on 15:45, 27 May 14
But there's hardly any detail to begin with.  And it uses a dither pattern the same size as Mode 0 pixels to pretend there's another shade of blue on those large ships too.


Yes you'll have to excuse the riddles I write.  ???
* Using the old Amstrad Languages :D   * with the Firmware :P
* I also like to problem solve code in BASIC :)   * And type-in Type-Ins! :D

Home Computing Weekly Programs
Popular Computing Weekly Programs
Your Computer Programs
Updated Other Program Links on Profile Page (Update April 16/15 phew!)
Programs for Turbo Pascal 3

arnoldemu

attaching latest doc and mission genocide scrolling (cleaned up and commented).

Found more interesting stuff (mission genocide appears to blank out the lines at the top of the screen that would normally cause flickering - I can see sprites going over these lines ; ) - flicker removal part is no in the example code.

Also, I know why it's best to have the panel at the bottom (described in doc).
The setup mission genocide uses is probably one of the best for a vertical scroller.

I will continue on my journey into cpc hardware scrolling and I will write more example code to show things working.


@Gryzor: I will update the wiki when you have updated it. don't worry about updating with this doc.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

So from investigations so far. If you're doing continuous vertical scrolling and only in one direction (e.g. a vertical scrolling shoot em up). I would highly recommend the mission genocide scroll.

The benefits:
- 32 char wide screen (64 bytes wide). Meaning you can using INC L to move to the next byte to the right. This means faster sprite plotting even with masked sprites; don't need to use the rotovision/bitplane sprite method.
- Problem area is always on the right (simplifies sprite plotting)
- scrolling is pixel by pixel smooth vertically (because of R5)
- works with all CRTC and all monitors/televisions
- if you need to hide the flicker at the top it is easy and simple to do so (I will explain why in another update).
- the screen area is a good size. Your player is at the bottom and you have plenty of time to see enemies approaching.
- the panel is a fair size without being too big

If you want to double buffer it I would put it at &8000-&bfff. This opens up the use of the extra ram being paged into &4000-&7fff (or asic sprite ram if you want).

It's a good solution.


My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

Just out of interest, does anyone have the c64 sprites as a bmp/tga/gif, perhaps the tiles as a gif and a tilemap using them??? Just wondered. I could drop them into one of my scrolling tests just to see how it would look.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

TMR

Quote from: arnoldemu on 09:32, 29 May 14
Just out of interest, does anyone have the c64 sprites as a bmp/tga/gif, perhaps the tiles as a gif and a tilemap using them??? Just wondered. I could drop them into one of my scrolling tests just to see how it would look.

It doesn't have the original tiles/maps but Subchrist Software's Char Pad comes with all of the Uridium and Uridium Plus levels redone with the correct characters and 1x1 character tiles. Download version 1.8 (Revision 3), open the program and look in the Examples folder. (If memory serves, they were originally 3x3 character tiles but it's been a very long time since i looked! =-)

TMR

Here's the in-game sprites from Uridium (there are a few extra details here and there in the Uridium Plus sprites but the Manta and enemies remain the same by the look of things). The second explosion is the player's and, since there's nothing else on the screen, it changes out the colours for it.

[attach=2]

(The inline version looks a bit blurry, click for clean image. =-)

arnoldemu

I will see if I can update my examples to use the tiles and the sprites.

But I don't intend to make a new version of Uridium.

My current investigations are concerning panels/status areas.

I am looking at both where the panel is within the hardware scrolling screen (and therefore must be redrawn when screen is scrolled), and panels made with rupture. I am working out where the best position for a panel may be on a horizontal scroller, a vertical scroller, and a scroll in all directions.

When I say best I mean best in terms of cpu power to set it up and maintain it.

I am sure that each type of scroll lends itself to a panel in a different place.


I will also look at overscan scrolling, including TFM's "crossfire".
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

sigh

#33
That's a nice and throrough document on scrolling. The status panel having to be updated seems like a pain, so having the the gameplay area separate from the panel is a good idea.

Are you going to update the document in regards to the "Commando" scrolling and on how that works with panels? Also the benefits and pitfalls of this method?


Also:

"NOTE: Doing this will give the illusion we are scrolling at the rate of 1 byte horizontally, however
the left and right edges of the display will flicker.
"


What happen if you were to draw black tiles over these edges? So it would have a sort of black border on either side of the screen although this would make the play area smaller by 2 tiles?

EDIT: Just re-read your other post:

"Found more interesting stuff (mission genocide appears to blank out the lines at the top of the screen that would normally cause flickering - I can see sprites going over these lines ; ) - flicker removal part is no in the example code"

Would this work for horizontal?

arnoldemu

#34
Quote from: sigh on 11:18, 30 May 14
That's a nice and throrough document on scrolling. The status panel having to be updated seems like a pain, so having the the gameplay area separate from the panel is a good idea.
true, but doing the rupture technique is quite hard to get right and technical. But once you've got code that works, generally you can re-use it.

Quote from: sigh on 11:18, 30 May 14
Are you going to update the document in regards to the "Commando" scrolling and on how that works with panels? Also the benefits and pitfalls of this method?
commando doesn't use hardware scroll, but I can certainly describe what it's doing.

The document was initially meant to be how to use and implement hardware scrolling.

Quote from: sigh on 11:18, 30 May 14
Also:

"NOTE: Doing this will give the illusion we are scrolling at the rate of 1 byte horizontally, however
the left and right edges of the display will flicker.
"


What happen if you were to draw black tiles over these edges? So it would have a sort of black border on either side of the screen although this would make the play area smaller by 2 tiles?

EDIT: Just re-read your other post:

"Found more interesting stuff (mission genocide appears to blank out the lines at the top of the screen that would normally cause flickering - I can see sprites going over these lines ; ) - flicker removal part is no in the example code"

Would this work for horizontal?
Yes it could, but the problem is that when you do the scroll, the bit you blanked out moves into the main area and you have to then re-draw it.

for mission genocide, it scrolls in one direction. the blanked out bit disapears from the top and new scroll comes in at the bottom. So you can safely redraw the lines without having to restore anything you previously scrolled.

Plus, it only really works so well because the panel is at the bottom and because of the way the rupture works you don't need to blank the bottom. It works perfectly in this case.

if you scrolled vertically and had to blank both top and bottom you have the same issue.

e.g. if you have just blanked top and bottom, if you scroll down the blanked area now scrolls into the main area. You have to redraw the tiles here to restore it THEN redraw the blanked part.

It all depends on how much CPU time you have to spare.

I don't know of any hardware way (on CPC) to blank it, all methods so far are cpu based.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

commando is interesting. single buffered and not much flicker (except on some later levels but that may be how they are drawing the sprites). small screen for drawing sprites faster.

the background is a single colour. sprites appear to be drawn using masking, but it does appear to XOR when you move over the background..

the bits in the background are kind of like sprites. When scrolling is done ONLY these bits are moved, the remainder of the background is not moved. So your effectively scrolling a lot less than if you had scrolled the entire screen.

If i turn off erasing of sprites, I can clearly see trails left around on the screen and when the scroll then moves, some of the trails remain on the screen and only those where the bits of scenery are moving into are cleared.

think of it as moving the sprite down then drawing a blank line of background behind it to stop it leaving a trail.

But the code is quite complex, so there is more going on than I've looked at so far.


My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Axelay

Quote from: arnoldemu on 13:04, 30 May 14
Yes it could, but the problem is that when you do the scroll, the bit you blanked out moves into the main area and you have to then re-draw it.

I'm not sure why you would need to re-draw anything with the R3 horizontal scroll?  You should hopefully be able to arrange your tile data in such a way you can write only the new byte column you need to display, and you only need to blank one column of bytes.  The trailing edge of the screen when the screen is in one position, and the leading edge in the other. 
Quote from: arnoldemu on 13:04, 30 May 14
for mission genocide, it scrolls in one direction. the blanked out bit disapears from the top and new scroll comes in at the bottom. So you can safely redraw the lines without having to restore anything you previously scrolled.

Plus, it only really works so well because the panel is at the bottom and because of the way the rupture works you don't need to blank the bottom. It works perfectly in this case.

if you scrolled vertically and had to blank both top and bottom you have the same issue.

e.g. if you have just blanked top and bottom, if you scroll down the blanked area now scrolls into the main area. You have to redraw the tiles here to restore it THEN redraw the blanked part.

It all depends on how much CPU time you have to spare.

I don't know of any hardware way (on CPC) to blank it, all methods so far are cpu based.


One option in the case of a vertical scroll for blanking the top is to extend the first interrupt down to the lowest point the top of the screen reaches and have the mode set to 2 so you only need set colour 1 to be the same as background at the beginning of the interrupt, or colour 0 & 1 if the background and border are different.  Then set mode and colours as required at the end of the interrupt.  As long as you can find some useful fixed time process to do in that interupt, maintaining a steady screen top will cost very little cpu time and you can write your tiles how you like.

arnoldemu

#37
Quote from: Axelay on 16:05, 30 May 14


I'm not sure why you would need to re-draw anything with the R3 horizontal scroll?  You should hopefully be able to arrange your tile data in such a way you can write only the new byte column you need to display, and you only need to blank one column of bytes.  The trailing edge of the screen when the screen is in one position, and the leading edge in the other. 
So to blank either side involves chars which are side by side.

Here is a diagram: B is on left, C is on right, A is also on right.

      A
B    C

After we get

AB 
C

A had the line masked on the right, it now moves to the left and we draw over it anyway to update the scroll and apply the mask.

What happens with B? It had the mask for the last frame.. We need to redraw it or partially redraw it.
C moves to next line and gets overwritten when we draw the column.

Or... am I missing something?


Quote from: Axelay on 16:05, 30 May 14
One option in the case of a vertical scroll for blanking the top is to extend the first interrupt down to the lowest point the top of the screen reaches and have the mode set to 2 so you only need set colour 1 to be the same as background at the beginning of the interrupt, or colour 0 & 1 if the background and border are different.  Then set mode and colours as required at the end of the interrupt.  As long as you can find some useful fixed time process to do in that interupt, maintaining a steady screen top will cost very little cpu time and you can write your tiles how you like.
True. Can I write that in my document? I will give you credit.

Another method I was thinking of was to set R1=0 for a few lines. That should force border and allow you to enable it again. It should work.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Executioner

#38
Quote from: arnoldemu on 17:37, 30 May 14
Another method I was thinking of was to set R1=0 for a few lines. That should force border and allow you to enable it again. It should work.

R1=0 doesn't work very well with CRTC type 0. (Oops, sorry, it's R6=0 that doesn't work with CRTC type 0, leaves a line of - - - - - - - - - - - at the top of the screen).

Axelay

Quote from: arnoldemu on 17:37, 30 May 14
So to blank either side involves chars which are side by side.

Here is a diagram: B is on left, C is on right, A is also on right.

      A
B    C
Hmm, just realised I was thinking of a fixed pixel scroll as I've been using, but I think the same principle should apply even to a byte step push scroll.  So if the display in your diagram above is about to have the offset changed so the screen moves left by one character, then the diagram above should have R3 set so the screen is 'to the left'.  The left half of B will haven been masked to prevent flicker, but the rightmost part of A & C do not need to have been masked.


Quote from: arnoldemu on 17:37, 30 May 14
After we get

AB 
C

A had the line masked on the right, it now moves to the left and we draw over it anyway to update the scroll and apply the mask.

What happens with B? It had the mask for the last frame.. We need to redraw it or partially redraw it.
C moves to next line and gets overwritten when we draw the column.
Then the offset in the next diagram has changed to move the screen left by one character, so to make the shift appear to be only half a character, the R3 register is set so the screen moves half a char to the right.  A & C are already intact, the left byte column that has B in it gets a new tile, the right column gets blanked.  The new left most character on the display would not need to be blanked at all.  Then in the next frame moving left, you would only set R3 to shift the screen left, not change the base address offset, and you then write the right part of the tile in the right column of B, and blank the left byte column on the left side of the display.



Not sure if I'm the one missing something, but it 'should', I think, just be a matter of blanking whichever byte column 'sticks out', so if you have a standard display width of 40 characters, you'll be maintaining a 39.5 character wide screen.  Though you dont even need to have the blanking column and new tile column adjacent so you can have a display that's a whole number of characters wide if that works better visually.
Quote from: arnoldemu on 17:37, 30 May 14
True. Can I write that in my document? I will give you credit.

Sure.
Quote from: arnoldemu on 17:37, 30 May 14

Another method I was thinking of was to set R1=0 for a few lines. That should force border and allow you to enable it again. It should work.
Well if that works that's two different ways in 'hardware' then.  ;)

Puresox



Are you going to update the document in regards to the "Commando" scrolling and on how that works with panels? Also the benefits and pitfalls of this method?

Just in relation to 'Commando' It would be nice to see a reboot of this to make it better than the new C64 version. Always was pretty impressed with this game on the CPC, the graphics were a bit lame in some places, but the game played really well. And had plenty of levels , where the original C64 only had 3.
This is only a bit of rhetoric , cos I know it is of topic .

arnoldemu

#41
I have attached the correct cleaned up source.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

I looked at ways of blanking the flicker - vertical scrolling only here.

Axelay's method works fine.
You can also use R8 to turn on the border and re-enable the display again but this is limited to CRTC type 0,3 and 4.

You can use R6=0 and back to correct height for CRTC type 1.

Leaving poor CRTC type 2 :(

I tried to use R1=0, but that doesn't work for the vertical scroll, it causes the graphics to jump. I thought it may do this, so it may not be useful at all.


For all of these I was trying to find a way to rely on interrupts to find a good starting position, then burn a small amount of time before re-enabling. The Mission Genocide scroll doesn't have interrupts in a good place. It looks like it could end up burning too many cycles doing it this way, will find out.

You can't use these methods to blank the flicker if you are using R5 without rupture. Interrupts move when you change r5 because they are synced with vsync and vsync also moves.

My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Executioner

Quote from: arnoldemu on 17:53, 04 June 14
Interrupts move when you change r5 because they are synced with vsync and vsync also moves.

Yes, but they will always happen in the same vertical position on the screen unless you're resetting R52 at any time. This means you can set MODE 2, Ink 0,1=Border and then wait a fixed amount of interrupts/time before resetting the inks and MODE.

arnoldemu

Quote from: Executioner on 02:34, 05 June 14
Yes, but they will always happen in the same vertical position on the screen unless you're resetting R52 at any time. This means you can set MODE 2, Ink 0,1=Border and then wait a fixed amount of interrupts/time before resetting the inks and MODE.
No, I don't think so. But I will check.

Here I talk of R5 without rupture where you are adding lines to the display, just as Legend of Kage does.
If you use R5 with rupture the interrupt position doesn't change.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Executioner

Quote from: arnoldemu on 09:20, 05 June 14
Here I talk of R5 without rupture where you are adding lines to the display, just as Legend of Kage does.
If you use R5 with rupture the interrupt position doesn't change.

I don't understand. The frame flyback interrupt will always occur 2 scan lines after the VSYNC, and the monitor will start displaying lines about 30 scan lines after the VSYNC signal, so the first interrupt down the monitor display will always be about 22 scan lines down the monitor (your screen data position could be completely different) unless R52 gets reset, no matter what your CRTC settings are.

arnoldemu

Quote from: Executioner on 00:23, 06 June 14
I don't understand. The frame flyback interrupt will always occur 2 scan lines after the VSYNC, and the monitor will start displaying lines about 30 scan lines after the VSYNC signal, so the first interrupt down the monitor display will always be about 22 scan lines down the monitor (your screen data position could be completely different) unless R52 gets reset, no matter what your CRTC settings are.

Legend of Kage performs smoother vertical scroll by using r5 to add lines to the display. It doesn't attempt to compensate for them like mission genocide does and it doesn't use rupture.

So it is adding between 1 and 7 lines to the display and making the frame longer.

This will cause VSYNC position to shift by 1-7 lines. This also means all interrupts should move by 1-7 lines.

So this means the interrupts are not in the same position for every frame, so you can't for instance use exact interrupts to hide the flicker using say R8 because that too would move, and to hide it properly you need the interrupts to be in the same positions every frame.

I will make a demo program that demonstrates it.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

In this post I have attached some examples:

pushscrl.dsk and pushscrl.asm
pushscr2.dsk and pushscr2.asm

pushscrl.dsk shows an example of scrolling. In this example you can't scroll vertically and horizontally at the same time.
Bad if you want to move diagonally.

When you get to the side of the screen the scroll quickly moves the screen and the sprite moves too.  The action is blocked while the scroll is active. This makes it hard to play.

Advantages I can see:
1. you don't need to draw/erase sprites while scrolling
2. scrolling only up/down or left/right is more simple to update the scroll and takes less time. scrolling diagonally requires you to draw more pixels.
3. sprite can move higher resolution than the scroll. e.g. pixel by pixel.
4. More simple to code.

Disadvantages:
1. really bad if you scroll right then scroll back left again and really interrupts play
2. scrolling diagonal is vertical then horizontal!

pushscr2.dsk shows another example

In this example the scroll continues to move while you move in that direction. The sprite doesn't move back. Like the first there is a region in the middle of the screen when the scroll doesn't happen.

Advantages:
1. smoother than the 1st
2. sprites/action updates while scrolling

Disadvantages:
1. a bit slower than 1st because you must erase/redraw sprites.
2. In a game like a beat em up or where new action is coming onto the screen you need a smaller "no-scroll" area so that you don't move into enemies too early.

My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

Another example:

This scrolling is like Turrican's.

* Player always stays in centre of screen (it can be any position really e.g. bottom in the middle)
* Scrolling is at the hardware scroll rate (or smoother if you use R5/R3).
* Scrolling in diagonals, horizontal or vertical.
* When you get to the edge of the scroll area, scrolling stops and sprite moves up to the side of the screen. When you return to the scroll trigger point scrolling starts again. (This can also be used in the other methods but their code doesn't show that).

With this scroll you need to carefully position the player character so that you have good screen space to react. In Turrican it's the middle. On-line there is a video of Galivan for arcade and it's the bottom in the middle. On other games it may be bottom-left.

NOTE: All scrolling examples could be adapted for software scroll.

For each however, I will go back and explain the advantages and disadvantages of each.

All scrollings could be considered push, because you make the movement to make the screen scroll.

A scroll like this is probably best in a shoot em up. A scroll where you have a region where no scroll happens is best in a beat em up.

My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

arnoldemu

Ghosts and goblins uses a scroll that is like pushscrl.dsk example but the player moves with the scroll.

There are some Amstrad games where you trigger the scroll and it ultimately moves a chunk of screen but it continues to scroll after you have triggered it and stopped, so that after the scroll you are almost centred in the display.

I will try and make an example of this.
My games. My Games
My website with coding examples: Unofficial Amstrad WWW Resource

Powered by SMFPacks Menu Editor Mod