Blitter First Demo :-)

162 views
Skip to first unread message

Julian Skidmore

unread,
Feb 8, 2013, 11:13:46 AM2/8/13
to FIGnition
Hi folks,

Take a look at the first Blitter demo for FIGnition - I think you'll
be impressed!

As part of the next firmware upgrade I've been working on an initial
version of the blitter, mostly because I know I need to make it fit in
Flash with the other firmware changes. I always figured the blitter
would be pretty good, but now we can finally see it in action:

http://www.youtube.com/watch?v=vqwK4lum0Hs

So, this is the first (albeit silent) demo. In this demo you can see
FIGnition's blitter blitting a number of 4x3 nyan cat sprites across
the bitmapped screen using the 2blt command. The sprites themselves
start at random locations and move at constant, random speeds between
1 and 16 pixels per step.

Initially there are 10 sprites, and the 2blt blitter is able to move
them at around 50 frames per second. As I increase the number of
sprites to 44, the frame rate slows down to about 11 fps. This means
that FIGnition is blitting at effectively 12,000 8x8 tiles per second
(because moving each of these sprites requires drawing 12 tiles in the
new location and undrawing 12 tiles in the old location: so 2 (drawing
ops)*12 (tiles/sprite)*10 (sprites)*50 (fps) = 12K tiles / second). It
can do this for sprites of any width and height up to the size of the
full frame buffer and at any pixel location, the shifting is performed
in real-time as it copies the image to the frame buffer.

This is good I believe, compared with the performance of most 8-bit
computers moving graphics images. It's certainly good enough for most
shoot-em-ups. For example, space invaders requires 55 aliens each of
which require 2 tiles. FIGnition would typically blit them all at
50fps.

Of course this is all done by copying images from internal tile space
to dog-slow* serial SRAM frame buffer while FIGnition is actually
generating a bitmapped video image from a frame buffer on the same
serial SRAM. Although it's only monochrome, it offers the kind of
versatility you can't get from a microcontroller alone.

The Blitter isn't finished yet. I need to add clipping (though this
will speed up the blitter), so that you can specify an area of the
screen outside of which blitting has no effect. I also need to add the
blts command to rapidly dump background patterns on the image.

I've changed the semantics of 2blt. I found that it was awkward to
have to generate what would be 6 inputs for the command. Instead the
at command now manages the clever part. Here's how it works. Normally
when you're moving images around the screen in a game, you want to
calculate the new location, blit the new sprite's image to the new
location then xor blit the old-sprites image to the old location to
make it disappear. That way you reduce the flicker on the screen if
the display operation didn't complete before the next frame starts.

This is pretty awkward because you have to remember the old location
all the way to the end of the operation. The new at command stacks the
previous at coordinates to make this easier. So now the general
operation is:

oldx oldy at CalcNewCoords
newx newy at ( oldx oldy get saved too by at)
prevSpriteTile prevSpriteDimensions newSpriteTile newSpriteDimensions 2blt

For my nyans routine the central routine is now:

: catsBlit ( --)
0 catList
numCats @ 0 do >r ( : catListPointer)
r c@ r 1+ c@ 2dup at ( old Coords)
swap r 2+ c@ catMv ( gen newCoords based on oldCoords and speed)
over r 1+ c! ( new x)
dup r c! ( new y!) ( update new Coords in catList)
swap at ( set new coords and save old ones)
0 772 0 772 2blt ( draw new location, erase old one)
r> 3 + ( next cat)
loop drop
;

I think the rest of the development will take several more days, it
always takes longer than you expect and then I'll have a bit of
tidying of the firmware to do. But at least this little demo lets you
know what I've been up to and also some of the game possibilities
FIGnition will offer in the much near future!

-cheers from julz

( *dogs aren't really slow admittedly :-) )

--

The DIY 8-bit computer from nichemachines™
NyanRace00.jpg
NyanRace.fth

carl

unread,
Feb 8, 2013, 2:23:45 PM2/8/13
to fign...@googlegroups.com
Nyan Cat! awesome/ sick as my son would say!! 

I hope you will not have to alter the keyboard input, the editor is really good for me at the moment.
Have liked the video, its a great demo.

James Grimwood

unread,
Feb 8, 2013, 4:30:53 PM2/8/13
to fign...@googlegroups.com
That's pretty impressive for an AVR that's doing all the other things the Fignition does in software.


--
You received this message because you are subscribed to the Google Groups "FIGnition" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fignition+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
iOS Games - http://ncot.piku.org.uk | Programming Blog - http://error-success.piku.org.uk | Photos - http://photography.piku.org.uk

Julian Skidmore

unread,
Feb 8, 2013, 6:38:49 PM2/8/13
to fign...@googlegroups.com
Hi James,

Thanks! I had the blt command working yesterday, so I had a cruder
sequence of the nyan cat just moving forward pixel by pixel across the
screen from top to bottom... 2*17,000K blts in 33s

But that was a bit too boring for a video so when I hacked up a
version of 2blt today I wrote this newer nyan cat demo to go with it.
It still only shows a single sprite moving with multiple copies, but I
have tested blt with different sized sprites with 1 and 4 tiles as
well as the 12 tile nyan cat.

I'm going to blog a bit more about the details when I get a chance -
there's still some work to do. On Monday I'll implement clipping,
which will, ironically, make blitting go slightly faster despite the
extra functionality. Then I'll need blts which blits repliactions of
bitmaps across the screen, about twice as quickly as blt runs.

What I'm really looking forward to at the moment is being able to use
the code from blts to dramatically increase the performance of 2blt by
almost 2x. This is how: blt always has two phases. To blit an image of
w by h tiles we read in a strip of w tiles from sram, xor it with an
8-pixel section from the sprite and then write it out. Then we shift
to the next strip of tiles, for h strips. That way the routine
achieves maximum performance, but it only needs to cache w tiles from
the frame buffer (though sometimes it will be w+1 tiles if the
destination x coordinate wasn't aligned on a tile boundary).

The xor process is actually interleaved with the SRAM reading process
so that as each byte is read it's combined with up to two sprite
bytes. It takes about 20ish cycles to do this and I need 20 cycles
between each SRAM read. But it also means that the blitter operates at
roughly the same speed as simply reading in SRAM - as though the
shifting and xoring comes for free :-)

Normally then if you wan to do a 2blt, to move an image, the obvious
way is to combine two blts, one for the new bitmap at the new location
and the other for the old bitmap for the original location (to erase
it). However, I realised that because it's possible to fit the
blitting operation into the SRAM reading phase, then it will be
possible to fit the second xor blitting operation into the SRAM
writing phase (you xor the two sram bytes into each tile byte and then
write it out). Thus, 2blt can effectively move a sprite in the time as
it takes to do a simple blit! It's like, you can get everything for
free :-)

And it so happens (I think, though I haven't proved this yet), that
because the blts replicated blitting operation is done purely with a
write operation (it just overwrites what was there so it doesn't read
it in first), then that phase of the code will basically be there
ready to be used by 2blt. And when I've only got <0.5Kb of Flash
spare, I'm thankful for everything I get for free :-)

I think the upshot will be that FIGnition's sprite graphics
performance will match (and quite possibly greatly exceed) those of
80s home micros of which I'm particularly thinking of the ZX Spectrum
/ C64 / BBC type machines. But I'll try and do a better demo when I
can :-) !

Thanks for reading this,

-cheers from julz

On 2/8/13, James Grimwood <ja...@piku.org.uk> wrote:
> That's pretty impressive for an AVR that's doing all the other things the
> Fignition does in software.
>
>
> On 8 February 2013 19:23, carl <carl.a...@gmail.com> wrote:
>
>> Nyan Cat! awesome/ sick as my son would say!!
>>
>> I hope you will not have to alter the keyboard input, the editor is
>> really
>> good for me at the moment.
>> Have liked the video, its a great demo.
>>
>>
>> On Friday, 8 February 2013 16:13:46 UTC, Julz wrote:
>>>
>>> Hi folks,
>>>
>>> Take a look at the first Blitter demo for FIGnition - I think you'll
>>> be impressed!
>>>
>>> As part of the next firmware upgrade I've been working on an initial
>>> version of the blitter, mostly because I know I need to make it fit in
>>> Flash with the other firmware changes. I always figured the blitter
>>> would be pretty good, but now we can finally see it in action:
>>>
>>> http://www.youtube.com/watch?**v=vqwK4lum0Hs<http://www.youtube.com/watch?v=vqwK4lum0Hs>

Julian Skidmore

unread,
Feb 16, 2013, 8:00:01 AM2/16/13
to fign...@googlegroups.com
Hi guys,

Just a little update on the Blitter progress: I've updated the code to
handle arbitrary clipping and I'm now in the process of testing it. I
won't be able to make much progress on that for a week, because I'll
be off to GEEK2013; and testing may well take a few days; I'm hoping
to have another update about the Blitter at the end of Feb.

http://www.geek2013.co.uk/

-cheers from julz

Julian Skidmore

unread,
Feb 28, 2013, 11:23:03 AM2/28/13
to fign...@googlegroups.com
Hi folks,

I'm back working this week and I've made a bit of progress, the
clipping blitter testing code is now tested, so I'll be able to start
testing the clipping blitter now (at the moment that version just
crashes).

-cheers from julz

Julian Skidmore

unread,
Mar 13, 2013, 9:58:26 AM3/13/13
to fign...@googlegroups.com
Hi folks,

I've been able to work on the blitter and I've finally gotten the
Clipping version of the blitter to work. I haven't timed it yet, I've
just tested my required test cases on the nyan cat. I can blit the cat
anywhere on the screen and parts outside the clipped frame (which can
be as small as 1x1 pixels or as large as the screen) are clipped
correctly - I thought it would just be a case of adding clipping code,
but in reality required a rewrite of the original blitter and
therefore took longer than I had expected.

I'll probably post a video of nyan cats with clipping enabled (it will
look only slightly different as cats won't wrap around the screen).
I'm thinking at this point there's still something I should change: in
the same way that you can put a bitmap near the bottom right and the
bottom and right parts of a sprite should be clipped, you should be
able to put a bitmap partially off-screen at the top left and only see
a bottom right portion. This means that I should handle negative
coordinates.

However, since the coordinate space of FIGnition's bitmap mode is
160x160, and coordinates are bytes (clever me ;-) !), it's not
possible to simply support coordinates in the range -128 to 128.
Instead I'll compromise: Coordinates will be from -56 to 199 (x=200
will be treated as -56). This means that bitmaps > 56 pixels wide or
56 pixels high can never be fully offscreen. (FIgnition can't
practically support a bitmap > say 56 pixels x 48 pixels anyway, since
that would require more than 51 internal tiles, remember tiles are
only bitmap caches; you can replace them on the fly, even within a
frame).

-cheers from julz

Julian Skidmore

unread,
Mar 13, 2013, 12:08:36 PM3/13/13
to fign...@googlegroups.com

Hi folks, it turns out it was easy to support coordinates in the range (-56,-56) to (199,191) and pretty easy to improve the clipping blitter to support bitmap height and widths at pixel resolution (I'll need it for blts).

Blts next :-)

-cheers from julz

Julian Skidmore

unread,
Mar 14, 2013, 5:23:44 PM3/14/13
to fign...@googlegroups.com
Hi folks,

I've finally written the final routine in the bltter: blts, though
it's currently untested. It's possible to write a version of blts that
goes twice as fast as blt, at around 3microseconds per byte, but in
the end I was concerned it might use up too much memory. So instead
I've written a version that's only a little faster than blt, but
actually should be fast enough for most purposes.

In my research I've been comparing FIGnition's routines to sprite
routines on a VIC-20 and others. Because of the weirdness of ZX
Spectrum video it's hard to track down how fast you can really display
sprites, but it's something like 40 tiles per frame, which is really
tiny. Similarly, there's some VIC-20 code for sprites that takes up a
little over 60microseconds per byte, around 10x slower than FIGnition.
So, I figure I can cope with FIGnition performance for the moment! And
if I find space later, I'll improve it!

The next message in this thread will be when I've finished testing this routine.

-cheers from julz

Julian Skidmore

unread,
Mar 18, 2013, 6:40:40 PM3/18/13
to fign...@googlegroups.com
Hi folks,

Just a little update: I've managed to get my initial version of blts
to work, it only took 3 to 4 hours of debugging (that's pretty good
going for firmware development!). That means my major hurdles for
firmware development are done and I can get back to working on the
final compiler changes before I can release 0.98 :-) I do really need
to do a better blitter demo though!

-cheers from julz

Julian Skidmore

unread,
Mar 20, 2013, 5:26:46 AM3/20/13
to fign...@googlegroups.com
Hi folks,

I've updated the firmware so that characters can be displayed in hires
mode, at any pixel location :-) (not just character locations).

Interestingly, I found out yesterday there were still some more bugs
in my blitting code! Stupidly I'd only really tested blts using the
nyan cat bitmap and assumed that because I'd clipped it down to 8x8
and even 1x1 pixels during testing, that it was the same as using 8x8
bitmaps - how wrong was that?

So, here's a description of the other 3 bugs I found:

* Firstly, blt, 2blt and blts should update the x coordinate to just
after the last bitmap you drew. blts should also update the y
coordinate after each line of bitmaps that are drawn. However, blts
was updating the y coordinate even if you only drew one line - that
meant that using blts to display characters, they would all be shown
vertically :-(

* Secondly, blt, 2blt and blts would work with bitmaps that started at
up to tile 30, but if you tried to use tile 31 onwards it'd show
gibberish. That was because the pixel shifting algorithm is a 'C'
compatible routine that assumed register r1 was 0, but this wasn't the
case if it was called from the blitter and you used tile 31 onwards
(because it'd add 1 to the tile and then multiply by 8, with r1
holding the high byte, which would be 1 in this case).

At this point I could start to display characters using the blitter
(which allows me to display them at any pixel on the screen). However
I then found that the blitter couldn't display 8x8 or 16x16 bitmaps
properly unless y was aligned on a multiple of 8. This turned out to
be a signed arithmetic bug, I'd done a signed division by 8 using lsr
instead of asr.

Fourthly, after all this, I was able to display characters (and 16x16
bitmaps) anywhere. So, I did a simple test displaying "Hi" from the
top left to bottom right* with a 5 tick pause between each. However,
it would only work if I paused after each display with key drop .
Weird. It turned out I hadn't set any default clipping boundaries when
I cleared the screen.

So, after another day's worth of work I finally I think I have a
usable version of the blitter, with blt, 2blt and blts written. The
firmware is up to 14076b long, which means there's 260b free for any
of my new features - who could ask for more ;-) ?

* The test code was:

: tc
1 vmode cls
159 0 do
i i at ." Hi"
5 pause
loop
0 vmode
;

You can see that using hires mode is getting easier and cls now also
works in hires mode to clear the display properly. Flipping back to
text mode also automatically clears the display so you don't get the
junk on the screen you used to. In addition of course, there are a few
hundred bytes I can free in from firmware routines that aren't doing
anything useful!

-cheers from julz

Julian Skidmore

unread,
Mar 20, 2013, 7:01:01 AM3/20/13
to fign...@googlegroups.com
Hi folks,

I now have some new performance data for the new version of the
blitter (which does clipping and works with blts); it's 99.6% of the
speed of the old one when tested with the nyan cat. That's 12622
tiles/s or 252 source tiles per frame.

If you measure it in destination tiles; that's 6.3µs per byte, or
equivalent to 22 clocks on a ZX Spectrum, 6.3 clocks on a VIC-20. In
other words, FIGnition's blitter can read a source bitmap, shift it,
clip it and store it as fast as a Spectrum can do a simple block move
and it does this using external serial RAM. A VIC-20 routine for
bitmapped sprites I saw a short while ago, required 60 clock cycles
per byte moves; a Spectrum using pre-shifted sprites would be at least
2 or 3x slower than FIGnition, e.g for a simple case:

ld b,8
loop:
ld a,(de) ;pre-shifted src bitmap
inc e
xor (hl)
inc l
ld (hl),a ;stored the lhs byte..
ld a,(de)
inc e
xor (hl)
dec l
inc h
ld (hl),a ;stored the rhs byte.
djnz loop
;6*7+5*4+13 = 75clocks/byte or 21.4µs/byte, 3.4x slower than FIGnition.

Or on a VIC-20, if (sprite) is a z-page sprite pointer, (screenLHS) is
a z-page pointer to a left-hand side framebuffer strip and (screenRHS)
is a z-page pointer to the right-hand side framebuffer strip at
176+screenLHS. (shiftVec) is a jump vector for shifting pixels. mask
is the pixel mask. height is the sprite's height. Y is the sprite byte
index (also the framebuffer byte index). We get:

loop:
lda (sprite),y ;5.5 cycles.
jmp (shiftVec) ;shifts>4 are handled by a right shift routine. 5c.
BitShift:
rora
rora
rora
rora ;average 4 cycles.
sta tmp ;3c
rora ;This gives the RHS byte
and mask
eor (screenRHS),y;5.5
sta (screenRHS),y ;6c.
lda mask
eor #255; invert the mask.
and tmp
eor (screenLHS),y
sta (screenLHS),y
iny
cpy height
bcs loop ;3

Total: 2*3+3*6+5+5.5*3+2*6+8 = 65.5c/ byte, 9.5x slower than
FIGnition. Note, this will work in multicolor mode too.

In either case, FIGnition is comparable. A Commodore 64 software
sprite routine would be similar to the VIC-20 code above (though the
bitmapped mode is laid out in tiles similar to FIGnition). A BBC
Micro's bitmapped mode again is similar to a C64, but it runs at 2MHz.
An Amstrad CPC464 runs slightly faster than a Spectrum, 3.0x slower
than FIGnition. etc.

FIGnition's blts code is composed from blt, but without having to save
registers between each bitmap copied. It'll be, maybe, 10% faster than
blt for small bitmaps (currently not measured).

-cheers from julz

Mark Wills

unread,
Mar 20, 2013, 7:37:09 AM3/20/13
to fign...@googlegroups.com

VIDEO or it didn't happen! ;-)

Mark

Julian Skidmore

unread,
Mar 20, 2013, 9:05:43 AM3/20/13
to fign...@googlegroups.com
Hi Mark,

OK, I'll post one in due course! Good to see people reading this topic :-)

-cheers from julz

Stuart Taylor

unread,
Mar 20, 2013, 11:42:23 AM3/20/13
to fign...@googlegroups.com
Hi Julz,

i'm a little confused here.

So have you written a blitter in AVR firmware, that is behaving like a hardware blitter for the figgy? Or have you implemented frame buffering instructions within the forth that is the figgy?

Also, did the Spectrum and Vic have hardware blitters? I thought that kind of awesome came a long in the Amiga/Atari era.

Stuart

Julian Skidmore

unread,
Mar 20, 2013, 12:58:47 PM3/20/13
to fign...@googlegroups.com
Hi Stuart,

I'm just using the word blitter in a generic sense to mean bit block
transfer. But yes, on FIGnition's 0.9.8 firmware revision there will
be a built-in software blitter in AVR assembler that blits to a full
bitmapped frame buffer held in the top 3200 bytes of external serial
ram.

It's a real, but fairly limited blitter. It can display monochrome
bitmapped images with any number of pixels in x and y dimensions for
bitmaps up to 2688 pixels. For example, a 56 x 48 pixel bitmap or a
number of 8x8 bitmaps or 16x12 bitmaps can be blitted. Bitmaps can be
blitted to any pixel location.

Any number of bitmaps can be displayed on the frame buffer
simultaneously - obviously, since the background display routine
displays a frame buffer, it doesn't render bitmaps on the fly. To
display bitmaps they must first be copied to internal RAM; this is
what limits the blitter to bitmaps <2688 pixels. However, there's no
reason why you can't overwrite different bitmaps in internal RAM; it's
just a cache in case you want to use certain bitmaps frequently.

The blitting area can be clipped to different areas. Normally the
clipping area is (0,0) to (160,160) ,which is the whole bitmapped
frame buffer, but any rectangle coordinates are possible. The clip
rectangle allows areas to be protected from blitting (e.g. high scores
etc).

Blitting can be done in the range (-56,-56) to (160,160) so that
bitmaps can appear partially off-screen (e.g. if you want to support
wrap-around in games).

There are four basic blitter commands supported from FIGnition Forth:

* tile (which copies a bitmap in external serial RAM to internal RAM);
* blt (which blits a bitmap from a tile to the current location on the
frame buffer and advances the current location).
* 2blt (which blits two bitmaps in one go; a destination bitmap is
blitted first and then a source bitmap is blitted. It's the primary
operation for animation, where the destination bitmap is the new
position for the image and the source bitmap is the old image to be
erased).
* blts (which blits multiple copies of the same bitmap over a
rectangular area. It's really for generating backgrounds).

The blitter operation has a two transfer modes: xor which is used for
blt and 2blt. And copy, which is used for blts. With the blitter it's
now possible to display characters on the bitmapped frame buffer; at
any pixel location (as detailed in earlier posts).

I think, with these commands it should be possible to write some
decent 80s type games on a FIGnition at a decent speed. Things like:
space invaders, pacman, platform games, defender (though scrolling may
be a little slow), asteroids (using bitmaps rather than vectors). etc.

I'm comparing FIGniton's blitting with early 80s computers that didn't
have hardware blitters, but would use dedicated sprite routines.
That's because FIGnition Forth itself wouldn't really be fast enough
to do a convincing blit operation. The ZX Spectrum had a simple frame
buffer with character aligned colour and no hardware support for any
graphics operations. The VIC-20 technically only had UDGs, but by
putting the graphics chip into double-height character mode and
filling the screen with 242 sequential characters that pointed to 242
different 8x16 UDGs it was possible to simulate true bitmapped
graphics. Early Atari STs only had software blitters too, IIRC.

The blitter operations were originally proposed here:

http://oneweekwonder.blogspot.co.uk/2011/11/fignition-hires-graphics-api-rfc.html

They've been a long time coming, but they're basically finally here!
Hope this whets your appetite for more advanced FIGnition
capabilities!

-cheers from julz

carl

unread,
Mar 20, 2013, 2:32:14 PM3/20/13
to fign...@googlegroups.com
It looks to be a great advancement, and a good achievement Julz,

I would imagine that this would enable moving graphics around at two speed easier, but how would one go about collision detection?

At the moment I can ask the location just before the sprite what is value is, this looks to be slightly different and may not use +vram+ in the same way, am I right in thinking this?



On Friday, 8 February 2013 16:13:46 UTC, Julz wrote:

Stuart Taylor

unread,
Mar 20, 2013, 3:02:42 PM3/20/13
to fign...@googlegroups.com

Wow, my head asplode.

Julian Skidmore

unread,
Mar 20, 2013, 3:56:24 PM3/20/13
to fign...@googlegroups.com
Hi Stuart,

> Wow, my head asplode.

It's OK, you're safe - there's no built-in collision detection ;-)

@Carl: As per the above message. The blitter doesn't have any
collision detection built in and you can't use the same technique as
for text mode games. Instead people will have to do software collision
detection.

-cheers from julz

carl

unread,
Mar 25, 2013, 8:05:48 AM3/25/13
to fign...@googlegroups.com

Julian Skidmore

unread,
Apr 1, 2013, 12:35:52 PM4/1/13
to fign...@googlegroups.com
Hi folks,

I found a bug in the Blitter - here's a new Version 0.9.8 Candidate
(you'll need it to play Luna!)

-cheers from julz
FirmwareRev0_9_8Candidate02.zip
Reply all
Reply to author
Forward
0 new messages