English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 06 December 2016, 03:44   #1
LuigiThirty
Registered User

 
Join Date: Dec 2016
Location: USA
Posts: 101
Question Infinite vertical scrolling

I'm new to Amiga programming and I'm trying to figure out how to write a simple vertical scrolling engine. I have 4 bitplanes tall enough to contain 2 screens worth of 16x16 tiles.

Every frame I move the bitplane pointers in my copperlist up by 1 scanline. When the window reaches the end of the tilemap I move it back down so the bottom half of the tilemap is visible. But I need to do it in a way that it's invisible to the user.

I think what I need to do is blit the next row of tiles both off the top and the bottom of the visible area so that when I reset the bitplane pointers the screen is still showing the same data, right? But when I did that, I couldn't blit the two rows of tiles before running out of time during the frame. Is there some example code floating around I can look at?
LuigiThirty is offline  
Old 06 December 2016, 10:17   #2
alpine9000
Registered User

 
Join Date: Mar 2016
Location: Australia
Posts: 730
http://aminet.net/package/dev/src/ScrollingTrick

Check this out. Explains most of the commonly used scrolling techniques.
alpine9000 is offline  
Old 06 December 2016, 11:28   #3
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,374
The scrolling trick package on Aminet is great stuff.

Do note that vertical scrolling using the copper-split version of his trick will make getting bobs drawn correctly on the screen harder (and use more CPU time).
roondar is offline  
Old 06 December 2016, 11:42   #4
DanScott
Lemon. / Core Design

DanScott's Avatar
 
Join Date: Mar 2016
Location: Sunny Bournemouth, UK
Posts: 478
Quote:
Originally Posted by LuigiThirty View Post
I'm new to Amiga programming and I'm trying to figure out how to write a simple vertical scrolling engine. I have 4 bitplanes tall enough to contain 2 screens worth of 16x16 tiles.

Every frame I move the bitplane pointers in my copperlist up by 1 scanline. When the window reaches the end of the tilemap I move it back down so the bottom half of the tilemap is visible. But I need to do it in a way that it's invisible to the user.

I think what I need to do is blit the next row of tiles both off the top and the bottom of the visible area so that when I reset the bitplane pointers the screen is still showing the same data, right? But when I did that, I couldn't blit the two rows of tiles before running out of time during the frame. Is there some example code floating around I can look at?
You should be able to blit 2 rows of tiles in a frame quite quickly (A->D blitter copy)
DanScott is offline  
Old 06 December 2016, 11:47   #5
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,374
Quote:
Originally Posted by DanScott View Post
You should be able to blit 2 rows of tiles in a frame quite quickly (A->D blitter copy)
Indeed, which is why I've never been sure if the copper split vertical scrolling method will actually give you enough of a performance boost to bother using it (it will use much less memory though). After all, using that method does require extra code in the blitter setup to test for and potentially split bobs.

At any rate, I'd suggest to the OP that blitting 2 rows of tiles is the best way to start out. Time enough for trying out more complicated routines after that works.
roondar is offline  
Old 06 December 2016, 12:17   #6
sandruzzo
Registered User
 
Join Date: Feb 2011
Location: Italy/Rome
Posts: 1,606
For proxima 3 I'm using 3 screen for it, and I switch pointer when needed.
sandruzzo is offline  
Old 06 December 2016, 13:42   #7
idrougge
Registered User
 
Join Date: Sep 2007
Location: Stockholm
Posts: 3,928
Make your bitmap two screens high. That way you can always blit outside of the visible area, as long as you blit two rows per update with a certain offset.
idrougge is offline  
Old 06 December 2016, 15:08   #8
LuigiThirty
Registered User

 
Join Date: Dec 2016
Location: USA
Posts: 101
Quote:
Originally Posted by DanScott View Post
You should be able to blit 2 rows of tiles in a frame quite quickly (A->D blitter copy)
I'm using the blitter to copy the individual tiles instead of assembling a row in memory and then blotting it which is probably why it's so slow.
LuigiThirty is offline  
Old 06 December 2016, 15:20   #9
DanScott
Lemon. / Core Design

DanScott's Avatar
 
Join Date: Mar 2016
Location: Sunny Bournemouth, UK
Posts: 478
Quote:
Originally Posted by LuigiThirty View Post
I'm using the blitter to copy the individual tiles instead of assembling a row in memory and then blotting it which is probably why it's so slow.
That should be fine... you can blit nearly a whole screen full of tiles in under a frame

Are you coding in 68k asm?
DanScott is offline  
Old 06 December 2016, 15:31   #10
LuigiThirty
Registered User

 
Join Date: Dec 2016
Location: USA
Posts: 101
I'm doing it in C but I'm going to rewrite my blit functions in ASM. I'm new to Amiga but not 68k.

Last edited by LuigiThirty; 06 December 2016 at 16:08.
LuigiThirty is offline  
Old 07 December 2016, 05:56   #11
LuigiThirty
Registered User

 
Join Date: Dec 2016
Location: USA
Posts: 101
I optimized the hell out of my C tile blitting routine before rewriting it in ASM and now I seem to be able to draw them no problem! That and looking at the scrolling trick for reference got me going and now I have a happily wrapping vertical scrolling playfield at 60fps

I think the next step is to, uh, change this to PAL so I can do 320x256@50Hz instead of 320x200@60Hz.
LuigiThirty is offline  
Old 07 December 2016, 11:36   #12
DanScott
Lemon. / Core Design

DanScott's Avatar
 
Join Date: Mar 2016
Location: Sunny Bournemouth, UK
Posts: 478
Quote:
Originally Posted by LuigiThirty View Post
I optimized the hell out of my C tile blitting routine before rewriting it in ASM and now I seem to be able to draw them no problem! That and looking at the scrolling trick for reference got me going and now I have a happily wrapping vertical scrolling playfield at 60fps

I think the next step is to, uh, change this to PAL so I can do 320x256@50Hz instead of 320x200@60Hz.
Nice one!!
DanScott is offline  
Old 07 December 2016, 22:14   #13
LuigiThirty
Registered User

 
Join Date: Dec 2016
Location: USA
Posts: 101
By the way, I'm compiling my program with VBCC, which can output debug info compatible with SAS/C. I tried setting up remote debugging using a serial cable between my PC running WinUAE and my A2000. I can load the program onto the target machine with cprx but when my program writes a new Copperlist, I just get a scrambled picture from a Copper run amok. If I copy the program onto a floppy and run it on the A2000, it's fine. Huh?
LuigiThirty is offline  
Old 09 December 2016, 18:04   #14
LuigiThirty
Registered User

 
Join Date: Dec 2016
Location: USA
Posts: 101
Turns out I was wrong

I think the problem may lie in my frame loop, not my blitter code. I disabled all my bobs and am just rendering tiles now. It shouldn't be stuttering just drawing 20 16x16 tiles! Hmmmmmm. I'm not sure how readable the code is but if you've got any ideas please don't hesitate to share. I'll keep plugging away at it.
LuigiThirty is offline  
Old 10 December 2016, 14:01   #15
phx
Natteravn

phx's Avatar
 
Join Date: Nov 2009
Location: Herford / Germany
Posts: 1,484
I only had a quick look over the source, so just a few notes:
  • Use double buffering. With a single visible bitmap you will easily run into the problems you noticed, with stuttering and tearing effects.
  • Use interleaved bitplanes, so you don't have to start the Blitter five times for each tile, but only once.
  • Optimize your assembly routines. For example: a multiplication in the blit-routine is deadly.
phx is offline  
Old 10 December 2016, 14:13   #16
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,374
Quote:
Originally Posted by LuigiThirty View Post
Turns out I was wrong

I think the problem may lie in my frame loop, not my blitter code. I disabled all my bobs and am just rendering tiles now. It shouldn't be stuttering just drawing 20 16x16 tiles! Hmmmmmm. I'm not sure how readable the code is but if you've got any ideas please don't hesitate to share. I'll keep plugging away at it.
I've checked your code and I do have some tips. However, even with those - this shouldn't really run over a frame (unless the compiler is adding massive overhead somewhere).

With that said, here are my tips:

Your code spends a lot of time blitting tiles when you reach the 16th frame. I did some cycle counting and your blitter routine is close to 650 cycles per call (assuming you are using a 68000 and that I didn't screw up). Now, you have chosen to not use an interleaved screen mode so each tile is 4 blits. And you're blitting 20 tiles in total when you reach the 16th frame. In total you are doing 80 blits.

This is the equivalent of spending ~52.000 CPU cycles in such a frame, just to do tile blitting. There are ~141.000 of them in a PAL frame, so you are spending over a third of a frame just setting up blits.

There are two ways to improve this:
  1. Use an interleaved bitmap. That will lower the amount of blits needed by a factor of four.
  2. You can spread the load over multiple frames - for instance: draw one or two tiles every frame until you reach the 20 you need.

These two can be combined as well.

Other than that you could also try to use 'blitter nasty' mode for blitting tiles, but it really should not be needed in this case as the blits are tiny.

Now, the rest of your code looks simple enough and should really run fairly fast. However, since we don't know which part is running slow, I'd suggest using colour 0 as a 'debug mechanism': set it to a different colour for every part of the loop and reset after you're finished in the loop. This way, you can see which part of the code takes which amount of raster time and focus there.

If I had to guesstimate, I'm thinking it may be overhead around calling your blit or a frame wait routine that somehow doesn't do what you want (although it looks almost exactly like the one I use and that one works).

All things combined - this is a bit of a mystery as I don't see anything that should be running so slow as to make your code drop frames.
roondar is offline  
Old 10 December 2016, 19:07   #17
LuigiThirty
Registered User

 
Join Date: Dec 2016
Location: USA
Posts: 101
Thanks for the analysis! I haven't cycle counted per scanline since I did Atari 2600 programming. It's easier on a 6502 than a 68000!

My A2000 has a 68030 so that's what I have WinUAE set to.

Quote:
You can spread the load over multiple frames - for instance: draw one or two tiles every frame until you reach the 20 you need.
Oh of course, like old NES scrolling where you copied 4 tiles (I think?) per fine scroll until the register overflowed and you did a coarse scroll.

Quote:
If I had to guesstimate, I'm thinking it may be overhead around calling your blit or a frame wait routine that somehow doesn't do what you want (although it looks almost exactly like the one I use and that one works).
Function call overhead is probably contributing to it, I'm not sure what VBCC's calling convention is but inlining the blits would speed it up. I'll also look into the technique for interleaved bitmaps.

Last edited by LuigiThirty; 10 December 2016 at 19:38.
LuigiThirty is offline  
Old 10 December 2016, 22:37   #18
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,374
Quote:
Originally Posted by LuigiThirty View Post
Thanks for the analysis! I haven't cycle counted per scanline since I did Atari 2600 programming. It's easier on a 6502 than a 68000!

My A2000 has a 68030 so that's what I have WinUAE set to.
If you're running on a 68030 there pretty much must be a different problem than one based on code speed. There is no way the code you've shown could be so slow as to overrun a frame. Does the problem show on both real hardware and on the emulator?

Because it is only showing on the emulator you may actually be seeing the result of a difference in frame rate between what the emulator wants to show and what your display is doing. This shows as the odd hickup every now and then as the emulator doubles a frame every now and then to convert between 50 and 60Hz.

Quote:
Oh of course, like old NES scrolling where you copied 4 tiles (I think?) per fine scroll until the register overflowed and you did a coarse scroll.
Yup, but like I said above: a 68030 is way to fast for that to be an actual problem.

Quote:
Function call overhead is probably contributing to it, I'm not sure what VBCC's calling convention is but inlining the blits would speed it up. I'll also look into the technique for interleaved bitmaps.
Interleaved blitting is almost always a better idea (if you can afford the extra memory needed for the masks). However, I'm nearly 100% convinced that you're not seeing a speed problem here, considering the CPU you are using.

Last edited by roondar; 10 December 2016 at 22:39. Reason: spelling
roondar is offline  
Old 11 December 2016, 00:43   #19
LuigiThirty
Registered User

 
Join Date: Dec 2016
Location: USA
Posts: 101
Quote:
Originally Posted by roondar View Post
Because it is only showing on the emulator you may actually be seeing the result of a difference in frame rate between what the emulator wants to show and what your display is doing. This shows as the odd hickup every now and then as the emulator doubles a frame every now and then to convert between 50 and 60Hz.
Well, my emulator and Copper window settings are set for NTSC since I have an NTSC A2000... it could still be something about the refresh rate difference between my monitor and WinUAE. I'll hook up some debugging graphics output and change that MULU for a table lookup and see how it runs on the real machine with a CRT.
LuigiThirty is offline  
Old 11 December 2016, 03:44   #20
roondar
Registered User

 
Join Date: Jul 2015
Location: The Netherlands
Posts: 1,374
I think I understand the problem now. The issue is that your frame loop only updates the copper list after blitting the tiles.

In short: the WFRAME code waits until rasterline 244 (out of 262 for NTSC). The copper list sets the bitplane pointers at rasterline 0 (there is no wait in the copper list prior to the setting of the pointers). This means the code has only a few rasterlines worth of time to set the pointers before the copper will write them.

During frames which blit the tiles, the code probably ends up taking more than the available time between line 244 and line 0, so when it does write the pointers into the copper list, the copper list execution is already past setting them into the display registers. This will result in a stutter.
roondar is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
Smooth vertical scrolling in AMOS idrougge Coders. AMOS 42 24 January 2016 15:37
Horizontal vs vertical scrolling Akira Coders. General 20 26 October 2015 12:15
infinite money in ishar 2 Jacobson support.Games 7 19 April 2012 13:42
[Found: Insanity Fight] Vertical Scrolling Shootemup capehorn Looking for a game name ? 5 13 March 2009 09:18
Vertical scrolling motorcycle game.. Anyone? Thrash75 Looking for a game name ? 11 18 May 2005 20:44

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 17:20.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, vBulletin Solutions Inc.
Page generated in 0.09757 seconds with 13 queries