It is currently Mon Oct 20, 2014 3:56 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 38 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Clowning around
PostPosted: Sat May 29, 2010 12:35 am 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
To break the silence, I'm in need of a spot of advice...

Back in the Eighties and inspired by Kevin Edwards' games programming series in TMU, I started a project to produce a version of Exidy's Circus arcader for the Beeb. I never actually got very far and at that time wasn't confident enough to go all-assembler so I was jumping in and out of Basic depending on what would suffice. I think I only managed to get about four balloons moving with a crude bouncing clown and eventually decided that hardware was more my thing 8-)

In recent times I've been following all the excellent discussions on RS and armed with this new and inspiring knowledge, I decided a little while ago to rekindle the project. I only had some yellowed paper listings and some design notes from my first attempt so I had no choice but to start from scratch but now with a few years programming skills behind me (mostly low-level) this was probably no bad thing. I originally got hooked on Exidy's game through a chance encounter with a cabinet in a hotel foyer although looking at it now (e.g.) I'm not sure why - maybe it was because I knew it was built on 6502 based hardware :D. The original Exidy game is pretty basic so I've added some new gameplay ideas and features but it's still a just a straightforward arcader so don't get too excited!

Anyway, I've pretty much got the basic game engine together and in fact I have several versions which contain permutations of all the game’s features which I just need to bring together into something that constitutes the full game. I did drop hints to Dave about this ‘hardware control project;) a long time ago but I didn't want to do a running development on here because I worry that people will have got bored with the game before it makes it to release! Therefore, I don't plan to drop any playable demos along the way, just the final game when it’s finished. However, because I want a spot of expert input, I've made a very short video of the core game theme (without any of my ‘new-to-Circus’ features) so that any questions I have will (might) make sense. Note that the demo build is deliberately sparse and does not include the backdrop, side-jumps, score, lives etc. etc.

The first and most important question then is, as usual, concerning flicker. I am using the standard (but unadjusted) vsync interrupt method but due to the main ‘action’, i.e. the balloons, being in the top third or so of the screen, this method isn’t really appropriate and I think I need to use the timer delay method to have an interrupt just below the blue balloon row? I would then hopefully be able to move the balloons first and before the scan comes round again.

Am I right in that assumption and if so, how do I do it? I have looked at Rich’s description elsewhere on here but can’t quite get my head around how I actually implement it and I don’t quite get what actually does what. For example, does the vsync interrupt then just set the timer and do nothing else? A kind of layman’s explanation in relation to this game but coupled to Rich’s framework code would be very helpful. Rich…? ;)

To help the clever people come up with the best anti-flicker method for this game, I have also included three screen shots which show the vsync code time usage by the temporary addition of Rich’s famous colour changer at the start and end of the IRQ code. The three shots show the decreasing processing needed as the ballons are burst. There’s also a static screenshot without said coloured timer to show the basic layout of the screen.

Any thoughts, comments, criticisms, advice etc. welcome

(Apologies in advance – I’m at a wedding tomorrow and then away for a week from Monday so if by any chance I don’t get chance to respond to any suggestions or questions in the short term, thanks very much and I promise I will be back!)

The video is here and the screenshots are below...
Attachment:
clowns screenshot.JPG [9.08 KiB]
Downloaded 614 times
Attachment:
clowns vsync time 1.jpg [5.62 KiB]
Downloaded 614 times
Attachment:
clowns vsync time 2.jpg [2.34 KiB]
Downloaded 614 times
Attachment:
clowns vsync time 3.jpg [2.12 KiB]
Downloaded 614 times


Top
 
 Post subject: Re: Clowning around
PostPosted: Sat May 29, 2010 10:11 am 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 7:02 pm
Posts: 273
Looking good Martin!

Re : vsync timer - yes that seems to be the best idea. Essentially you do just use the vsync interrupt to start the new timer. You can get away with a one-shot timer so User VIA timer 2 is probably the best bet.

To start with it's probably best to just set the timer at the start of your vsync routine then just change the background colour in the timer routine - so you can fine-tune it. Once that's working then you can move the rest of your routines from vsync to the timer and hopefully it should work!


Top
 
 Post subject: Re: Clowning around
PostPosted: Sat May 29, 2010 10:53 am 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
Ah brilliant, cheers Tom. Yes, that's the idea I was looking for in setting it up - I had a play but just got in a mess so that will allow me to migrate in easy stages. Nice one :D

Does the User VIA 2 timer use a different vector? I can look it up but you'll know ;) Actually, the balloon rows are on a cyclic scheduled update (only one row per interrupt) so I guess I could actually have three timer values, one for just under each of the rows and selecting the appropriate value by checking the row schedule. That would perhaps always be the most efficient because there are 'other' things that move around not shown in the demo.

Regarding the 'other' sprites and the airborne clown, I suppose I'd have to look at their Y co-ord to determine the best order to update them? Is that like the Y-sorting that people refer to?


Top
 
 Post subject: Re: Clowning around
PostPosted: Sat May 29, 2010 11:57 am 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 7:02 pm
Posts: 273
User VIA timer 2 is still on IRQ1V, yes - you could use IRQ2V (as the OS doesn't handle it) but then you get loads of latency. You could also use different timings for the different balloon rows but I'm not sure there'd be much difference.

What method you use for the other sprites depends on what the flicker's like after this! Y-sorting would be the 'best' solution. But you might get reasonable mileage by setting up a second interrupt (chained off the first) to go off just _before_ the end of display (which is quite a few lines before vsync) and doing the rest of the drawing then.


Top
 
 Post subject: Re: Clowning around
PostPosted: Sat May 29, 2010 2:12 pm 
Offline
Site Admin
User avatar
 Profile

Joined: Wed Dec 19, 2007 10:46 pm
Posts: 779
ooh, very nice ...



Reminds me of Boxer's balloons ...

Sam.


Top
 
 Post subject: Re: Clowning around
PostPosted: Sun May 30, 2010 1:37 pm 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
Thanks Sam ;)

I did try and embed the video but it looked as if it was doing a repeat of the STH saga where you kept calling me thick and I kept agreeing but then we found out that I didn't have the privileges to use the bb flash thingy? I am after all under-privileged in so many ways.....


Top
 
 Post subject: Re: Clowning around
PostPosted: Tue Jun 01, 2010 2:32 am 
Offline
Site Admin
User avatar
 Profile

Joined: Wed Dec 19, 2007 10:41 pm
Posts: 373
What a great choice of game to convert (+upgrade!) ... :mrgreen:

Looks like you've done a brilliant job of recapturing the crazy/hypo speed of the original ver, too (the first couple of jumps on the video are particularly mental!!).

V happy right now! :)


Top
 
 Post subject: Re: Clowning around
PostPosted: Tue Jun 01, 2010 10:09 am 
Offline
Site Admin
User avatar
 Profile

Joined: Wed Dec 19, 2007 10:46 pm
Posts: 779
MartinB wrote:
I did try and embed the video but it looked as if it was doing a repeat of the STH saga

MartinB wrote:
but then we found out that I didn't have the privileges to use the bb flash thingy?

Try it again, Martin.

Looks like I didn't implement the same permissions over here at the time. Sorry 'bout that. Should be working for you now.

Sam.


Top
 
 Post subject: Re: Clowning around
PostPosted: Thu Jun 03, 2010 9:14 am 
Offline
User avatar
 WWW  Profile

Joined: Thu Apr 03, 2008 2:49 pm
Posts: 277
Location: Antarctica
Excellent stuff - always one of my favourites on the Atari 2600 - Circus Atari


Top
 
 Post subject: Re: Clowning around
PostPosted: Sun Jun 06, 2010 11:57 pm 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
Just back from a week away, thanks for the comments ;)

@Sam - Cheers for sorting that, I'll try posting another clip after I've done the timer interrupt change.

@Dave F - Thanks for the encouragement, I looked at all the various platform versions to get a feel for what's good and what's not so good so hopefully this conversion will be good fun. There is a conversion for the Beeb called Bozo & Beebo (I think?) but whilst it's bright and colourful, it doesn't 'feel' very playable. I don't think I've seen Boxer's Balloons that Sam referred to?

@Dave M - Glad you're pleased with the choice, I needed something to learn on and since I'd started (many years ago!), I thought I'd finish. The "crazy/hypo" speed is indeed available and I've bags of capacity to have him moving faster than would be playable! In fact, making it 'playable' is where I might fall down and I will doubtless need some testers who can play games better than me. It's a curious paradox that I'll struggle to play a game I'm writing :roll:

Being an engineer, I of course had to include lots of real-world physics and so gravity's there at about 10ms-2 on the basis that the clowns are about 5'6" tall. In fact, I can dynamically modify gravity (overall or in relation to altitude) so there's scope to vary the gameplay in that respect. (Moon balloons perhaps?) The flip board does behave like a real one would in that the speed of the outgoing clown depends on a combination of his position in relation to the fulcrum, the incoming clown's position in relation to the fulcrum and the speed of the incoming clown. The flipper though has to be lossless and in fact has to be slightly energy-giving to prevent things grinding to a halt. You can see the lowest status-quo at the end of the clip where the clowns will only pick up if the base is nudged to move them further along the board. It works fine but perhaps again needs some tuning to make it more of a game feature than a science exhibit! I have lots of options regarding the dynamics of the clown when he bursts a balloon - the crazy speed Dave M referred to can come about with a 180 degree reverse and a boost of energy from the balloon or he can just get nudged around as in the later part of the clip. These, and many other aspects, are all written to have fully tunable behaviour and this is where I think I might need feedback from one or two people who can, unlike me, actually play games :lol:

Finally, I might yet decide to re-write a major chunk of the basic game 'engine' because I've given the balloons single pixel movement but initially left the clowns and base at 2 pixels. However, I am toying with changing everything to one pixel because I think I can perhaps create better dynamics and hence a more tactile game with the better resolution. Dunno, maybe I'm being too much of an engineer and not thinking in arcade game mode? I can now see that a game needs much more than just the code... ;)


Top
 
 Post subject: Re: Clowning around
PostPosted: Thu Jun 10, 2010 10:08 pm 
Offline
User avatar
 WWW  Profile

Joined: Thu Apr 03, 2008 2:49 pm
Posts: 277
Location: Antarctica
Just looked at the video - looking really nice, top job on the physics, lovely and fluid :)


Top
 
 Post subject: Re: Clowning around
PostPosted: Tue Jun 15, 2010 9:19 pm 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
Thanks for the comments Dave :D and here's an update on the timing changes...

I followed Tom's suggestion and with serious guidance from RichTW's skeleton code, first added a timer interrupt primed by vsync where the new code block simply changed the background colour, the latter being reset by the next vsync. To keep things calm I disabled all the interrupt graphics motion and tuned to the timer to get a stable sync as below :
Attachment:
clowns timer sync.jpg [7.58 KiB]
Downloaded 413 times

That done, I then moved the motion code into the timer sync block, reduced the vsync code to priming the timer only, pressed go and...



(btw, ignore the clown dropping through the floor and reappearing - I removed his mortality for debugging purposes.)

This was somewhat baffling as I knew that vsync was fixed and that the timer was being primed by a fixed value so how could I have a seemingly rolling sync? I also noticed that as the balloons progresssively decreased in number, the rolling effect slowed and eventually stopped, settling down to the expected display. Given this, the answer was ultimately obvious but also very subtle - with full (or nearly full) rows of balloons, a row update takes longer than the time between my chosen timer trigger and the next vsync. Therefore, the timer sync IRQ code was still executing when the next vsync pulse arrived and the particularly subtle point is that whilst we are servicing an IRQ, the 6502 Interrupt Inhibit flag is set so whilst the new vsync pulse is registered by the 6522, it does not cause an IRQ condition until the RTI is executed at the end of the timer IRQ code. Thus, the vsync interrupt is effectively 'deferred' until the RTI and since the timer code consumes a slowly reducing time interval, the rolling effect is seen.

Easy to fix then, just add a CLI early on in the timer IRQ code so that this code can itself be interrupted, albeit briefly, to allow the timer to be re-primed and away we go...



Err.. until I tried moving the base (which at this time is background updated outside of the interrupt routines)...



This became one of those times when you just feel that you're chasing around in ever decreasing circles :roll:. Eventually (summing up no few hours head scratching) I realised that the OS method of saving the Accumulator in $FC means that the IRQ handling as a 'system' is not re-entrant because the contents of $FC are overwritten by the second IRQ and more than likely things will fall apart. After much anguish I have added an LDA $FC : STA my_A_store_<n> at the start of both IRQ code blocks with appropriate retrieval prior to the RTI and this seems to have fixed everything. Note that balloons are now totally flicker-free :D but the jumping clown now has some serious flicker (almost fade). I can easily sort the latter though by testing his Y position against the timer trigger line and schedule his update accordingly.



Looks good but hmm.., I'm not 100% convinced about the robustness of the code now because whilst I've been adding in other (previously tested) game features I've had some 'funnies' which have all the hallmarks of rampant register corruption but I can never seem to capture them.

In summary then - any thoughts or ideas anyone? (Assuming you're still awake...)


Top
 
 Post subject: Re: Clowning around
PostPosted: Tue Jun 15, 2010 10:41 pm 
Offline
User avatar
 WWW  Profile

Joined: Mon Mar 15, 2010 2:28 pm
Posts: 42
Location: Minehead, Somerset (UK)
Still being awake isn't the issue. I'm sat here thinking that if I need to understand all the details of this post for what I want to work on (likely) then I may as well give up before I even start!!!

Looks good BTW :)


Top
 
 Post subject: Re: Clowning around
PostPosted: Wed Jun 16, 2010 10:06 pm 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
other Martin wrote:
...then I may as well give up before I even start!!!
Noooo.. don't say that, it's probably just me that makes it sound complicated! I felt just like you but there's tons of great tutorials buried in the forum, lots of example code and a positive glut of experts to help you along. Do what I did - throw yer wellies on and just wade in 8-)

Returning to interrupt issues, Rich described how one can alter the line at which the vsync interrupt is generated, but is there a +- line limit on that offset? I looked back at what Rich has written and the questions I asked but I realise that at the time I perhaps didn't understand as much as I thought I did :roll:. For example, could I offset the line at which the vsync interrupt is generated way down the screen such that I wouldn't then need a timer at all? If not, could I at least put in the maximum possible line delay to effectively extend the time between the timer interrupt and the next vsync?

Sorry if those are dumb questions but I'm asking because I'm not entirely comfortable with the current state where the timer IRQ code is being interrupted by the vsync. (Unless someone a lot wiser than me can confirm that my preserving the contents of $FC is technically correct and should cover any double-IRQ issues?)


Top
 
 Post subject: Re: Clowning around
PostPosted: Wed Jun 16, 2010 11:13 pm 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 7:02 pm
Posts: 273
I'd have thought pushing the accumulator to the stack rather than a seperate area would be more reliable, but I can't think of any reason why your method wouldn't work.


Top
 
 Post subject: Re: Clowning around
PostPosted: Thu Jun 17, 2010 8:45 am 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 6:46 pm
Posts: 380
Location: Málaga, Spain
Hi Martin,

Yeah, as you discovered, the usual way to achieve reentrancy in IRQs is
Code:
.irq
LDA &FC
PHA
CLI
\\ your handler here \\
PLA
STA &FC
RTI

Obviously using the stack is safer as it makes it multiply reentrant.

Not exactly sure what could be causing your IRQ handler to be reentered more than once, but see if preserving &FC on the stack helps at all. Personally, I prefer not to do much work at all in an IRQ handler - I'd rather just set a flag and poll it in the main loop, but that's a personal preference thing... I'm sure there are advantages in doing all the hard work actually in the IRQ handler itself.

Regarding the VSync position - yes, you can change the screen line at which the VSync occurs (and hence when the interrupt is generated), but of course doing this will reposition your screen vertically so that VSync line is positioned just off the bottom of your TV screen, at the moment of flyback (which of course is less than useful!). That's why we have to do it with two interrupts - the VSync one just provides a constant reference point in each frame, and the timer is then set to interrupt us at a fixed point relative to the VSync in the following frame.

(In theory, it would be possible to use just 1 interrupt - a timer 1 free-run interrupt with a period of 20000us (or actually, I think about 3 ticks less than that, to account for the amount of time it takes to reload from the latch), but this is a bit more fiddly to set up at the beginning, and you still need to use the VSync pulse as a reference point to position it correctly at the start.)

Anyway, I haven't said it yet, but it looks mighty fine!


Top
 
 Post subject: Re: Clowning around
PostPosted: Thu Jun 17, 2010 9:10 am 
Offline
 Profile

Joined: Tue Apr 08, 2008 11:50 pm
Posts: 12
Regarding the 'flickering' of the ballons. Have you considered not erasing them... just plotting over the top with an XOR sprite.

The classic space invader style of game (mono) uses a base sprite we are all familiar with ;

000001000000
000011100000
000011100000
011111111100
111111111110
111111111110
111111111110

would have a movement sprite of ;

000001100000
000010010000
000010010000
010000000010
100000000001
100000000001
100000000001

Plot the base sprite, then XOR with the movement sprite. The base will appear to move one pixel to the right. Each pixel movement right just requires plotting the XOR sprite again a further pixel over. Conveniently being a symmetric sprite, we can use the same XOR sprite to move left again.

Since your ballons move in a classic invaders style, you could try this on them. No need to erase them completely, could reduce the flicker in the top of the screen - might get all the 'drawing' done in one raster field.

Just an idea.


Top
 
 Post subject: Re: Clowning around
PostPosted: Thu Jun 17, 2010 8:17 pm 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
Thanks very much Rich for the observations and kind words - you have already contributed greatly since there are many of your neat techniques lurking in there together with no small amount of your inspiration 8-)

Ok, I understand (finally!) about the vsync positioning and no, it's not a viable alternative. I did actually contemplate a timer-only route but I wondered whether there could be drift between vsync and the 6522 since I assume neither can be 100% accurate? Anyway, even if it did run accurately it would as you say be somewhat fiddly and I think I would feel nervous about it hanging together properly.

Actually, I have in the meantime managed to get some repeatability with the corruption I mentioned and I've realised that it only ever occurs during a process I call 'Flip'. This is the seemingly brief but actually complex set of routines that detect the incoming clown successfully arriving at the raised end of the board initiating a see-saw jump ending with the outgoing clown being launched. Here's a couple of sequential snaps of what happens when things go wrong. Curiously, using a BeebEm video capture subsequently single-stepped in QuickTime, the left-hand snap is the first faulty frame! A nasty bug indeed... :shock:
Attachment:
flip corruption.JPG [28.63 KiB]
Downloaded 349 times
This has definitely only ever started happening since I introduced the timer and more specifically it only happens if there is a vsync interrupt during a timer interrupt during a flip - and even then, only occasionally. I know this because if I decrease the number of ballons to say 6 or 7 (a game pre-set constant) which ensures that the timer IRQ code has always finished before the next vsync, the problem never occurs. That ought to be a good clue but as yet I've not had the required eureka moment. I'm thinking along the lines of a shared variable getting corrupted or similar but each time I think of something I'm drawn to the fact that the vsync code now only primes the timer and RTI's so it's very puzzling but I will crack it eventually. Probably something screamingly obvious but these things have a cunning way of sitting in your programming blind-spot!

@ recycled - Thanks for that, I do recall seeing the technique described somewhere but without tying my already befuddled brain in even tinier knots by thrashing around with EOR'd sprites, will that work when the two sprites are different? Hopefully you noticed that the balloons have waggerly tails? I can visualise EOR'ing the two balloon types together to produce a 'mess' where the 'mess' would then EOR with either type to produce the other type but that would only toggle them on the spot. I can't just visualise how that technique would be applied to allow the balloon to both move one-pixel and waggle it's tail? As I say, could be brain overload but I'm all ears... ;)


Top
 
 Post subject: Re: Clowning around
PostPosted: Thu Jun 17, 2010 11:56 pm 
Offline
User avatar
 Profile

Joined: Mon Jan 07, 2008 7:02 pm
Posts: 273
Re EORed sprites - why EOR them? Just have a blank column or two of pixels round each balloon and just STA them onto the screen.

If you get bored trying to find the interrupt bug then I'm happy to look at the code for you if you want.


Top
 
 Post subject: Re: Clowning around
PostPosted: Fri Jun 18, 2010 12:14 am 
Offline
User avatar
 Profile

Joined: Fri Apr 25, 2008 7:55 pm
Posts: 147
Thanks very much for the kind offer Tom - I'll thrash it around a bit longer but if I have to admit defeat then I may well take you up ;)

On the sprite drawing, part of this project was me challenging myself to produce a fairly dynamic game with lots of sprites using traditional plotting methods. I think I'll stick with the game engine as it is until it's finished and then maybe try a re-write using optimised techniques.

I wrote:
...and more specifically it only happens if there is a vsync interrupt during a timer interrupt during a flip
After much investigation I can modify that to :

...and more specifically it only happens if there is a vsync interrupt during a timer interrupt during a flip AND a key is pressed AND the base is moving at the time the flip is initiated.

I might as well show the video evidence - the first clip shows a run where I just leave things alone until a good number of balloons have been burst and then I start sliding the base around. In the second clip I start moving the base straight away and a few flips later....





Note again that the clown behaviour is basic debug only and not representative of the final game ;)


Top
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 38 posts ]  Go to page 1, 2  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: