It is currently Mon Oct 20, 2014 5:45 pm

All times are UTC [ DST ]




 Page 1 of 1 [ 15 posts ] 
Author Message
 Post subject: BBC Sprite Designer
PostPosted: Sat Nov 24, 2007 2:15 pm 
User avatar

Joined: Fri Dec 29, 2006 1:15 am
Posts: 495
Location: Glasgow, UK
Hi guys,

I'm planning on getting the BBC Sprite Designer underway. What I need from people are features you would need incorporated into the software.

I have a very basic sprite designer up and partially running at the moment that has the following features:

- Loading of image files (BMP, JPG, PNG, etc.)
- Set size and mode of sprite
- Very basic drawing facilities which allows you to paint pixels
- Add/delete frames (for animated sprites)

So far I have had the following requests:

- Output to VDU/DATA statements
- Accept input of animated GIFs
- Allow selection of a palette
- Allow resize (if required)
- Output the frames to a memory location of your choice (under BeebEm), then produce basic or fast asm code to call and activate the animation!!!! :shock:

Kind regards,

Francis.



_________________
Dreamland Fantasy Studios
http://www.dfstudios.co.uk
Offline
 Profile  
 
 Post subject:
PostPosted: Sat Nov 24, 2007 2:52 pm 
User avatar

Joined: Wed Aug 24, 2005 1:13 pm
Posts: 2128
Location: Back of beyond
Sounds great Francis, think you've got most bases covered. I'd like the facility to add a sprite mask. We'd have to agree on the output format for this though, as either a colour ref in the png (or whatever) that is not in the palette or as abit map mask.

Not all games require this, some use one of the existing colours to designate the mask in which case the mask type I've mentioned above doesn't matter, but some like it separate for occasions when you want to use all colours properly in a sprite.

I'm probably being vague there, if you want more details I can supply them. And no rush for this if you want to get a version out without it first.


Offline
 Profile  
 
 Post subject:
PostPosted: Sat Nov 24, 2007 3:56 pm 
User avatar

Joined: Thu Jan 13, 2005 6:20 pm
Posts: 595
Location: Málaga, Spain
Thought I'd just share my experience of sprite designing and exporting, in case it proves helpful in some way.

In the past, I used to use the Acorn Sprite Rom on the Master welcome disc ("Spriter"), and use the admittedly shocking editor to create a set of sprites (e.g. player character animation frames, or background map tiles). Then, for each set of sprites, I would write a Basic program which would display them one-by-one at the top-left of the screen (via PLOT &EF, x, y), and copy them into a block of memory in my own arrangement, before finally saving this block out as my 'raw' data.

I found I nearly always needed the data in just two particular arrangements, depending on how the sprites were being used.

For sprites which are being plotted only at character-block aligned positions (e.g. background map tiles), the data's most useful in the 'conventional' format, i.e. as per the BBC screen layout.

Here's a Basic fragment which would take an 12x24 MODE 2 sprite plotted at the very top of the screen and convert it into this format:

Code:
FOR row%=0 TO 2
  FOR x%=0 TO 47 STEP 4
    x%!(sprbase%+row%*48)=x%!(&3000+row%*640)
  NEXT
NEXT


Then, you would plot a sprite like this via the most simple type of sprite routine, which might look a little like this:

Code:
\\ on entry:
\\  (sprdata, sprdata+1) -> base of sprite to plot
\\  (screen, screen+1) -> screen address to plot at
.simplesprite
LDX #2
.spriterow
LDY #47
.spriteloop
\ unroll a little for extra speed
LDA (sprdata),Y:STA (screen),Y:DEY
LDA (sprdata),Y:STA (screen),Y:DEY
LDA (sprdata),Y:STA (screen),Y:DEY
LDA (sprdata),Y:STA (screen),Y:DEY
LDA (sprdata),Y:STA (screen),Y:DEY
LDA (sprdata),Y:STA (screen),Y:DEY
LDA (sprdata),Y:STA (screen),Y:DEY
LDA (sprdata),Y:STA (screen),Y:DEY
BPL spriteloop
DEX:BMI finished
\ move screen address pointer to next screen row
CLC:LDA screen:ADC #&80:STA screen:LDA screen+1:ADC #2:STA screen+1
\ move sprite address pointer to next sprite row
\ C is clear here
LDA sprdata:ADC #48:STA sprdata:BCC spriterow:INC sprdata+1
\ Z flag guaranteed to be clear here
BNE spriterow
.finished
RTS



For sprites which need to be able to be plotted at any screen line, the routine is much more complicated due to the awkward non-linear Beeb screen layout. I always found that the most useful format in this particular instance was 'column first', i.e. putting a whole column's worth of data in a contiguous block, like this Basic fragment here:

Code:
FOR column%=0 TO 5
  FOR row%=0 TO 2
    FOR n%=0 TO 7 STEP 4
      n%!(sprbase%+row%*8+column%*24)=n%!(&3000+row%*640+column%*8)
    NEXT
  NEXT
NEXT


The sort of routine you could use to plot this might then look a little like this:

Code:
\\ on entry:
\\  (plotcolumn+1, plotcolumn+2) -> base of sprite to plot
\\  (screen, screen+1) -> address of top of character block to plot at
\\  Y = which line within character block
.complexsprite
LDA #6:STA columns
LDA screen:STA screentemp
LDA screen+1:STA screentemp+1
STY ytemp
.foreachcolumn
LDX #0
.plotcolumn
LDA &FFFF,X   \ self-modified
STA (screen),Y
INX:CPX #24:BEQ donerow
INY:CPY #8:BCC plotcolumn
\ C already set when we get here
LDA screen:ADC #&7F:STA screen:LDA screen+1:ADC #2:STA screen+1
LDY #0:BEQ plotcolumn
.donerow
\ C already set when we get here
DEC columns:BEQ finished
LDA plotcolumn+1:ADC #23:STA plotcolumn+1
BCC skiphibyteinc:INC plotcolumn+2:CLC:.skiphibyteinc
LDY ytemp
LDA screentemp:ADC #7:STA screentemp:STA screen
LDA screentemp+1:ADC #0:STA screentemp+1:STA screen+1
\ Z guaranteed to be clear here
BNE foreachcolumn
.finished
RTS

(Disclaimer: all totally untested code! If it doesn't assemble, crashes your Beeb, or burns your lasagne, it's not my fault, honest!)

These are by no means totally optimal (though I can't stop myself from optimising the code as I write it to some extent...) - for example, the 'complex' sprite routine would be better if it plotted the sprites from the bottom upwards, saving the two CPX/CPYs in the innermost part of the loop, but this is left as an exercise...blah blah....

So to cut a long rambling post vaguely short-ish, support for these two export formats would be great!

Oh, masks!

(am I ever gonna shut up?)

sorvad mentioned masks... well, certainly in a 4 colour mode, they're necessary if you want to avoid horrible-looking EOR mode plotting. I would treat mask data as totally separate from sprite data (don't try to interleave them or anything in the export), and effectively the mask just contains white pixels for transparent, and black pixels for opaque. Then, instead of:
Code:
LDA (sprdata),Y
STA (screen),Y


you use:
Code:
LDA (screen),Y
AND (maskdata),Y
EOR (sprdata),Y
STA (screen),Y

or similar.

In Mode 2, I would say that exporting a separate mask is not necessary, as it doubles your sprite data size, and there are already redundant bits in the sprite data (which represent colours 8-15) which can happily be used to indicate transparent pixels, though your sprite routine then needs to be a little more clever!

OK, I'm out of here, I'm all sprited-out!


Offline
 Profile  
 
 Post subject:
PostPosted: Sat Nov 24, 2007 6:43 pm 
User avatar

Joined: Wed Aug 24, 2005 1:13 pm
Posts: 2128
Location: Back of beyond
Concur with all you said, also
Rich Talbot-Watkins wrote:
These are by no means totally optimal (though I can't stop myself from optimising the code as I write it to some extent...) - for example, the 'complex' sprite routine would be better if it plotted the sprites from the bottom upwards, saving the two CPX/CPYs in the innermost part of the loop, but this is left as an exercise...blah blah....


A good coder always goes down ! Well numerically speaking :) Just to clarify bottom upwards is referring to the screen but is actually counting down :) Reason being is that if you reach zero you can detect this without having to check if the value is zero first and saves you some processor cycles and in the inner loops of sprite plotting you want to save all you can :)

Hope you don't mind me expanding on that Rich :)


Offline
 Profile  
 
 Post subject:
PostPosted: Sat Nov 24, 2007 10:11 pm 
User avatar

Joined: Fri Dec 29, 2006 1:15 am
Posts: 495
Location: Glasgow, UK
@sorvad & Rich

Thanks for your comments and suggestions.

Kind regards,

Francis.



_________________
Dreamland Fantasy Studios
http://www.dfstudios.co.uk
Offline
 Profile  
 
 Post subject:
PostPosted: Sat Nov 24, 2007 11:11 pm 

Joined: Mon Jan 03, 2005 2:38 am
Posts: 369
Plotting downwards is also marginally better when it comes to 'beating the timeout' on flicker-free plotting, since the raster gun works from top to bottom.


Offline
 Profile  
 
 Post subject:
PostPosted: Sun Apr 27, 2008 1:29 am 

Joined: Mon Jan 03, 2005 2:38 am
Posts: 369
Rich Talbot-Watkins wrote:
Code:
\\ on entry:
\\  (plotcolumn+1, plotcolumn+2) -> base of sprite to plot
\\  (screen, screen+1) -> address of top of character block to plot at
\\  Y = which line within character block
.complexsprite
LDA #6:STA columns
LDA screen:STA screentemp
LDA screen+1:STA screentemp+1
STY ytemp
.foreachcolumn
LDX #0
.plotcolumn
LDA &FFFF,X   \ self-modified
STA (screen),Y
INX:CPX #24:BEQ donerow
INY:CPY #8:BCC plotcolumn
\ C already set when we get here
LDA screen:ADC #&7F:STA screen:LDA screen+1:ADC #2:STA screen+1
LDY #0:BEQ plotcolumn
.donerow
\ C already set when we get here
DEC columns:BEQ finished
LDA plotcolumn+1:ADC #23:STA plotcolumn+1
BCC skiphibyteinc:INC plotcolumn+2:CLC:.skiphibyteinc
LDY ytemp
LDA screentemp:ADC #7:STA screentemp:STA screen
LDA screentemp+1:ADC #0:STA screentemp+1:STA screen+1
\ Z guaranteed to be clear here
BNE foreachcolumn
.finished
RTS

(Disclaimer: all totally untested code! If it doesn't assemble, crashes your Beeb, or burns your lasagne, it's not my fault, honest!)

These are by no means totally optimal (though I can't stop myself from optimising the code as I write it to some extent...) - for example, the 'complex' sprite routine would be better if it plotted the sprites from the bottom upwards, saving the two CPX/CPYs in the innermost part of the loop, but this is left as an exercise...blah blah....


If one was trying to 'beat the raster redraw' (i.e. getting the very maximum flicker-free plot time for sprites in a frame before the beam catches up to one's drawing), surely plotting sprites from top to bottom would allow (slightly) more redraw time than plotting sprites from bottom to top, before the crt gun passes down the screen?

It seems to me that the maximised window of time to plot a sprite is achieved by setting a timer to coincide with the redraw beam having just passed down past the last line of one's sprite, and the timer's callback routine draws the next sprite from top-to-bottom. The largest non-flickering sprite would be the kind that has its last line plotted just before the crt gun overtakes it!


Offline
 Profile  
 
 Post subject:
PostPosted: Sun Apr 27, 2008 11:43 am 
User avatar

Joined: Thu Apr 17, 2008 12:56 pm
Posts: 33
Location: Northampton
Aww its nice to see so many game coders discussing stuff ... I've been coding for 30 years (holy poo!), never on the beeb thou!!

Whats nice is the thought and effort of comments - so a big thumbs up frfom me!!

Well, I'll have to get stuck in, lots to learn!!

- :shock:

thanks - Neil



_________________
---------------------------------------------------
We live for the one, we die for the one!
Offline
 Profile  
 
 Post subject:
PostPosted: Mon Apr 28, 2008 8:49 am 
User avatar

Joined: Thu Jan 13, 2005 6:20 pm
Posts: 595
Location: Málaga, Spain
garfield wrote:
If one was trying to 'beat the raster redraw' (i.e. getting the very maximum flicker-free plot time for sprites in a frame before the beam catches up to one's drawing), surely plotting sprites from top to bottom would allow (slightly) more redraw time than plotting sprites from bottom to top, before the crt gun passes down the screen?

Yeah, that's true. But the 'plotting from bottom-up' change is a speed optimisation, which saves 4 clock cycles per byte - something which could add up to a significant saving if you plot enough sprites per frame.

As it goes, the plotting direction doesn't really matter so much in this routine, because the sprite is plotted in separate columns from left to right which means that if you intersect the raster redraw, you'll probably still see an artefact in one of the columns.

Quote:
It seems to me that the maximised window of time to plot a sprite is achieved by setting a timer to coincide with the redraw beam having just passed down past the last line of one's sprite, and the timer's callback routine draws the next sprite from top-to-bottom. The largest non-flickering sprite would be the kind that has its last line plotted just before the crt gun overtakes it!

Yep, that's true! But in practice, in a game, this is hard, because you probably can't guarantee the y positions of the sprites every frame. But you can still help the flicker problem by sorting the sprites by y position first, and then plotting them in that order, after the raster has reached the lowest point of the game window.

My spinning dots demo in BeebAsm makes optimal use of these raster timings. First all the dots are plotted from highest to lowest. Then they are all erased in the same order. The demo is timed so that the erasing starts such that when the last dot is erased, the raster beam is at the lowest y coordinate of the globe, ready for the plotting part again. This is only possible though because the y positions are fixed and very carefully chosen to be spread out evenly.


Offline
 Profile  
 
 Post subject:
PostPosted: Mon Apr 28, 2008 9:16 am 
User avatar

Joined: Wed Aug 24, 2005 1:13 pm
Posts: 2128
Location: Back of beyond
Also Rich mentions plotting in columns, i.e. column 0 column 1 etc. from bottom to top.

Why not plot horizontal you may ask ? i.e. a row at a time. Well, because of the way the Beebs memory map is organised by the 6845 (which is optimised to plot ascii characters) it would take even more clock cycles to do this than working in byte columns.


Offline
 Profile  
 
 Post subject:
PostPosted: Mon Apr 28, 2008 10:58 am 

Joined: Mon Jan 03, 2005 2:38 am
Posts: 369
By the way guys, where 'physically speaking', does the vsync interrupt correspond to on-screen? Is it conceptually at the very bottom of the frame, or at the very top of the next frame (if the distinction matters at all!)?

And is it correct to assume that the redrawing crt gun is just slightly ahead of the point where the vsync interrupt was issued when you actually get to service it?

:?:


Offline
 Profile  
 
 Post subject:
PostPosted: Mon Apr 28, 2008 11:33 am 
User avatar

Joined: Wed Aug 24, 2005 1:13 pm
Posts: 2128
Location: Back of beyond
Looking at the advanced user guide it seems to be after the last row from memory is displayed. But I'm not 100% if this is the case, Rich may know better.

And yes, the electron beam will be slightly ahead of where Vsync occurred by the time you get to service it due to interupt latency and time to process interupt handler OS code.


Offline
 Profile  
 
 Post subject:
PostPosted: Mon Apr 28, 2008 12:11 pm 
User avatar

Joined: Thu Jan 13, 2005 6:20 pm
Posts: 595
Location: Málaga, Spain
garfield wrote:
By the way guys, where 'physically speaking', does the vsync interrupt correspond to on-screen? Is it conceptually at the very bottom of the frame, or at the very top of the next frame (if the distinction matters at all!)?


Actually, neither! The best way to explain it is with reference to the CRTC registers.

Let's take MODE 2 as an example.

First of all, remember we have 312 lines in a PAL screen - or 39 character rows of 8 scanlines (39*8=312). These are defined here:

CRTC R4 = 38 (vertical total minus 1)
CRTC R9 = 7 (scanlines per character minus 1)

Now MODE 2 has 32 visible rows, and this is defined here:

CRTC R6 = 32 (vertical displayed)

This means we have 7 rows which are unaccounted for - these in fact comprise the top and bottom borders and the vertical flyback period. So whenabouts in these is the VSync?

The answer is to look at CRTC R7 which defines the screen row at which VSync occurs. Looking at the AUG, we see that, by default for MODE 2, VSync is programmed to occur at line 34, i.e. after two rows of border after the screen has 'finished'.

Now, VSync is a signal to the VDU to commence vertical flyback, i.e. bringing the beam position back to the top of the screen. This doesn't happen in an instant, but of course requires some time. How long?

Well, we know that we have two blank rows before VSync. We also know that the screen is more-or-less centred on the monitor, so it makes sense that we also have two blank rows of border before the 'actual' screen is displayed. So if we have in total 4 blank rows displayed as border, it follows that we are using roughly 3 rows for the flyback period.

Thus we can breakdown the screen like this:

top border CRTC row 37
top border CRTC row 38 ________
screen row 0
screen row 1
......
screen row 30
screen row 31 ________
bottom border CRTC row 32
bottom border CRTC row 33
VSync row 34 *

* at this point, flyback begins, and three rows later, the CRT beam is back to the very top of the TV's physical display (at CRTC row 37), ready to emit 2 further lines of border before commencing the memory-mapped display.

Now you can see how changing the value of CRTC R7 vertically displaces the screen by character row amounts, just like *TV. If, for example, the VSync position were changed to row 32, the screen would be moved down, due to the CRT beam reaching the top of the screen at CRTC row 35, resulting in 4 rows of top border instead of 2.

So, the other thing is that using the VSync to time new frame rendering is not really ideal. Better is to set off a timer relative to VSync which interrupts as soon as the raster is just beyond the bottom of the game area. This gives you as much time as possible to render the next frame!


Offline
 Profile  
 
 Post subject:
PostPosted: Mon Apr 28, 2008 12:43 pm 
User avatar

Joined: Wed Aug 24, 2005 1:13 pm
Posts: 2128
Location: Back of beyond
Absolutely great reply Rich :) Your the man with those CRT registers for sure !


Offline
 Profile  
 
 Post subject:
PostPosted: Mon Apr 28, 2008 1:36 pm 

Joined: Mon Jan 03, 2005 2:38 am
Posts: 369
Thanks Rich and Sorvad. Very well explained!


Offline
 Profile  
 
Display posts from previous:  Sort by  
 Page 1 of 1 [ 15 posts ] 

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:  

phpBB skin developed by: John Olson
Powered by phpBB® Forum Software © phpBB Group