[comp.sys.amiga.programmer] Block Moves Blits

dueker@xenon.arc.nasa.gov (The Code Slinger) (06/25/91)

In article <utoddl.677798586@next1.oit.unc.edu>, utoddl@next1.oit.unc.edu (Todd M. Lewis) writes...

-- Woes on attempting to figger out the Blitter deleted --

>Does anybody out there have some advice for--or working examples of--how
>to use this wonderful but woefully underdocumented chip for doing block
>moves?   Any help would be appreciated.
> 
>Thanks,
>Todd M. Lewis
>utoddl@next1.oit.unc.edu

Thomas Rokicki wrote a "Blitter laboratory" called Blitlab, and it's on
the Fish disks.  I'm not at home or I could tell you which one.  Give it
a try.  It's very good and it's written so's you can experiment in
relative safety (an important laboratory necessity).

Chris
------------------------------------------------------------------------
"Ah, Benson, you are so mercifully free of the ravages of intellegence!"
"Oh, thank you, Master!"             - from the movie, TIME BANDITS
------------------------------------------------------------------------
dueker@xenon.arc.nasa.gov        |   Chris Dueker (The Code Slinger)
duke@well.sf.ca.us               |   Mtn. View, CA  (Sillycon Valley!)

utoddl@next1.oit.unc.edu (Todd M. Lewis) (06/25/91)

I've been putting off asking this because I really wanted to figure it out
myself, but enough is enough.

I have a working program that uses BltMaskBitMapRPort() quite a lot.  Since
I'm doing the same 10 or so blits over and over I thought I could save some
time by doing the blitter register setups once at the beginning, then doing
OwnBlitter()/stuff_blit_regs()/DisownBlitter() a la BlitLab when I actually
need to blit.  The problem is I've had a devil of a time figuring out all
the details of how the blitter regs work with various shifts and ascending
and descending blit modes.  Some of them work as expected, others have
obvious problems with modulos, etc.

As an educational exercise I have undertaken to write BltMaskBitMapBitMap()
with the intent of providing a well-anotated high-level example of how
all these things interact and what must be taken into account to get
blitter moves to work.  Special case blits (like the ones in the program
I mentioned) could be easily derived from this general case example.  (At
least it would be easier than working from the hardware ref. man.)  I 
would hope it could at least save others the hours I've spent on this.

So, I'm getting tired of scratching my head and reading the same FM and
gazing at the screen trying to figure out why what should work doesn't.
Does anybody out there have some advice for--or working examples of--how
to use this wonderful but woefully underdocumented chip for doing block
moves?   Any help would be appreciated.

Thanks,
Todd M. Lewis
utoddl@next1.oit.unc.edu

spence@cbmvax.commodore.com (Spencer Shanson) (06/25/91)

In article <utoddl.677798586@next1.oit.unc.edu> utoddl@next1.oit.unc.edu (Todd M. Lewis) writes:
>
>I've been putting off asking this because I really wanted to figure it out
>myself, but enough is enough.
>
>I have a working program that uses BltMaskBitMapRPort() quite a lot.  Since
>I'm doing the same 10 or so blits over and over I thought I could save some
>time by doing the blitter register setups once at the beginning, then doing
>OwnBlitter()/stuff_blit_regs()/DisownBlitter() a la BlitLab when I actually
>need to blit.  The problem is I've had a devil of a time figuring out all


You are calling WaitBlit() before poking any blitter registers, aren't you?

>Thanks,
>Todd M. Lewis
>utoddl@next1.oit.unc.edu


-- 
---------------------------------------------------------------------------
Spencer Shanson - Amiga Software Engineer     | email: spence@commodore.COM
                                              | or uunet!cbmvax!spence
All opinions expressed are my own, and do not | Bix: sshanson
(necessarily) represent those of Commodore.   | "Copper? I hardly even
                                              | know her!"

chrisg@cbmvax.commodore.com (Chris Green) (06/25/91)

In article <utoddl.677798586@next1.oit.unc.edu> utoddl@next1.oit.unc.edu (Todd M. Lewis) writes:
>...
>I'm doing the same 10 or so blits over and over I thought I could save some
>time by doing the blitter register setups once at the beginning, then doing
>OwnBlitter()/stuff_blit_regs()/DisownBlitter() a la BlitLab when I actually
>need to blit.  The problem is I've had a devil of a time figuring out all


	You've got the sequence wrong there. You want to:

	1. OwnBlitter()
	2. calculate initial values to stuff into blit regs
	3. WaitBlit()  (call the rom one. it deals with blitter bugs, etc.)
	4. stuff initial values
	5. stuff values for next bitplane, starting blitter
	6. calculate values for next bit plane.
	7. if more blits then WaitBlit. Goto 5.
	8. DisownBlitter().

	If you disown the blitter after stuffing the initial register setups, then some
other task can get in and changes them before you do the rest of your blit. It
is not safe to assume anything about the contents of blitter registers after
an OwnBlitter().

	-- 
*-------------------------------------------*---------------------------*
|Chris Green - Graphics Software Engineer   - chrisg@commodore.COM      f
|                  Commodore-Amiga          - uunet!cbmvax!chrisg       n
|My opinions are my own, and do not         - killyouridolssonicdeath   o
|necessarily represent those of my employer.- itstheendoftheworld       r
*-------------------------------------------*---------------------------d

mykes@amiga0.SF-Bay.ORG (Mike Schwartz) (06/26/91)

In article <utoddl.677798586@next1.oit.unc.edu> utoddl@next1.oit.unc.edu (Todd M. Lewis) writes:

[ paraphrased: He wants to drive the blitter to do 
  BlitMaskBitMapRastPort() himself ]

>So, I'm getting tired of scratching my head and reading the same FM and
>gazing at the screen trying to figure out why what should work doesn't.
>Does anybody out there have some advice for--or working examples of--how
>to use this wonderful but woefully underdocumented chip for doing block
>moves?   Any help would be appreciated.
>
>Thanks,
>Todd M. Lewis
>utoddl@next1.oit.unc.edu

Get ahold of Tom Rokiki's BlitLab from the Fish disks.  It is excellent
for illustrating how the blitter works.

And, by the way, rewriting BMBMPRP() is a great idea.  It is a useful
general purpose function as is, but it is at least 100 times slower
than most software needs it to be.

--
****************************************************
* I want games that look like Shadow of the Beast  *
* but play like Leisure Suit Larry.                *
****************************************************

carolyn@cbmvax.commodore.com (Carolyn Scheppner - CATS) (06/27/91)

In article <utoddl.677798586@next1.oit.unc.edu> utoddl@next1.oit.unc.edu (Todd M. Lewis) writes:
>[]
>need to blit.  The problem is I've had a devil of a time figuring out all
>the details of how the blitter regs work with various shifts and ascending
>and descending blit modes.  Some of them work as expected, others have
>obvious problems with modulos, etc.
>[]

Do you have the 1.3 Addison Wesley Amiga Hardware Manual ?

That book includes what I call the "Lost Blitter Docs" on how
moves and modulos work.  In addition, the chapter was reworked
and edited by Mr. Blitter himself, Tom Rokicki (author of BlitLab).

-- 
==========================================================================
 Carolyn Scheppner -- Tech. Mgr. CATS - Commodore Amiga Technical Support
 PHONE 215-431-9180 {uunet,rutgers}!cbmvax!carolyn  carolyn@commodore.com

 I am fully operational and all of my circuits are funcTiOnINg pperrf...
==========================================================================

utoddl@next1.oit.unc.edu (Todd M. Lewis) (06/27/91)

Mike Schwartz writes:
>In article <utoddl.677798586@next1.oit.unc.edu> utoddl@next1.oit.unc.edu (Todd M. Lewis) writes:
>
>[ paraphrased: He wants to drive the blitter to do 
>BlitMaskBitMapRastPort() himself ]

Sorry, Mike, that's not what I said.  A side effect of what I want to do
would be the creation of the routine BltMaskBitMapBitMap(), which currently
doesn't exist.  But that's not the point.  The points are (1) to understand
all the nuances of using the blitter to do block moves, and (2) to provide
a working piece of example code which incorporates every detail that must
be dealt with when using the blitter directly, excluding perhaps dealing with 
overlapping blits and layers.

My reasons are simple and follow the two points above: (1) I'm doing lots
of blits over and over and I can make them go faster (I hope) if I precalculate
each blit and do the QBlit() tricks, which requires that I understand how
the blitter works, and (2) it would be a shame to make sense of all that
and not share it with other programmers.

Several people have pointed out to me that I left out some steps in my
thumbnail description of what I was doing.  I didn't mean to be incomplete,
but I didn't want to get bogged down at the OwnBlitter/WaitBlit/DisownBlitter
level--I want to get bogged down at a much lower level:-)

>Get ahold of Tom Rokiki's BlitLab from the Fish disks.  It is excellent
>for illustrating how the blitter works.

Thanks to all who pointed this out, though I mentioned BlitLab in the original
article.  Tom did his usual great job on that program, and I'm sure it has
saved me many hours.  I'm using ver. 1.1, BTW.  Is that the latest?

>And, by the way, rewriting BMBMPRP() is a great idea.  It is a useful
>general purpose function as is, but it is at least 100 times slower
>than most software needs it to be.

Have to disagree with you there, at least until I see some data supporting
your assertion.  BMBMPRP() has to deal with layers, and must set up the blitter
without making any assumptions about the blit.  The overhead could easily take
longer than the blit itself, especially for small (say, the size of a lemming)
blits.  My guess (I haven't looked at the code) is that BMBMPRP() is just about
as optimized as it can get and still work.

Incidentally, if I do get a working BltMaskBitMapBitMap(), I can promise you it
will be dog slow.  Why?  Because I intend to make it as clear as possible
for people to understand what is involved in blitter settup.  In fact, it should
not be used.  Just knock up a RastPort with a null Layer, set the BitMap ptr to
the right place and use BltMaskBitMapRastPort() and save yourself some time and
code size.

>****************************************************
>* I want games that look like Shadow of the Beast  *
>* but play like Leisure Suit Larry.                *
>****************************************************

I want games that play like Lemmings, but where people send me the money!

Todd (utoddl@next1.oit.unc.edu) Lewis

mykes@amiga0.SF-Bay.ORG (Mike Schwartz) (06/28/91)

In article <utoddl.678036758@next1.oit.unc.edu> utoddl@next1.oit.unc.edu (Todd M. Lewis) writes:
>
>Mike Schwartz writes:
>>In article <utoddl.677798586@next1.oit.unc.edu> utoddl@next1.oit.unc.edu (Todd M. Lewis) writes:
>>
>>[ paraphrased: He wants to drive the blitter to do 
>>BlitMaskBitMapRastPort() himself ]
>
>Sorry, Mike, that's not what I said.  A side effect of what I want to do
>would be the creation of the routine BltMaskBitMapBitMap(), which currently
>doesn't exist.  But that's not the point.  The points are (1) to understand
>all the nuances of using the blitter to do block moves, and (2) to provide
>a working piece of example code which incorporates every detail that must
>be dealt with when using the blitter directly, excluding perhaps dealing with 
>overlapping blits and layers.
>

1)	Get the SOURCE to blitlab.  It not only has code to drive the
	blitter, but it also has 'C' code that emulates the blitter.
	If you want to reinvent the wheel, go ahead.  Tom has already
	given us a great example of how to use the blitter.  Also, 
	AmigaMail contains a few examples as does the Hardware Manual.

2)	get blitlab...

>My reasons are simple and follow the two points above: (1) I'm doing lots
>of blits over and over and I can make them go faster (I hope) if I precalculate
>each blit and do the QBlit() tricks, which requires that I understand how
>the blitter works, and (2) it would be a shame to make sense of all that
>and not share it with other programmers.
>

1)	Precalculating is a good idea if you want speed, but QBlit makes
	no sense at all.  If you know the size of what you want to blit,
	it is trivial to code up REAL fast blit routines to blit specific
	sized items.  Also you might want to consider RAW blitting,
	which has been covered here a few times.

	Once you do an OwnBlitter(), you can load the values you want into
	the blitter registers and most of them stay there forever, or until
	you release the blitter (Qblit forces you to reload the blitter
	registers over and over).

2)	Your desire to share your results is commendable, and I appreciate
	it.

>Several people have pointed out to me that I left out some steps in my
>thumbnail description of what I was doing.  I didn't mean to be incomplete,
>but I didn't want to get bogged down at the OwnBlitter/WaitBlit/DisownBlitter
>level--I want to get bogged down at a much lower level:-)
>

You NEED to be complete, especially when dealing with the blitter the way
you want to.  Again, if you don't do things correctly, your code will cause
havoc to the system.  If the OS is using the blitter to scroll a window while
you are storing to the blitter registers, you are going to make the blitter
store to random memory locations - instant GURU.

Also, again, you need to do OwnBlitter() if you want to keep the blitter
registers loaded with the numbers you want.  Once you set up the blit,
you only need to store Source, Destination, and BltSize to start the next
plane blit.  Any other way, and you will have to load up to 14 registers
again and again.  You might also consider using blitter NASTY, which makes
the blitter go 2x faster.  You might also consider using the CPU instead
of the blitter if the CPU is an 030 (it is faster that way).

>>And, by the way, rewriting BMBMPRP() is a great idea.  It is a useful
>>general purpose function as is, but it is at least 100 times slower
>>than most software needs it to be.
>
>Have to disagree with you there, at least until I see some data supporting
>your assertion.  BMBMPRP() has to deal with layers, and must set up the blitter
>without making any assumptions about the blit.  The overhead could easily take
>longer than the blit itself, especially for small (say, the size of a lemming)
>blits.  My guess (I haven't looked at the code) is that BMBMPRP() is just about
>as optimized as it can get and still work.
>

BMBMRP() is slow no matter how you use it.  Try it for yourself and see.  Create
a bitmap and rastport with NO layers and it still is dog slow.  When I first started
programming the Amiga 6 years ago, a friend gave me a blit routine he wrote called
BlitBitMapPlane(), which was written in 'C'.  It took 16 input parameters on the
stack (for each plane of a blit no less) and it in turn called an internal blit
routine with another 14 parameters on the stack.  All that pushing and popping
of parameters gets multipled by 5 if you do 32 colors...  Anyhow, this terribly
inefficient 'C' code was 10 times faster than BMBMRP().  And if you really want
to know how to use the system blit routines to do BMBMRP() style blitting, 
you can do 2 BltBitMap() calls faster than a single BMBMRP() call.

>Incidentally, if I do get a working BltMaskBitMapBitMap(), I can promise you it
>will be dog slow.  Why?  Because I intend to make it as clear as possible
>for people to understand what is involved in blitter settup.  In fact, it should
>not be used.  Just knock up a RastPort with a null Layer, set the BitMap ptr to
>the right place and use BltMaskBitMapRastPort() and save yourself some time and
>code size.
>

You should explore the 2 BltBitMap() calls before you determine how dog slow
your code needs to be.  You should try 2 BltBitMapRastPort() calls as well,
which also runs real fast.  I agree you will save yourself programming time
and code size if you don't bother to try to make faster code.

>>****************************************************
>>* I want games that look like Shadow of the Beast  *
>>* but play like Leisure Suit Larry.                *
>>****************************************************
>
>I want games that play like Lemmings, but where people send me the money!
>
>Todd (utoddl@next1.oit.unc.edu) Lewis

--
****************************************************
* I want games that look like Shadow of the Beast  *
* but play like Leisure Suit Larry.                *
****************************************************

mykes@amiga0.SF-Bay.ORG (Mike Schwartz) (07/01/91)

In article <PETERM.91Jun30133541@kea.am.dsir.govt.nz> peterm@am.dsir.govt.nz (Peter McGavin) writes:
>In article <utoddl.678036758@next1.oit.unc.edu> <mykes.4002@amiga0.SF-Bay.ORG>
>Mike Schwartz writes:
>>Qblit forces you to reload the blitter registers over and over
>
>Nope.  One call to QBlit() can perform multiple blits, and you need only
>reload the registers that change for the 2nd and subsequent blits.  See
>the description of "function" on page 380 of the 1.3 L&D RKM.
>
>>Also, again, you need to do OwnBlitter() if you want to keep the blitter
>>registers loaded with the numbers you want.
>
>Again, nope (if you use QBlit() right).
>
>Furthermore, QBlit() has the advantage of not blocking your task when
>someone else already owns the blitter.  So it is easier to keep both the
>CPU and blitter busy at the same time with QBlit() than with OwnBlitter().
>--
>Peter McGavin.   (srwmpnm@wnv.dsir.govt.nz  or  peterm@am.dsir.govt.nz)

No matter what the RKM says, QBlit() doesn't perform as you indicate.  It
clearly states in my RKM that QSBlit() overrides the QBlit fifo, meaning that
your blitter registers could be trashed.  It also isn't clear from the RKM whether
someone else can do an OwnBlitter() and get the blitter in the midst of QBlitting.
In the many areas where the RKM isn't clear like this, CBM seems to indicate that
you shouldn't rely on the behavior of the OS routines...  In other words, if you
assume that the blitter registers are going to be the same as when you last
QBlitted a plane, your code might work on YOUR machine with YOUR applications,
but not on mine.

--
****************************************************
* I want games that look like Shadow of the Beast  *
* but play like Leisure Suit Larry.                *
****************************************************