[comp.sources.amiga] v91i095: CpuBlit 1.0 - speeds up blitter on a 68020/30 Amiga, Part01/02

amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator) (05/08/91)

Submitted-by: ecarroll%maths.tcd.ie@pucc.PRINCETON.EDU
Posting-number: Volume 91, Issue 095
Archive-name: utilities/cpublit-1.0/part01

[ includes uuencoded executable and icons  ...tad ]

CpuBlit replaces the system BltBitMap routine with a version that uses your
68020/68030 when it is worthwhile to do so. This results in text scrolling
twice as fast as usual, and in addition, the "colour flicker" effect normally
present when scrolling multi-coloured text is removed.

One advantage of the blitter is that while it is busy manipulating bitmaps,
the CPU can be getting on with some other work. To facilitate this, you can
tell CpuBlit to only use the CPU for blitting when it would otherwise be idle
(i.e. no tasks are ready to run). This way, you get increased speed without
affecting your Amiga's overall computing performance.

If your Amiga only has a 68000, CpuBlit probably won't be of much use other
than as a curiosity since the 68000 is slower than the blitter.

This is V1.0, which fixes all known bugs in earlier versions available from
ab20.larc.nasa.gov and bix.

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 2)."
# Contents:  CpuBlit.doc CpuBlit.uu CpuBlit0.uu History Kill_CpuBli.uu
#   src src/cpublit.c src/makefile src/res.s src/scroll.h src/small.a
#   src/system.h
# Wrapped by tadguy@ab20 on Tue May  7 19:45:25 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'CpuBlit.doc' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CpuBlit.doc'\"
else
echo shar: Extracting \"'CpuBlit.doc'\" \(14030 characters\)
sed "s/^X//" >'CpuBlit.doc' <<'END_OF_FILE'
X
X              CpuBlit V1.00 -- Uses CPU to perform blitter functions
X
X           (c) Copyright Eddy Carroll, April 1991. Freely Distributable.
X
X
XGETTING STARTED
X
X    In brief, CpuBlit makes your 68020/68030-equipped Amiga scroll text
X    about twice as fast as before. You can quickly try it out as follows.
X    Run CpuBlit (make sure you have the cache enabled). Now try Typing a
X    file in a CLI window. Look at the speed. Change the text colour to
X    colour 3. Type the file again. Look at the lack of flicker on the text
X    as it scrolls. Nice, eh?
X    
X    If you have Workbench 2.0, you can install CpuBlit permanently by
X    simply dragging its icon into your WBStartup drawer. Otherwise, you
X    need to call CpuBlit from your Startup-Sequence. I recommend using the
X    -2 or -s options for general use, though you may like to experiment
X    with the others.
X
X    Now read on for a more detailed description.
X
X
XINTRODUCTION
X
X    After upgrading from an A1000 to an A3000 a while ago, I was in Amiga
X    heaven. The display was great, the disk performance much improved, and
X    the speed awesome (at least compared to the A1000). But there was one
X    blemish on this otherwise perfect scene: the speed of text scrolling
X    in CLI windows. On a 704 x 560 screen, a snail wouldn't have much trouble
X    keeping up with a full size CLI window.
X
X    Thus was born CpuBlit. It replaces the standard system BltBitMap routine
X    with a version that uses the 68030 where practical. The 68030 can
X    comfortably outrun the blitter for simple tasks like scrolling, although
X    the blitter still wins out if the data has to be bit shifted as well
X    (for example when scrolling sideways). Another benefit of using the CPU
X    is that it isn't constrained to operating on one bitplane at a time; it
X    can do them all simultaneously. So, the infamous "flicker" effect when
X    coloured text is scrolling disappears. This is particularly useful when
X    you're logged onto a bulletin board with colour ANSI menus.
X
X    At this stage, I imagine some of you are getting ready to jump up and
X    complain about system throughput suffering, and how overall, the blitter
X    plus the CPU is faster than the CPU on its own. I certainly wouldn't
X    argue with that. So, CpuBlit can be setup to only use the CPU if no
X    other tasks are ready to use it. That way, you get improved performance
X    when you are single tasking, yet multiple tasks operate at full
X    efficiency.
X
X    There is one caveat. CpuBlit will probably only be of use to you if you
X    have at least a 68020 installed in your Amiga; using the standard 68000
X    doesn't give any noticeable speed increase. In fact, even a standard
X    68020 Amiga may not give much speed increase since it only has a 16 bit
X    datapath into chip RAM. The A3000 on the other hand can access chip ram
X    32 bits at a time and CpuBlit takes advantage of this. The easiest way to
X    find out is to give it a try and see if you notice any other difference.
X    A3000 owners will certainly notice a difference -- an A3000-25 performs
X    blits about 2.8 times faster than the blitter, which results in text
X    scrolling at about twice the normal speed (actually displaying the text
X    to be scrolled takes a constant amount of time, regardless of what method
X    you use to scroll it).
X
X    To get the best speed increase, use a non-overscanned screen of not
X    more than four colours, and ensure you have the CPU cache enabled (it
X    is disabled by default under Workbench 1.3 -- use SetCPU by Dave Haynie
X    to enable it). Both overscan and 8 or 16 colour screens will decrease
X    CpuBlit's efficiency, since the custom chips access CHIP ram more
X    frequently, leaving less time available for the CPU. Even with these
X    restrictions, you should still find CpuBlit about 50% faster than the
X    blitter on the A3000.
X
X
XUSAGE
X
X    You can start CpuBlit from either the CLI or the Workbench. There are
X    a number of parameters you can change, to alter CpuBlit's operation.
X    When you start CpuBlit, it automatically detaches itself from the CLI
X    window. Any combination of the following options can be given on the
X    command line or as Workbench ToolTypes. Note that each options has
X    two ways of specifying it. You can use whichever way you like best.
X
X    BLITMODE=ALWAYS
X    -a
X    	This is the default setting, so you normally don't need to give it
X        specifically. In this mode, CpuBlit always use the CPU where
X	possible. If you tend to only do one thing on your Amiga at a time,
X	this is probably the best option to use.
X
X    BLITMODE=ONE
X    -1
X    	In this mode, CpuBlit will only use the CPU for blits if there are
X        no other tasks ready to run at that time. The blitter is used at all
X	other times. Hence, you get fast blits whenever the CPU would be
X	otherwise idle, and normal processing speed when running multiple
X	tasks.
X
X	There is one catch. When displaying text via the console device,
X	the program displaying the text is considered to be still running,
X	even though it's the console device that actually outputs the text.
X	For those interested, this is because the console device runs at
X	a higher priority than user applications and so preempts the task
X	before it has a chance to go to sleep. Hence, CpuBlit will think the
X	program is waiting to do work, and won't use the CPU for blitting.
X
X	This means that the -1 option will only speed up scrolling when a
X	task scrolls the text directly, rather than indirectly via the
X	console device. Comms packages and text editors are the most likely
X	candidates for this. Standard CLI windows won't show any improvement.
X
X    BLITMODE=2
X    -2
X    	In this mode, CpuBlit will only use the CPU for blits if there is
X        at most one other task waiting to run. This results in everything
X	being speeded up (both applications and CLI output) but isn't quite
X	as system friendly as using -1. It should be more than adequate for
X	most people however.
X
X    BROKEN=[YES|NO]
X    -b
X    	Some programs don't initialise bitmap structures properly. By
X        default, CpuBlit passes such bitmaps on to the blitter and doesn't
X	attempt to handle them. Using this option tells CpuBlit to bypass the
X	validation checks it normally performs on bitmaps, and so may allow
X	broken programs like this to gain the benefits of faster blitting;
X	it may also cause problems. If you have a program that you think
X	should be sped up by CpuBlit and it seems to be showing no noticeable
X	change, then give this option a try; else, leave it alone.
X
X    SINGLE=[YES|NO]
X    -o
X    	This option tells CpuBlit to only handle blits where the source and
X        destination bitmaps are the same. Typically, this only happens when
X	a text window is scrolling. Normally you should not need to use this
X	option as CpuBlit should co-exist happily with every program that
X	uses the blitter. However, if CpuBlit seems to be incompatible with
X	some particular application, specifying `-o' will allow you to
X	continue using it. Don't forget to notify me about the problem, so
X	that it can be fixed! 
X
X    MINTASKPRI=N
X    -pN
X    	If you like to keep a program running in the background (like a
X	Mandelbrot generator) then you may find it counteracts the -1 and -2
X	options (since it is always ready to run). You can tell CpuBlit
X	to ignore all such tasks using this option; any task with a priority
X	less than N will not be considered ready to run.
X	
X	Normally, CpuBlit will ignore any tasks with a priority less than
X	zero, which is perfectly adequate for most cases. You can override
X	this with a different setting if you like. For example, setting
X	MINTASKPRI=-5 will cause your Mandelbrot program at priority -1 to
X	be considered, but not your CPU monitor at priority -20.
X
X    BLITMODE=SHARE
X    -s
X    	In this mode, CpuBlit attempts to share blits between the CPU and the
X	blitter. The CPU will be used for blits by default, but if a task
X	tries to blit some data while another task is already using the CPU
X	to blit data, the blitter is used for the former. The result is
X	better overall throughput.
X	
X	If you try experimenting with two CLI windows to see this effect in
X	action, you won't notice anything; this is because the console.device
X	used for scrolling CLI windows is single threaded and waits for a
X	blit in one window to finish before starting another. Hence, both
X	windows are scrolled using the CPU. It works fine in the case of
X	a CLI window and a program that bypasses the console device (such as
X	a comms package).
X
X    HELP
X    -h
X    	Prints out a brief help message, listing the valid options. In fact,
X        giving any invalid option will cause this message to be printed.
X
X    QUIT
X    -q
X    	This option asks any copy of CpuBlit already installed to remove
X        itself. If another program has patched BltBitMap since CpuBlit was
X	started, you'll get a message asking you to terminate that program
X	and then try again.
X
X    If you run CpuBlit with no options, it behaves as if you had typed:
X
X    	CPUBLIT  BLITMODE=ALWAYS  SINGLE=NO  BROKEN=NO  MINTASKPRI=0
X
X    You can pick a different mode of operation at any time by simply running
X    CpuBlit again with new options; it's not necessary to remove the previous
X    copy first. You can use -a to cancel the effect of the -b and -o options.
X    Note that only one of -a, -1, -2 and -s can be in effect at a time. Also,
X    the BROKEN and SINGLE options default to YES if you use them without
X    specifying a YES/NO value.
X
X
XWORKBENCH
X
X    As mentioned above, CpuBlit can be started from Workbench. It doesn't
X    return to Workbench until it quits, so if you are starting it from your
X    WBStartup drawer (under 2.0) one of the tooltypes must be DONOTWAIT.
X    in the icon.
X
X    When CpuBlit starts up, it parses all the ToolTypes in its own icon,
X    followed by the tooltypes in any project icons you specified. This
X    can be handy if you have several configurations of CpuBlit that you
X    like to switch between. Simply create a project icon for each one,
X    and set the appropriate tooltypes. Then set the default tool for each
X    icon to CpuBlit. Now, clicking on any of the icons will set the
X    corresponding CpuBlit options.
X
X    To remove CpuBlit from Workbench, you need to start it from an icon
X    which has a QUIT tooltype. The standard CpuBlit distribution includes
X    such an icon that you can use. If CpuBlit cannot remove itself (perhaps
X    because someone else has patched into the BltBitMap routine ahead of
X    CpuBlit) then the screen will flash. You can type CpuBlit QUIT in
X    a CLI window for a more detailed explanation.
X
X
XIMPLEMENTATION
X
X    This section gives a brief description of how CpuBlit works. It's not
X    necessary to read this to use CpuBlit, it's included merely for those
X    interested.
X
X    CpuBlit only handles blits with a very specific set of characteristics.
X    First of all, the source and destination bitmaps must be aligned on the
X    same bit boundary within a longword. For example, a blit from 0,0 to
X    128,100 would be okay whereas a blit from 0,0 to 100,100 would fail.
X    In addition, only blitter functions of the form $Cx are supported
X    (i.e. plain replace operation). Also, the source and destination rows
X    must be different; if they are the same, a sideways blit is being
X    performed, and this is not supported.
X
X    Assuming the blit fulfills all these criteria, CpuBlit then checks
X    system activity to see whether or not it is appropriate to use the
X    CPU at all. Exactly what is checked depends on the option selected
X    when CpuBlit was installed.
X
X    Assuming everything is still okay, CpuBlit then works out how many
X    bitplanes there are in the bitmap, and calls one of four routines to
X    handle the actual scrolling. It also handles any bitplane pointers of
X    $FFFFFFFF or $00000000 at this time (new for Workbench 2.0, these
X    values are legal for bitplane pointers, and act as if they pointed to
X    either a solid or empty bitplane). If there are more than four
X    bitplanes, the blit is split into two operations; the first four planes
X    are moved, followed by the remaining planes. While this results in a
X    bit of colour flicker for deep bitmaps, it is still not as bad as when
X    the bitplanes are moved separately.
X
X    The actual bitmap copying is done using optimised 68000 code. The bulk
X    of the data on each row is copied using a MOVE.L/DBF loop, and the uneven
X    bits at the sides are copied separately. No non-68000 instructions are
X    used (there wouldn't be any advantage to it anyway) so CpuBlit will still
X    run on a 68000 Amiga (not that there's much point). Due to a lack of
X    CPU registers (only 16 ... how DO people manage on Intel chips with a
X    mere 8 registers? :-) the routines for copying three and four bitplanes
X    aren't quite as efficient as those for copying one and two bitplanes.
X    However, they are still quite a bit faster than the blitter itself, and
X    the removal of colour flicker is more than worth the small loss in speed.
X
X
XACKNOWLEDGEMENTS
X
X    Thanks to Andy Mowatt for encouraging me to change CpuBlit from an idea
X    into a program. Thanks also to the following people who provided useful
X    feedback and bug reports for beta versions of CpuBlit: Steve Tibbett,
X    David Joiner, Mike Sinz, Dan Ten Ton, Robert Jenks, LeRoy Hutzenbiler,
X    Jim Biggs, Mike Meyer, Urban Mueller, Jamie Clark, Marc Jacobs and
X    Albert-Jan Brouwer. Their help is greatly appreciated.
X
X
XAUTHOR
X
X    Eddy Carroll
X
X    Email:     ecarroll@maths.tcd.ie
X    Phone:     +353-1-287-4540
X    Snailmail: The Old Rectory, Delgany, Co. Wicklow, Ireland.
X
X
XDISTRIBUTION
X
X    CpuBlit may be freely distributed, as long as no charge is made other
X    than to cover time and copying costs. If you want to include CpuBlit
X    as part of a commercial package, contact the author listed above. Fred
X    Fish is specifically given permission to include CpuBlit in his fine
X    disk library.
END_OF_FILE
if test 14030 -ne `wc -c <'CpuBlit.doc'`; then
    echo shar: \"'CpuBlit.doc'\" unpacked with wrong size!
fi
# end of 'CpuBlit.doc'
fi
if test -f 'CpuBlit.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CpuBlit.uu'\"
else
echo shar: Extracting \"'CpuBlit.uu'\" \(10162 characters\)
sed "s/^X//" >'CpuBlit.uu' <<'END_OF_FILE'
Xbegin 666 CpuBlit
XM```#\P`````````"``````````$```7&```!)@```^D```7&2.=^_DOO`#0D?
XM2"0`2?D`````+'@`!"E.`!`I3P`8(`V0K0`$!H````"`*4``!$/L`"AP`$ZN1
XM_=@I0``<9P`!%"9N`11*JP"L9AY!ZP!<3J[^@$'K`%Q.KOZ,*4``)"\`<``O/
XM`&```,X@:P"LT<C1R")H`!#3R=/)(`)R`!(9*4D`(-"!4H!"9U*``D#__I_`V
XM58!"=P@`(`)3@-2!'[(``"``4X)1R/_V(`)"-R``4X(?L2``(`!1RO_X0_<`@
XM`21/G_P```&0)D\NBD7O``1T`6$T91)G^D'I__]A'&$H9OQ"*?__8.H@26$."
XM81ID_$(I__]A$F;\9]@DR%)"#$(`9&,B<&Y@5!`99R8,```B9Q8,```@9PH,K
XM```)9P0,```*`CP`'DYU`#P``0(\`/M.=2\++P)'^0``!%AR`"`\````$&`"I
XM)L%1R/_\3KH')G``8`AP9&`$("\`!"\`+'@`!")L`!Q.KOYB2JP`)&<0+&P`9
XM$$ZN_WPB;``D3J[^AB`?+FP`&$S??WY.=0``+P<N+P`(("P$B&<(+P!.NA1\^
XM6$\O!TZZ_[)83RX?3G4M80``+3$``"TR```M<P``+6(``"UO```M<0``+7``>
XM`$),251-3T1%``!!3%=!65,``$].10!45T\`4TA!4D4`0E)/2T5.``!.3P``.
XM4TE.1TQ%``!-24Y405-+4%))``!154E4``!#<'5";&ET(%8Q+C`P`&=R87!H!
XM:6-S+FQI8G)A<GD``$-P=4)L:70Z(&-O=6QD;B=T(&-R96%T92!L;V-A;"!M;
XM97-S86=E('!O<G0N"@!I8V]N+FQI8G)A<GD``&EN='5I=&EO;BYL:6)R87)YG
XM`$-P=4)L:70@<F5M;W9E9"!S=6-C97-S9G5L;'DN"@``0V]U;&1N)W0@<F5MF
XM;W9E($-P=4)L:70[('-O;65O;F4@96QS92!H87,@<&%T8VAE9"!";'1":71-Z
XM87`N(%!L96%S92!R96UO=F4*86YY(&]T:&5R('5T:6QI=&EE<R!Y;W4@:&%V3
XM92!I;G-T86QL960@86YD('1H96X@=')Y(&%G86EN+@H``$-P=4)L:70@:&%S-
XM;B=T(&)E96X@:6YS=&%L;&5D('EE="X*`$-O=6QD;B=T('-P87=N(&)A8VMGN
XM<F]U;F0@0W!U0FQI="!T87-K+@H``$-P=4)L:70@5C$N,#`@J2`Q.3DQ($5DT
XM9'D@0V%R<F]L;"X*`"\+)F\`""`3Y8!![`,B*7`(``-$*6L`!`-(*6L`"`-,[
XM&6L`#`-0)E].=4Y5__A(YP`P)FT`"$AX``)(>OW6+PM.NA%<3^\`#$J`9A)P!
XM`"E``S(I0`,V*4`#.F```L!(>``"2'K]LB\+3KH1-$_O``Q*@&8*<`$I0`,R5
XM8``"H$AX``)(>OV6+PM.NA$43^\`#$J`9@IP`BE``S)@``*`2'@``DAZ_7HO@
XM"TZZ$/1/[P`,2H!F"G`#*4`#,F```F!(>``"2'K]7B\+3KH0U$_O``Q*@&8*W
XM<`$I0`,Z8``"0$AX``)(>OU"+PM.NA"T3^\`#$J`9@IP`2E``S9@``(@2'@`;
XM`DAZ_28O"TZZ$)1/[P`,2H!F"G`!*4`$C&```@!(>``"2'K]"B\+3KH0=$_OL
XM``Q*@&8:2BL``F<40>L``B\(3KH2#%A/&4`#/F```=!(>``(2'K\WB\+3KH0[
XM1$_O``Q*@&8``)Q%ZP`(($I2BDH09P``B$H29P``@DAX``9(>OR\+PI.NA`8/
XM3^\`#$J`9@A"K`,R8``!ADAX``-(>ORF+PI.N@_Z3^\`#$J`9@IP`2E``S)@P
XM``%F2'@``TAZ_(HO"DZZ#]I/[P`,2H!F"G`"*4`#,F```49(>``%2'K\;B\*!
XM3KH/ND_O``Q*@&8``2YP`RE``S)@``$D<`!@``$@2'@`!DAZ_$PO"TZZ#Y)/#
XM[P`,2H!F1D'K``8O2``(*TC__%*(2.T!`/_\(&\`"$H09R!(>``"2'K\(B\M1
XM__Q.N@]>3^\`#$J`9@A"K`,Z8```S'`!*4`#.F```,)(>``&2'K[_"\+3KH/2
XM-D_O``Q*@&9"0>L`!B](``@K2/_\4HA([0$`__P@;P`(2A!G'DAX``)(>OO&7
XM+RW__$ZZ#P)/[P`,2H!F!D*L`S9@<'`!*4`#-F!H2'@`"DAZ^ZPO"TZZ#MY/R
XM[P`,2H!F,$'K``HO2``(*TC__%*(*TC__")O``A*$6<22A!G#B\(3KH08EA/:
XM&4`#/F`F<`!@)$AX``1(>OMR+PM.N@Z83^\`#$J`9@AP`2E`!(Q@!'``8`)P!
XM`4S?#`!.74YU2.<`,B9O`!`@;``0,"@`%'(DL$%E#")++'@`!$ZN_GI@."QXQ
XM``1.KO]\(&P`$"1H`8@@"F<:("H`"F<0($`B2Q`8L!EF!DH`9O9G!"128.(L!
XM>``$3J[_=B`*3-],`$YU3E7_\$CG`3)^`47Z!(Q"ITAZ^N!.N@\B4$\F0"`+!
XM9P`!*D/Z^MQP`"QX``1.KOW8*4`$6$J`9P`!$B)`,'S_XDWZ!%P@#BQX``1.1
XMKOY<)(`@2RQX``1.KOZ`($LL>``$3J[^C"E`!(1*@&<``*@@0"`H`!A*@&<,9
XM4X!G'E.`9SI@``""<`U![`,R+&P$A")N`!02V%'(__Q@:G`-(FP$A"!I`!1#,
XM[`,R$MA1R/_\2&P#,F$`^\983V!*+'@`!$ZN_WPB;`18,'S_XB`23J[^7"M`$
XM__!!^@/(L<!F#GX`<@$@;`2$(4$`'&`6(FP$6#!\_^).KOY<<`(@;`2$(4``'
XM'$ZN_W8B;`2$+'@`!$ZN_H9@`/](2H=F`/\X+PM.N@W:6$]!^@-H*4@#1'#_]
XML*P#0&<,<@HL;``<3J[_.F#L(FP$6"QX``1.KOYB3-],@$Y=3G5.5?_@2.<W^
XM,BXM``@F;0`,2H=7P$0`2(!(P"E`!)!(>OF`80#^*EA/)$`@"F=T<`$I0`24S
XM0J="ITZZ#:Q03RE`!(AF+DJL!)!F'BQL`!Q.KO_$<BTO00`D(@!!^OED)`@F[
XM+P`D3J[_T$AX``IA`/BL6$\I;`2(!')"K`1\0>P#,BE(!'@@2D/L!&0L>``$1
XM3J[^DB!L!(A.KOZ`(&P$B$ZN_HQ*K`209P``LB!L`"0K:``D__1#^ODX<``L#
XM>``$3J[]V"E`!&!F"DAX``5A`/A,6$]\`"!L`"2\J``<;&X@;?_T(!!G7B!H>
XM``1*$&=6(@`L;``<3J[_@BH`(&W_]"!H``0L;`1@3J[_LBM`__!G'B!`*V@`?
XM-O_L(&W_["`09PXO`&$`^BY83UBM_^Q@ZB!M__`L;`1@3J[_IB(%+&P`'$ZN'
XM_X)2AE"M__1@B")L!&`L>``$3J[^8F!*?`&\AVQ$(`;E@"\S"`!A`/GH6$]*I
XM@&8N+&P`'$ZN_\1![``T(DA*&6;\4XF3R"(`)@E![``T)`A.KO_02'@`!6$`=
XM]WY83U*&8+A*K`249P``SDJL!(QG"'`"*4`$?&`&<`$I0`1\($I#[`1D+'@`$
XM!$ZN_I(@;`2(3J[^@"!L!(A.KOZ,2JP$D&<L<`*PK`2`9B1#^O@.<`!.KOW8]
XM*4`$7$J`9Q(L0)'(3J[_H").+'@`!$ZN_F)*K`209EIP`;"L!(!F("QL`!Q.#
XMKO_$<AXO00`D(@!!^O?>)`@F+P`D3J[_T&`R<`*PK`2`9BHL;``<3J[_Q')#3
XMTH$O00`D(@!!^O?4)`@F+P`D3J[_T$AX``5A`/:N6$]"IV$`]J983TJL!(QGJ
XM+DJL!)!F'BQL`!Q.KO_$<B,O00`D(@!!^O@@)`@F+P`D3J[_T$AX``5A`/9R+
XM6$](;`,R80#X=EA/2JP$D&<&80#[\&!B2'@/H$AZ^^9(>``%2'KVT$ZZ"5)/<
XM[P`02H!F*"QL`!Q.KO_$<B@O00`D(@!!^O?J)`@F+P`D3J[_T$AX``IA`/88?
XM6$\L;``<3J[_Q'(C+T$`)"(`0?KW["0()B\`)$ZN_]!"IV$`]?),[4SL_\!.B
XM74YU```P'\V(S8A3N0```T`L'T[Y```+O$YU2D1G^K/(9@:V06?L8`A*N0``/
XM`TAFXB\&`@8`\`P&`,!FU"P`M88"!@`?9LI*N0```TQF&$HH``1FO$IH``9F0
XMMDHI``1FL$II``9FJE*Y```#0,V(('D```-$3M#-B"PY```#0&:*8%8@>0``I
XM`!!!Z`&6L>@`"&=$/P`@4"!0$"@`"2!0S8A*AF<*L#D```-0;`#_6#`?8"8@V
XM>0```!!!Z`&6L>@`"&<4(%`P:``(S8B\.0```U!L`/\X8`+-B$CG??Y.KO\<M
XM2,!(P4C"2,-(Q$C%MD%B```P/"@``$C&)$;#QBP`YHX"!@#\TH8H03PI``!(_
XMQB9&Q\8L`N:.`@8`_-:&*D-@.-*%4X$\*```2,;#QD2&)$8L`.:.`@8`_-*&<
XM*$'6A5.#/"D``$C&Q\9$AB9&+`+FC@(&`/S6ABI#`D``']B`(@0"00`?ZHS2(
XM@=*!9@)3A$WZ!P(D-A``T(#0@$WZ!G8B-@``?``<*``%O"D`!64$'"D`!5.&#
XM(`12@-"`T("5P)?`Q4S'35.$)@0@!4'H``A#Z0`(*`@J"2XO`!1/[__`+$\_]
XM!WX`XM=D+E)'($0B12@0*A%&A6<``*!&A6<``)I&A&<``)Q&A&<``*3)B,N),
XMT<K3RRS(+,E8A%B%4<[_R%2/G<\L#N*.649J"$_O`$!@``"*#$8`#&(8)@-J>
XM!L*"4$901BQ[:#).ED_O`$!@``!L)@-J",*"80`$MF`(80`"G`1&`!!/[P`@^
XM+'MH#$Z63^\`(&```$8```Y.```.O@``#VX``!!^```1S@``$?H``!(V```2Z
XMDLF(RXE@`/]ZR8C+B=/+80`$U&``_VS)B,N)T\MA``408`#_7B`'4[D```-`#
XM3-]_OBP?3G5(Y__"3>\`,"!>(EY3@"@!1H0J`D:%4X-K```P+!C,@2X1SH2.N
XMAB+'+`,BV%'.__PL&,R"+A'.A8Z&(L?1S-/-4<C_VDS?0_].=2P8S($N$<Z$4
XMCH8BQRP8S((N$<Z%CH8BQ]',T\U1R/_B3-]#_TYU2.?_\DWO`#A,U@\`4X`H%
XM`4:$*@)&A5.#:P``5"P8S($N$<Z$CH8BQRP:S($N$\Z$CH8FQRP#(MA1SO_\@
XM+`,FVE'.__PL&,R"+A'.A8Z&(L<L&LR"+A/.A8Z&)L?1S-/-U<S7S5'(_[9,O
XMWT__3G4L&,R!+A'.A(Z&(L<L&,R"+A'.A8Z&(L<L&LR!+A/.A(Z&)L<L&LR"K
XM+A/.A8Z&)L?1S-/-U<S7S5'(_\9,WT__3G5(Y__R3>\`.$S>#P!3@"@!1H0JN
XM`D:%4X-K``"(+!C,@2X1SH2.AB+'+!K,@2X3SH2.AB;'+`,BV%'.__PL`R;:.
XM4<[__"P8S((N$<Z%CH8BQRP:S((N$\Z%CH8FQ]',T\W5S-?-+PLO"B1>)E8L#
XM&LR!+A/.A(Z&)L<L`R;:4<[__"P:S((N$\Z%CH8FQ]7,U\TLBRT*)%\F7U'(!
XM_X),WT__3G4L&,R!+A'.A(Z&(L<L&,R"+A'.A8Z&(L<L&LR!+A/.A(Z&)L<L0
XM&LR"+A/.A8Z&)L?1S-/-U<S7S2\++PHD7B96+!K,@2X3SH2.AB;'+!K,@BX3L
XMSH6.AB;'U<S7S2R++0HD7R9?4<C_FDS?3_].=4CG__)-[P`X3-X/`%.`*`%&,
XMA"H"1H53@VL``*PL&,R!+A'.A(Z&(L<L&LR!+A/.A(Z&)L<L`R+84<[__"P#@
XM)MI1SO_\+!C,@BX1SH6.AB+'+!K,@BX3SH6.AB;'T<S3S=7,U\U(YP#P3-8/V
XM`"P8S($N$<Z$CH8BQRP:S($N$\Z$CH8FQRP#(MA1SO_\+`,FVE'.__PL&,R"D
XM+A'.A8Z&(L<L&LR"+A/.A8Z&)L?1S-/-U<S7S4C6#P!,WP\`4<C_7DS?3_].>
XM=2P8S($N$<Z$CH8BQRP8S((N$<Z%CH8BQRP:S($N$\Z$CH8FQRP:S((N$\Z%$
XMCH8FQ]',T\W5S-?-2.<`\$S6#P`L&,R!+A'.A(Z&(L<L&,R"+A'.A8Z&(L<L_
XM&LR!+A/.A(Z&)L<L&LR"+A/.A8Z&)L?1S-/-U<S7S4C6#P!,WP\`4<C_?DS?.
XM3_].=4CG^,)-[P`D(%XB5E.`)`%&@B88QH$H$<B"B(,BQ-',T\U1R/_N3-]#Z
XM'TYU2.?X\DWO`"Q,W@\`4X`D`4:")AC&@2@1R(*(@R+$)AK&@2@3R(*(@R;$6
XMT<S3S=7,U\U1R/_>3-]/'TYU2.?X\DWO`"Q,W@\`4X`D`4:")AC&@2@1R(*(>
XM@R+$)AK&@2@3R(*(@R;$T<S3S=7,U\TO"2\((%XB5B88QH$H$<B"B(,BQ-',G
XMT\TLB2T((%\B7U'(_[Y,WT\?3G5(Y_CR3>\`+$S>#P!3@"0!1H(F&,:!*!'(\
XM@HB#(L0F&L:!*!/(@HB#)L31S-/-U<S7S4CG`/!,U@\`)AC&@2@1R(*(@R+$_
XM)AK&@2@3R(*(@R;$T<S3S=7,U\U(U@\`3-\/`%'(_ZY,WT\?3G5(YY-`?O]3>
XM@"8#:RQ30VL8@YDL`R+'4<[__(69T\U1R/_P3-\"R4YU@YF%F=/-4<C_^$S?[
XM`LE.=2P!S(*-F=/-4<C_^DS?`LE.=4CG\T!&@4:"?@!3@"8#:RQ30VL8PYDL]
XM`R+'4<[__,69T\U1R/_P3-\"STYUPYG%F=/-4<C_^$S?`L].=2P!C(+-F=/-U
XM4<C_^DS?`L].=?____]_____/____Q____\/____!____P/___\!____`/__M
XM_P!___\`/___`!___P`/__\`!___``/__P`!__\``/__``!__P``/_\``!__`
XM```/_P``!_\```/_```!_P```/\```!_````/P```!\````/````!P````,`+
XM```!_____X````#`````X````/````#X````_````/X```#_````_X```/_`\
XM``#_X```__```/_X``#__```__X``/__``#__X``___``/__X`#___``___XY
XM`/___`#___X`____`/___X#____`____X/____#____X_____/____X``$CG/
XM.#(L>``$<@!P)$ZN_SI*@&<``&PF0)/)3J[^VB1`(&H`K-'(T<@G:``\``1"=
XMJ``\)KP````D1>L`""QY````'#3\*'PDS#3\3KDD[P`D-/PL?"3.1^L`!"8+&
XMY(LT_"(\),,D_$[N_V0B+P`<)"\`("@O`"A.KO]V3-],'$YU<'A.^0```58@O
XM+P`$#```86T*#```>FX$!```($YU``!.5?_\2.<#,"9O`!PD;P`@+B\`)$J'L
XM9S9*$V<R2A)G+G``$!LO`$ZZ_\!R`!(:+H$O0``43KK_LEA/(B\`$)*`+`%*O
XMAF<$(`9@&E.'8,9*AV<02A-G!'`!8`I*$F<$</]@`G``3-\,P$Y=3G4O"R9OX
XM``AP`!`30>P#50@P``,(`&<$4HM@["`+)E].=0```````'!A(&\`!")(<@!P:
XM`"\"#!``*V<&#!``+68"4D@0&`0``#!M$@P```EN#"0!Y8'2@M*!TH!@Y@P1!
XM`"UF`D2!)!\@"%.`(&\`"""!D(E.=4CG`!(F;P`,2JL`"F<*(DLL>``$3J[^-
XMF!=\`/\`"'#_)T``%'``$"L`#RQX``1.KOZP(DMP(DZN_RY,WT@`3G5(YP,RJ
XM)F\`&"XO`!QP_RQX``1.KOZV?``<`'#_O(!F!'``8&9P(B(\``$``4ZN_SHD;
XM0"`*9@@@!DZN_K!@2B5+``H@!Q5```D5?``$``A"*@`.(`850``/D\E.KO[:B
XM)4``$"`+9P@B2DZN_IY@&D'J`!@E2``40>H`%"5(`!Q"J@`8%7P``@`@(`I,&
XMWTS`3G5.5?_\+PLF;0`((`MF!'``8!8O"TZZ_J8F0$AM__PO"TZZ_L(@+?_\B
XM)FW_^$Y=3G4```/L````"@```````!4<```.%@``#A(```X.```."@``#@8`N
XM``X"```-_@``#?H```NX````#@````$``!36```,6```#"@```Y"```,<```"
XM#$H```P>```,%```#`P```OL```+S@``"[````$V````#@````````/R```#`
XMZ@```18`````````````````````````````````````````````````````!
XM9&]S+FQI8G)A<GD`0W!U0FQI="!6,2XP,""I($5D9'D@0V%R<F]L;"P@07!R>
XM(#$Y.3$N(%)E<&QA8V5S(&)L:71T97(@=VET:"`V.#`R,"\V.#`S,"X*57-A4
XM9V4Z($-P=4)L:70@>V]P=&EO;G-]('P@>VME>7=O<F1S?0H*3W!T:6]N<SH*M
XM("`@("UA("`@($%L=V%Y<R!U<V4@0U!5('1O(&1O(&)L:71S("AD969A=6QT5
XM('-E='1I;F<I"B`@("`M,2`@("!5<V4@0U!5(&9O<B!B;&ET<R!U;FQE<W,@C
XM86YO=&AE<B!T87-K(&ES(')E861Y('1O(')U;@H@("`@+3(@("`@57-E($-0V
XM52!F;W(@8FQI=',@=6YL97-S(&UO<F4@=&AA;B!O;F4@=&%S:R!I<R!R96%D_
XM>2!T;R!R=6X*("`@("UB("`@(%5S92!#4%4@979E;B!I9B!B:71M87`@:7-N#
XM)W0@:6YI=&EA;&ES960@8V]R<F5C=&QY"B`@("`M;R`@("!5<V4@0U!5(&]N9
XM;'D@=VAE;B!A('-I;F=L92!B:71M87`@:7,@:6YV;VQV960*("`@("US("`@$
XM(%5S92!#4%4@9F]R(&)L:71S('5N;&5S<R!A(&)L:70@:7,@86QR96%D>2!I'
XM;B!P<F]G<F5S<PH@("`@+7!.("`@26=N;W)E('1A<VMS('=I=&@@<')I;W)I3
XM='D@/"!.("AD969A=6QT('-E='1I;F<@:7,@,"D*("`@("UQ("`@(%)E;6]VH
XM92!#<'5";&ET(&9R;VT@=&AE('-Y<W1E;0H*2V5Y=V]R9',Z($),251-3T1%(
XM/5M!3%=!65-\3TY%?%173WQ32$%215T@0E)/2T5.(%-)3D=,12!-24Y405-+#
XM4%))/6X@455)5`H*4V5E('1H92!D;V-U;65N=&%T:6]N(&9O<B!D971A:6QS2
XM(&%B;W5T('-T87)T:6YG($-P=4)L:70@9G)O;2!7;W)K8F5N8V@N"@`````,U
XM>@``#%8```PF```,&@``````````````````_____P``#'H`````````````V
XM````("`@("`@("`@*"@H*"@@("`@("`@("`@("`@("`@("!($!`0$!`0$!`0`
XM$!`0$!`0A(2$A(2$A(2$A!`0$!`0$!"!@8&!@8$!`0$!`0$!`0$!`0$!`0$!.
XM`0$!`1`0$!`0$(*"@H*"@@("`@("`@("`@("`@("`@("`@("$!`0$"`@("`@X
XM("`@("`H*"@H*"`@("`@("`@("`@("`@("`@($@0$!`0$!`0$!`0$!`0$!"$D
XMA(2$A(2$A(2$$!`0$!`0$(&!@8&!@0$!`0$!`0$!`0$!`0$!`0$!`0$!$!`0>
XM$!`0@H*"@H*"`@("`@("`@("`@("`@("`@("`@(0$!`0(````````^P````%X
X@`````````T0```,N```#*@```R8```,B`````````_(0X
X``
Xend
Xsize 7232
END_OF_FILE
if test 10162 -ne `wc -c <'CpuBlit.uu'`; then
    echo shar: \"'CpuBlit.uu'\" unpacked with wrong size!
fi
# end of 'CpuBlit.uu'
fi
if test -f 'CpuBlit0.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'CpuBlit0.uu'\"
else
echo shar: Extracting \"'CpuBlit0.uu'\" \(795 characters\)
sed "s/^X//" >'CpuBlit0.uu' <<'END_OF_FILE'
Xbegin 666 CpuBlit.info
XMXQ```0``````&P`C`#H`%P`%``,``0?`Z6``````````````````````````<
XM```!`U(`````!\#I>````!<````1`````````````!`````````Z`!8``@`"*
XM:7`#````````````````0`````````#```"``````,```8``````P``!P```>
XM``#```'``````,```(``````P`````````#``````````,``#```````P`$`.
XM``````#``````````,``````````P`````````#``````````,``````/_X`]
XMP`````'__\#`````\___\,````&____XP````?_'\?S``````````,!_____&
XM____P/________^`P`&```````#!`\```````,'#X```````P?/@`!P```#`/
XM^^``/@```,`_P``>````P`^``^P```#`'^`_^````,!S\?_\^```P?______]
XM``#`?__]_^?``,`'__[^````P`/__`````#`#_?@`````,`_```7=```P/@`)
XM`*JJ@`#````#=W=@`,```$*JJK``P````7U?0`#`````>`<``(``````````'
XM````&````!1!551(3U(]161D>2!#87)R;VQL`````!!"3$E434]$13U!;'=A3
XM>7,`````"E-)3D=,13U.;P`````*0E)/2T5./4YO``````I$3TY/5%=!250`Z
X``
Xend
Xsize 540
END_OF_FILE
if test 795 -ne `wc -c <'CpuBlit0.uu'`; then
    echo shar: \"'CpuBlit0.uu'\" unpacked with wrong size!
fi
# end of 'CpuBlit0.uu'
fi
if test -f 'History' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'History'\"
else
echo shar: Extracting \"'History'\" \(2257 characters\)
sed "s/^X//" >'History' <<'END_OF_FILE'
XHISTORY
X
X
X    Version 1.00, 20 Apr 1991
X
X    	First release to the public. (No changes since V0.98.)
X
X
X    Version 0.98, 10 Apr 1991
X
X	Added Workbench support and ReadArgs-style command line arguments.
X	Also added MinTaskPri option to allow CpuBlit to ignore background
X	tasks when deciding whether it should do a blit or not. If running
X	under 1.3, CpuBlit uses its own version of FindPort() instead of
X	Exec's version which causes Enforcer hits on an A3000. No bugs
X	reported since V0.97, so it looks like the blit code itself is
X	pretty stable now (famous last words).
X
X
X    Version 0.97, 17 Feb 1991
X
X	Fixed bug in handling blits which had a negative Y offset.
X	Previously, the negative Y offset got changed into a large positive
X	Y offset; if this was the destination offset, random memory could
X	get trashed. Now works fine with Shanghai.
X
X
X    Version 0.96, 14 Feb 1991
X
X	Fixed bug in handling of single plane bitmaps. Added check to ensure
X	blits with zero width don't cause surprising results. Modified
X	command line parsing to handle multiple arguments, since the
X	various parameters are no longer all mutually exclusive. Tidied up
X	source a little.
X
X
X    Version 0.95, 9 Feb 1991
X
X	Now handles being run from a disk with a space in its name properly
X	(for example "RAM DISK:CpuBlit"). Previously, everything after the
X	space got treated as a command line option. Also added some checks
X	to ensure upwards compatibility with future Amigas.
X
X
X    Version 0.93, 7 Feb 1991
X
X	Bug in the handling of Workbench 2.0 $00000000 and $FFFFFFFF bitplane
X	pointers is now fixed. Since Workbench 2.0 uses these for gadgetry
X	etc, this was causing quite a few problems under 2.0. Also fixed a
X	small nasty bug that arrived with CpuBlit 0.92.
X
X
X    Version 0.92, 6 Feb 1991
X
X	Now correctly handles the case where the source and destination
X	bitmaps do not have equal numbers of bitplanes. Also fixed problem
X	where CpuBlit was (incorrectly) intercepting blits with minterms of
X	$D0, $E0 or $F0.
X
X
X    Version 0.91, 5 Feb 1991
X
X	Added `-o' option to help track down the source of CpuBlit
X	incompatibilities.
X
X
X    Version 0.90, 3 Feb 1991
X
X	Initial release. Currently thought to be bug free, but undoubtedly
X	this will change once users get their hands on it :-)
END_OF_FILE
if test 2257 -ne `wc -c <'History'`; then
    echo shar: \"'History'\" unpacked with wrong size!
fi
# end of 'History'
fi
if test -f 'Kill_CpuBli.uu' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Kill_CpuBli.uu'\"
else
echo shar: Extracting \"'Kill_CpuBli.uu'\" \(713 characters\)
sed "s/^X//" >'Kill_CpuBli.uu' <<'END_OF_FILE'
Xbegin 666 Kill_CpuBlit.info
XMXQ```0``````?``C`#H`%P`$``,``0?`*0@`````````````````````````D
XM```!!%('P".@!\`IH````'@````1`````````````!`````````Z`!8``@`">
XM:!`#````````````````0`````````#```"`_^```,```8\`'@``P``!\``!Z
XMP`#```'\``!P`,```X<``!@`P``&`<``#`#```8`<``,`,``#``<``8`P`$,?
XM``<`!@#```P``<`&`,``!@``<`P`P``&```<#`#```,```<8`,```<``/_X`P
XMP```<`'__\#````/\___\,````'____XP````?_'\?S``````````,!_____%
XM____P/________^`P`&```````#!`\```````,'#X```````P?.``!P```#`O
XM^@``/@```,`\P``>````P`F``^P```#`&>`/^````,!S\>/\^```P?/_^/_YH
XM``#`<__\/^'``,`!__Z.````P`'__`````#`#/?@`````,`^```6!```P/@`)
XM`*HJ@`#````#87=@`,`````*JK``P````7U?0`#`````>`<``(``````````/
X9````"$-P=4)L:70`````"`````5154E4`'U?G
X``
Xend
Xsize 475
END_OF_FILE
if test 713 -ne `wc -c <'Kill_CpuBli.uu'`; then
    echo shar: \"'Kill_CpuBli.uu'\" unpacked with wrong size!
fi
# end of 'Kill_CpuBli.uu'
fi
if test ! -d 'src' ; then
    echo shar: Creating directory \"'src'\"
    mkdir 'src'
fi
if test -f 'src/cpublit.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/cpublit.c'\"
else
echo shar: Extracting \"'src/cpublit.c'\" \(15098 characters\)
sed "s/^X//" >'src/cpublit.c' <<'END_OF_FILE'
X/****************************************************************************
X *
X *		CPUBLIT.C
X *
X *		(C) Copyright Eddy Carroll, 1991. Freely distributable.
X * 
X *		CpuBlit replaces the BltBitMap function in graphics.library with
X *		a version that uses the CPU where practical. This is up to 2.8
X *		times faster on a 68030 system.
X *
X *		This module installs the new blit routine, handles parsing the
X *		command line options etc. Scroll.s does the actual blitting.
X *
X ***************************************************************************/
X
X#define DEBUG	0			/* If 1, then include debugging code			*/
X
X#ifndef LATTICE_50
X#include "system.h"
Xtypedef void (*__fptr)();	/* The sort of thing returned by SetFunction	*/
X#endif
X
X#include "scroll.h"
X
X#define YES		1
X#define NO		0
X
X#define NAME			"CpuBlit V1.00"
X#define PORTNAME		NAME
X#define SIGNON			NAME " \251 1991 Eddy Carroll.\n"
X#define DATE			"Apr 1991"
X
X#define print(s)		Write(Output(), s, strlen(s))
X#define BltBitMap_LVO	(-30)	/* Offset of BltBitMap in graphics.library	*/
X
Xchar HelpMsg[] =
XNAME " \251 Eddy Carroll, " DATE ". Replaces blitter with 68020/68030.\n"
X"Usage: CpuBlit {options} | {keywords}\n"
X"\n"
X"Options:\n"
X"    -a    Always use CPU to do blits (default setting)\n"
X"    -1    Use CPU for blits unless another task is ready to run\n"
X"    -2    Use CPU for blits unless more than one task is ready to run\n"
X"    -b    Use CPU even if bitmap isn't initialised correctly\n"
X"    -o    Use CPU only when a single bitmap is involved\n"
X"    -s    Use CPU for blits unless a blit is already in progress\n"
X"    -pN   Ignore tasks with priority < N (default setting is 0)\n"
X"    -q    Remove CpuBlit from the system\n"
X"\n"
X"Keywords: BLITMODE=[ALWAYS|ONE|TWO|SHARE] BROKEN SINGLE MINTASKPRI=n QUIT\n"
X"\n"
X"See the documentation for details about starting CpuBlit from Workbench.\n";
X
X/****************************************************************************
X *
X *		Globals
X * 
X ***************************************************************************/
X
Xstruct Gfxbase  	 *GfxBase;
Xstruct IntuitionBase *IntuitionBase;
Xstruct IconBase		 *IconBase;
X
X/*
X *		Valid modes of operation for BlitMode
X */
X#define BLIT_ALWAYS		0	/* Always use CPU for blits						*/
X#define BLIT_ONE		1	/* Use CPU unless another task is ready to run	*/
X#define BLIT_TWO		2	/* Use CPU unless more than one task is ready	*/
X#define BLIT_SHARE		3	/* Use CPU unless CPU is already doing a blit	*/
X
X/*
X *		This array corresponds to the above modes
X */
Xvoid (*BlitFuncs[])() = { StartBlit, Friend1, Friend2, ShareBlit };
X
X/*
X *		All the settings that can be set by the program
X */
Xstruct Settings {
X	long	BlitMode;		/* Current mode of operation for blits  */
X	long	OnlySingle;		/* True if restricting blits to 1 bmap	*/
X	long	Broken;			/* True if handling broken software		*/
X	BYTE	MinTaskPri;		/* All tasks less than this are ignored	*/
X} Settings = {
X	BLIT_ALWAYS, NO, NO, 0
X};
X
X/*
X *		Commands that we can send in a message
X */
X#define MSG_GETVARS		0	/* Get copy of current CpuBlit settings	*/
X#define MSG_SETVARS		1	/* Update CpuBlit settings				*/
X#define MSG_QUIT		2	/* Remove background copy of CpuBlit	*/
X
Xstruct MyMsg {
X	struct	Message msg;	/* Standard message structure			*/
X	struct	Settings *vars;	/* Settings used by CpuBlit				*/
X	int		command;		/* Requested operation        			*/
X	int		result;			/* True if command completed okay		*/
X} MyMsg, *msg;
X
X/*
X *		Return codes passed back in result
X */
X#define MSG_OKAY	0		/* Message was handled correctly		*/
X#define MSG_REMOVED	1		/* CpuBlit was removed safely			*/
X#define MSG_FAILED	2		/* CpuBlit couldn't be removed			*/
X
X/*
X *		Scalar variables
X */
Xstruct MsgPort *LocalPort;	/* Local port for returned messages		*/
Xlong QuitFlag;				/* True if user asks CpuBlit to quit	*/
Xlong FromWorkbench;			/* True if started from Workbench		*/
Xlong AlreadyRunning;		/* True if CpuBlit already installed	*/
X
X/****************************************************************************
X *
X *		myexit(err)
X *
X *		Performs a small amount of cleanup and then exits to AmigaDos.
X *		Principally, handles cleaning up if we were run from Workbench.
X *
X ***************************************************************************/
X
Xvoid myexit(err)
X{
X	if (LocalPort)
X		DeletePort(LocalPort);
X
X	exit(err);
X}
X
X/****************************************************************************
X *
X *		SetVars(settings)
X *
X *		Sets the various CpuBlit flags according to the values in the
X *		supplied Settings structure.
X *
X ***************************************************************************/
X
Xvoid SetVars(struct Settings *settings)
X{
X	BlitFunc	= BlitFuncs[settings->BlitMode];
X	OnlySingle	= settings->OnlySingle;
X	Broken		= settings->Broken;
X	MinTaskPri	= settings->MinTaskPri;
X}
X
X/****************************************************************************
X *
X *		ParseOption()
X *
X *		Parses an option string, setting the appropriate field in the
X *		master Settings structure. This routine handles both Unix-style
X *		-opts and also ReadArgs/ToolTypes keywords. Returns true if
X *		the option string made sense, false otherwise.
X *
X ***************************************************************************/
X
Xint ParseOption(char *opt)
X{
X#define MATCHSTR(s1,s2)		(!strnicmp(s1, s2, sizeof(s2)-1))
X
X	if MATCHSTR(opt, "-a") {
X		Settings.BlitMode	= BLIT_ALWAYS;
X		Settings.OnlySingle	= NO;
X		Settings.Broken		= NO;
X	}
X	else if MATCHSTR(opt, "-1")		Settings.BlitMode	= BLIT_ONE;
X	else if MATCHSTR(opt, "-2")		Settings.BlitMode	= BLIT_TWO;
X	else if MATCHSTR(opt, "-s")		Settings.BlitMode	= BLIT_SHARE;
X	else if MATCHSTR(opt, "-b")		Settings.Broken		= YES;
X	else if MATCHSTR(opt, "-o")		Settings.OnlySingle	= YES;
X	else if MATCHSTR(opt, "-q")		QuitFlag            = YES;
X	else if (MATCHSTR(opt, "-p") && opt[2])
X		Settings.MinTaskPri = atoi(opt+2);
X	else if MATCHSTR(opt, "BLITMODE") {
X		char *p = opt + 8;
X		if (*p++ && *p) {
X			if		MATCHSTR(p, "ALWAYS")	Settings.BlitMode	= BLIT_ALWAYS;
X			else if MATCHSTR(p, "ONE")		Settings.BlitMode	= BLIT_ONE;
X			else if MATCHSTR(p, "TWO")		Settings.BlitMode	= BLIT_TWO;
X			else if MATCHSTR(p, "SHARE")	Settings.BlitMode	= BLIT_SHARE;
X		} else return (0);
X	}
X	else if MATCHSTR(opt, "BROKEN") {
X		char *p = opt + 6;
X		if (*p++ && MATCHSTR(p, "NO"))		Settings.Broken		= NO;
X		else 								Settings.Broken		= YES;
X	}
X	else if MATCHSTR(opt, "SINGLE") {
X		char *p = opt + 6;
X		if (*p++ && MATCHSTR(p, "NO"))		Settings.OnlySingle	= NO;
X		else 								Settings.OnlySingle = YES;
X	}
X	else if MATCHSTR(opt, "MINTASKPRI") {
X		char *p = opt + 10;
X		if (*p++ && *p)						Settings.MinTaskPri = atoi(p);
X		else return (0);
X	}
X	else if MATCHSTR(opt, "QUIT")			QuitFlag = YES;
X	else  return (0);
X
X	return (1);
X}
X
X/****************************************************************************
X *
X *		MyFindPort(name)
X *
X *		Replacement for the FindPort() in exec.library. Under 1.3, FindPort()
X *		will cause Enforcer hits since FFS partitions create public ports
X *		that have no name (this is a no-no), and FindPort() doesn't check
X *		for null names.
X *		
X *		Even though this isn't really CpuBlit's problem, I had quite a few
X *		reports of CpuBlit causing Enforcer hits which turned out to be
X *		because of this, so I've added this workaround to keep people
X *		happy.
X *
X *		Commodore made FindPort() (actually FindName()) a bit more robust
X *		under Kickstart 2.0, so in that case we can safely use the standard
X *		routine.
X *
X ***************************************************************************/
X
Xstruct MsgPort *MyFindPort(char *name)
X{
X	struct Node *nd;
X	extern struct ExecBase *SysBase;
X
X	if (SysBase->LibNode.lib_Version >= 36)
X		return (FindPort(name));
X
X	Forbid();
X	for (nd = SysBase->PortList.lh_Head; nd; nd = nd->ln_Succ)
X		if (nd->ln_Name && !strcmp(nd->ln_Name, name))
X			break;
X	Permit();
X	return (struct MsgPort *)nd;
X}
X
X
X/****************************************************************************
X *
X *		mainloop()
X *
X *		This is the main event loop. It sits waiting for a message from
X *		other invocations of CpuBlit, which tell it to either change the
X *		current settings or to remove itself.
X *
X ***************************************************************************/
X
Xvoid mainloop(void)
X{
X	struct MsgPort *MyPort;
X	int installed = 1;
X	__fptr *BltBitMapPtr = (__fptr *)BltBitMapAddress;
X
X	/*
X	 *		We have to create our rendezvous port here rather than in the
X	 *		mainline, since the message port depends on task information etc.
X	 *		This is not altogether satisfactory since if it fails, there is
X	 *		no way to tell the user (as a background task, we have no stdin
X	 *		or stdout). But since port creation is unlikely to fail anyway,
X	 *		it's not a big problem.
X	 */
X	MyPort = CreatePort(PORTNAME, 0);
X	if (!MyPort)
X		return;
X
X	/*
X	 *		Now have to open graphics.library, so that we can add in our
X	 *		new patch. As above, if this fails there is no easy way to
X	 *		tell the user. However, at least it won't crash the system.
X	 */
X	GfxBase = OpenLibrary("graphics.library", 0);
X	if (!GfxBase)
X		return;
X
X	*BltBitMapPtr = SetFunction(GfxBase, BltBitMap_LVO, NewBltBitMap);
X
X	/*
X	 *		Now wait a message from another copy of CpuBlit. This will
X	 *		either contain an updated command line argument or else a
X	 *		request to quit.
X	 */
X	do {
X		__fptr oldptr;
X
X		WaitPort(MyPort);
X		while ((msg = (struct MyMsg *)GetMsg(MyPort)) != NULL) {
X			switch (msg->command) {
X
X			case MSG_GETVARS:
X				memcpy(msg->vars, &Settings, sizeof(Settings));
X				break;
X
X			case MSG_SETVARS:
X				memcpy(&Settings, msg->vars, sizeof(Settings));
X				SetVars(&Settings);
X				break;
X
X			case MSG_QUIT:
X				/*
X				 *		Try and remove ourselves. We have to surround this
X				 *		with Forbid() to make sure that no other tasks manage
X				 *		to call BltBitMap() in the case where we restore the
X				 *		original vector and then realise that its current
X				 *		replacement actually pointed to something other than
X				 *		CpuBlit.
X				 */
X				Forbid();
X				oldptr = SetFunction(GfxBase, BltBitMap_LVO, *BltBitMapPtr);
X				if (oldptr == NewBltBitMap) {
X					installed = 0;
X					msg->result = MSG_REMOVED;
X				} else {
X					SetFunction(GfxBase, BltBitMap_LVO, oldptr);
X					msg->result = MSG_FAILED;
X				}
X				Permit();
X			}
X			ReplyMsg(msg);
X		}
X	} while (installed);
X
X	/*
X	 *		Now our patch has been removed, it only remains to free up the
X	 *		code. It is possible that someone is still in our blitter code.
X	 *		We can determine this fairly safely by looking at UsageCount;
X	 *		if this is -1, nobody is in our code. Otherwise, we wait until
X	 *		it is -1 (delaying for a little while inbetween to give programs
X	 *		a chance to run).
X	 *
X	 *		We also set the blitter test function to ExitBlit, so that if
X	 *		someone does slip through our test and end up inside our code,
X	 *		they will get rerouted back to the normal blitter code almost
X	 *		immediately.
X	 */
X	DeletePort(MyPort);
X	BlitFunc = ExitBlit;
X
X	while (UsageCount != -1)
X		Delay(10);				/* Wait 0.2 seconds */
X
X	/*
X	 *		Now we're completely finished so we can close the libraries
X	 *		and exit.
X	 */
X	CloseLibrary(GfxBase);
X}
X
X
X/****************************************************************************
X *
X *		Mainline 
X *
X ***************************************************************************/
X
Xvoid main(int argc, char **argv)
X{
X	struct MsgPort *BlitPort;
X	int i;
X
X	FromWorkbench = (argc == 0);
X
X	/*
X	 *		Now see if CpuBlit is already running in
X	 *		the background. If it is, then get a copy of the settings it
X	 *		is currently using.
X	 */
X	BlitPort = MyFindPort(PORTNAME);
X	if (BlitPort) {
X		/*
X		 *		The new blit routine has already been installed. So, send
X		 *		it a message giving the command line options (if any)
X		 *		to the remote routine, telling it to update its own options.
X		 */
X		AlreadyRunning = YES;
X		LocalPort = CreatePort(NULL, 0);
X		if (!LocalPort) {
X			if (!FromWorkbench)
X				print("CpuBlit: couldn't create local message port.\n");
X			myexit(10);
X		}
X		MyMsg.msg.mn_ReplyPort	= LocalPort;
X		MyMsg.command			= MSG_GETVARS;
X		MyMsg.vars   			= &Settings;
X		PutMsg(BlitPort, &MyMsg);
X		WaitPort(LocalPort);
X		GetMsg(LocalPort);
X	}
X	/*
X	 *		Now parse the command line options, modifying our local copy
X	 *		of Settings accordingly.
X	 */
X	if (FromWorkbench) {
X		extern struct WBStartup *WBenchMsg;
X		struct WBArg *wbarg = WBenchMsg->sm_ArgList;
X
X		IconBase = (struct IconBase *)OpenLibrary("icon.library", 0);
X		if (!IconBase)
X			myexit(5);
X
X		/*
X		 *		Now walk down all the icons we've been given (probably
X		 *		just our own tool icon) and parse the arguments present
X		 *		in each one.
X		 */
X		for (i = 0; i < WBenchMsg->sm_NumArgs; i++, wbarg++) {
X			struct DiskObject *dobj;
X			char **tooltypes;
X			BPTR olddir;
X
X			if (wbarg->wa_Lock && *wbarg->wa_Name) {
X				olddir = CurrentDir(wbarg->wa_Lock);
X				if (dobj = GetDiskObject(wbarg->wa_Name)) {
X					for (tooltypes = dobj->do_ToolTypes;
X											*tooltypes; tooltypes++)
X						ParseOption(*tooltypes);
X				}
X				FreeDiskObject(dobj);
X				CurrentDir(olddir);
X			}
X		}
X		CloseLibrary(IconBase);
X	} else {
X		/*
X		 *		Plain jane CLI startup
X		 */
X#if DEBUG
X		if (argv[1][0] == '!') {
X			static buf[1000];
X			sprintf(buf,
X				"Blitmode   = %d\n"
X				"OnlySingle = %d\n"
X				"Broken     = %d\n"
X				"MinTaskPri = %d\n",
X				Settings.BlitMode, Settings.OnlySingle,
X				Settings.Broken, Settings.MinTaskPri);
X			print(buf);
X			exit(5);
X		}
X#endif
X		for (i = 1; i < argc; i++) {
X			if (!ParseOption(argv[i])) {
X				print(HelpMsg);
X				myexit(5);
X			}
X		}
X	}
X
X	/*
X	 *		Now we either send the options to the remote copy of CpuBlit
X	 *		or install ourselves in the background.
X	 */
X	if (AlreadyRunning) {
X		if (QuitFlag)
X			MyMsg.command = MSG_QUIT;
X		else
X			MyMsg.command = MSG_SETVARS;
X		PutMsg(BlitPort, &MyMsg);
X		WaitPort(LocalPort);
X		GetMsg(LocalPort);
X		if (FromWorkbench && MyMsg.result == MSG_FAILED) {
X			IntuitionBase = (struct IntuitionBase *)
X							OpenLibrary("intuition.library", 0);
X			if (IntuitionBase) {
X				DisplayBeep(0);	/* Flash all screens -- pretty rude */
X				CloseLibrary(IntuitionBase);
X			}
X		}
X		if (!FromWorkbench) {
X			if (MyMsg.result == MSG_REMOVED)
X				print("CpuBlit removed successfully.\n");
X			else if (MyMsg.result == MSG_FAILED) {
X				print(
X"Couldn't remove CpuBlit; someone else has patched BltBitMap. Please remove\n"
X"any other utilities you have installed and then try again.\n");
X				myexit(5);
X			}
X		}
X		myexit(0);
X	}
X
X	/*
X	 *		This is the first time we are being run. If we were run from
X	 *		the CLI, detach ourselves (and allow the current process to
X	 *		return to the CLI immediately). If we were run from Workbench,
X	 *		then just call the message handling code directly and wait
X	 *		until another copy of CpuBlit asks us to return.
X	 */
X	if (QuitFlag) {
X		if (!FromWorkbench)
X			print("CpuBlit hasn't been installed yet.\n");
X		myexit(5);
X	}
X
X	SetVars(&Settings);
X	if (FromWorkbench)
X		mainloop();
X	else {
X		if (!res(NAME, 5, mainloop, 4000)) {
X			print("Couldn't spawn background CpuBlit task.\n");
X			myexit(10);
X		}
X		print(SIGNON);
X	}
X	myexit(0);
X}
END_OF_FILE
if test 15098 -ne `wc -c <'src/cpublit.c'`; then
    echo shar: \"'src/cpublit.c'\" unpacked with wrong size!
fi
# end of 'src/cpublit.c'
fi
if test -f 'src/makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/makefile'\"
else
echo shar: Extracting \"'src/makefile'\" \(821 characters\)
sed "s/^X//" >'src/makefile' <<'END_OF_FILE'
X#
X# Lattice LKM makefile, for SAS/C C V5.10a                          :ts=8
X#
X# CpuBlit (C) Copyright Eddy Carroll, Feb 1991
X#
X
X#DBSYM	= -d5
XCFLAGS	= -cusq -j88i -ms -v $(DBSYM)
XBFLAGS	= sc sd nd map ram:map
X#BFLAGS	= sc sd map ram:map addsym
XLIBS	= lib:lc.lib lib:amiga.lib
XASM	= lc:asm
X
X.c.o:
X	lc $(CFLAGS) -Hsystem.sym $*.c
X.s.o:
X	$(ASM) -iinclude: $*.s    # Standard "pure" assembly
X.a.o:
X	$(ASM) -u -iinclude: $*.a # Prefixes all labels with style underscore
X.n.doc:
X	nro >$*.doc -ms:an $*.n
X.h.sym:
X	lc1 -ph -o$*.sym $*.h
X
X#
X# Makefile dependencies
X#
X
XNAME	= cpublit
X
Xall: $(NAME)
X
XOBJS	= small.o $(NAME).o scroll.o res.o
X
X$(NAME): $(OBJS) makefile
X	blink from $(OBJS) to $(NAME) $(BFLAGS) lib $(LIBS)
X
Xsystem.sym:	system.h
Xcpublit.o:	cpublit.c	scroll.h	system.sym
Xsmall.o:	small.a
Xscroll.o:	scroll.s
Xres.o:		res.s
END_OF_FILE
if test 821 -ne `wc -c <'src/makefile'`; then
    echo shar: \"'src/makefile'\" unpacked with wrong size!
fi
# end of 'src/makefile'
fi
if test -f 'src/res.s' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/res.s'\"
else
echo shar: Extracting \"'src/res.s'\" \(6516 characters\)
sed "s/^X//" >'src/res.s' <<'END_OF_FILE'
X*:ts=8
X*****************************************************************************
X*                                                                           *
X* RES.S                                    (C) Copyright Eddy Carroll 1989  *
X*                                                                           *
X* This module allows you to make a duplicate copy of your current process.  *
X* In fact, both processes actually share the same code. However, the        *
X* seglist pointer of the current process is modified so that when the       *
X* process terminates, the memory doesn't get freed (if it did, the new      *
X* process would suddenly find itself deallocated. Hello guru...)            *
X* This code only works when called from CLI processes.                      *
X*                                                                           *
X* The parameters passed are similar to those for CreateProc(), with the     *
X* difference that instead of passing a BPTR to a seglist, you pass the      *
X* address of the function the new process should start executing at.        *
X*                                                                           *
X* When the new process returns from this function, it will be removed from  *
X* the system, and its memory (finally) deallocated.                         *
X*                                                                           *
X* The typical use for a function like this is to allow a program to detach  *
X* itself from a CLI (completely, with no trailing console handles etc.)     *
X* when it is run. This is a convenient feature for the user, if the program *
X* is of the sort designed to sit in the background the whole time, rather   *
X* than do something immediately, then exit.                                 *
X*                                                                           *
X* Lattice provide cback.o which at first glance would seem to provide a     *
X* similar solution. However, cback.o makes it difficult to print error      *
X* messages to the console if there is an error on the command line - by     *
X* the time you spot the error, the CLI prompt has already been printed      *
X* and your error message is printed after it. This looks very messy.        *
X* Res avoids this problem by not spawning the background process until      *
X* after the error checking has been done.                                   *
X*                                                                           *
X* From C, you call it as follows:                                           *
X*                                                                           *
X* pid = res(name,pri,func,stacksize)                                        *
X*                                                                           *
X* name         - pointer to null terminated string                          *
X* pri          - integer, priority of the new process                       *
X* func         - pointer to the function for new process to call            *
X* stacksize    - integer, size of the stack for the new process             *
X*                                                                           *
X* pid          - Process ID of new process, or 0 if none created            *
X*                                                                           *
X*****************************************************************************
X
X	INCLUDE "exec/types.i"
X        INCLUDE "exec/alerts.i"
X        INCLUDE "exec/nodes.i"
X        INCLUDE "exec/lists.i"
X        INCLUDE "exec/ports.i"
X        INCLUDE "exec/libraries.i"
X        INCLUDE "exec/tasks.i"
X        INCLUDE "libraries/dos.i"
X        INCLUDE "libraries/dosextens.i"
X        INCLUDE "workbench/startup.i"
X        INCLUDE "exec/funcdef.i"
X        INCLUDE "exec/exec_lib.i"
X        INCLUDE "libraries/dos_lib.i"
X
X	xref	_exit
X	xref	_DOSBase
X	xdef	_res
X
XAbsExecBase	equ	4
Xsegsize		equ	36		; Size of fake seg. (code = 28 bytes)
X
X        csect   text,0,0,1,2		* xref's after this are 16-bit reloc
X
X
Xcallsys macro
X        CALLLIB _LVO\1
X	endm
X
X_res:
X	movem.l	d2-d4/a2/a3/a6,-(a7)	; Save registers
X	move.l	AbsExecBase.w,a6	; Get base of Exec library
X	moveq	#0,d1			; Any sort of memory will do
X	moveq	#segsize,d0		; Get size of fake segment
X	callsys	AllocMem		; Grab some memory
X	tst.l	d0			; Did we get any?
X	beq	fatal			; If not, abort immediately!
X	move.l	d0,a3			; Save pointer to memory
X	sub.l	a1,a1			; NULL pointer indicates our process
X	callsys	FindTask		; Get pointer to our process block
X	move.l	d0,a2			; Save it
X	move.l	pr_CLI(A2),a0		; Get BPTR to our process's segarray
X	add.l	a0,a0			; Convert BPTR to address
X	add.l	a0,a0			; 
X	move.l	cli_Module(a0),4(a3)	; Make fake segment point to our code
X	clr.l	cli_Module(a0)		; Remove process seg. from CLI seglist
X	move.l	#segsize,(a3)		; Set size of fake seglist
X	lea.l	8(a3),a2		; Get pointer to first code byte
X
X;
X; Now a tiny machine code program is constructed. It looks like this:
X;
X;	move.l	#$xxxxxx,A4	; Initialise A4
X;	jsr	$xxxxxx		; Call user program
X;	move.l	#$xxxxxx,A6	; Load DOSbase into A6
X;	move.l	#$xxxxxx,d1	; Get BPTR to this segment 
X;	jmp	UnLoadSeg(A6)	; Unload our process from memory
X;
X; It's built "on the fly" so to speak, to keep code size down, and also
X; because it's a convenient way of initialising all the variables.
X; Note that a potential problem exists if DOSBase should somehow alter or
X; disappear. We'll assume it will remain relatively stable for the next
X; few years anyway :-)
X;
X
X	move.l	_DOSBase,a6		; Prepare for DOS call
X	move.w	#$287C,(a2)+		; Store MOVE.L $xxxxxx,A4 instruction
X	move.l	a4,(a2)+		; Output value of A4 to initialise to
X	move.w	#$4EB9,(a2)+		; Store JSR $xxxxxx
X	move.l	36(a7),(a2)+		; followed by address of user function
X	move.w	#$2C7C,(a2)+		; Store MOVE.L $xxxxxx,A6 instruction
X	move.l	a6,(a2)+		; followeds by current DOSbase
X;
X	lea	4(a3),a3		; Now get seglist ptr to fake segment
X	move.l	a3,d3			; and convert it to BPTR
X	lsr.l	#2,d3			; D3 now has seglist ptr to fake seg
X	move.w	#$223C,(a2)+		; Store MOVE.L $xxxxxx,D1 instruction
X	move.l	d3,(a2)+		; Followed by BPTR to the segment
X	move.l	#$4EEEFF64,(a2)+	; Store JMP UnLoadSeg(A6)
X;
X	move.l	28(A7),d1		; Get pointer to name
X	move.l	32(A7),d2		; Get process priority
X	move.l	40(A7),d4		; Get stacksize
X	callsys	CreateProc		; Create new process
X	movem.l	(a7)+,d2-d4/a2/a3/a6	; Pop registers
X	rts				; Return
Xfatal:
X	moveq	#120,d0			; Set error exit code
X	jmp	_exit			; And exit
X
X	end
END_OF_FILE
if test 6516 -ne `wc -c <'src/res.s'`; then
    echo shar: \"'src/res.s'\" unpacked with wrong size!
fi
# end of 'src/res.s'
fi
if test -f 'src/scroll.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/scroll.h'\"
else
echo shar: Extracting \"'src/scroll.h'\" \(1524 characters\)
sed "s/^X//" >'src/scroll.h' <<'END_OF_FILE'
X/****************************************************************************
X *
X *		SCROLL.H
X *
X *		Declares functions and variables available in the assembly
X *		file SCROLL.S.
X *
X *		We have to do a little trick to allow the smalldata model to be
X *		used with Blink. We want to modify the longword stored at
X *		BltBitMapAddress. However, this is located in the code section
X *		of the program. The solution is to declare it as a function, then
X *		setup a pointer to it from inside the actual code and modify it
X *		through the pointer. This is a little ugly, but reduces the code
X *		size by about 20%.
X *
X ***************************************************************************/
X
Xextern void NewBltBitMap();			/* Our replacement BltBitMap routine	*/
Xextern void BltBitMapAddress();		/* Points to original BltBitMap()		*/	
X
Xextern void Friend1();				/* Ptr to check fn for one active task	*/
Xextern void Friend2();				/* Ptr to check fn for two active tasks	*/
Xextern void ShareBlit();			/* Ptr to check fn to share CPU/blitter	*/
Xextern void StartBlit();			/* Ptr to check fn that always uses CPU	*/
Xextern void ExitBlit();				/* Ptr to check fn that never uses CPU	*/
X
Xextern void (*BlitFunc)();			/* Holds Ptr to current check function	*/
Xextern long UsageCount;				/* No. of callers currently in CPU code	*/
Xextern long OnlySingle;				/* True if restricting blits to 1 bmap	*/
Xextern long Broken;					/* True if handling broken software		*/
Xextern BYTE MinTaskPri;				/* Ignore tasks with pri <= this value	*/
END_OF_FILE
if test 1524 -ne `wc -c <'src/scroll.h'`; then
    echo shar: \"'src/scroll.h'\" unpacked with wrong size!
fi
# end of 'src/scroll.h'
fi
if test -f 'src/small.a' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/small.a'\"
else
echo shar: Extracting \"'src/small.a'\" \(7425 characters\)
sed "s/^X//" >'src/small.a' <<'END_OF_FILE'
X*:ts=8
X******************************************************************************
X*									     *
X*	SMALL.A				  (C) Copyright Eddy Carroll 1991    *
X*	~~~~~~~				  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    *
X*									     *
X*	Replacement startup code for Lattice C V5.10a. Use instead of c.o.   *
X*	This has many features stripped out to allow small utilities to      *
X*	have as small a filesize as possible. If you use this, don't call    *
X*	any stdio functions.						     *
X*                                                                            *
X* 	In some of my earlier projects, I used a similar file called tiny.a. *
X*	Small.a is essentially that file but with Workbench support added.   *
X*	avoid confusion between the two.				     *
X*                                                                            *
X******************************************************************************
X
X	INCLUDE "exec/types.i"
X	INCLUDE "exec/execbase.i"
X	INCLUDE "exec/nodes.i"
X	INCLUDE "exec/lists.i"
X	INCLUDE "exec/ports.i"
X	INCLUDE "exec/libraries.i"
X	INCLUDE "exec/tasks.i"
X	INCLUDE "libraries/dos.i"
X	INCLUDE "libraries/dosextens.i"
X	INCLUDE "workbench/startup.i"
X	INCLUDE "exec/funcdef.i"
X	INCLUDE "exec/exec_lib.i"
X	INCLUDE "libraries/dos_lib.i"
X
XMAXARGS	    EQU 100	; Maximum number of command line arguments from CLI
XAbsExecBase EQU 4	; Welcome to the only fixed point in the universe
X
X* A useful macro to let us call library routines
Xcallsys macro
X	CALLLIB _LVO\1
X	endm
X
X	xdef	XCEXIT
X	xdef	exit
X	xref	LinkerDB
X	xref	_BSSBAS
X	xref	_BSSLEN
X
X	csect	text,0,0,1,2		* xref's after this are 16-bit reloc
X	xref	main			* Name of C program to start with.
X
Xstart:
X	movem.l d1-d6/a0-a6,-(a7)
XREGSIZE EQU	(6+7)*4
X	lea	REGSIZE(a7),A5		* Determine old stack pointer
X	move.l	a0,a2			* Save command pointer
X	move.l	d0,d2			* and command length
X	lea	LinkerDB,a4		* Load base register
X
X	move.l	AbsExecBase.W,a6
X	move.l	a6,SysBase(A4)
X	move.l	a7,_StackPtr(A4)	* Save stack ptr
X
X	move.l	a5,D0	  		* get top of stack
X	sub.l	4(a5),D0		* compute bottom
X	add.l	#128,D0 		* allow for parms overflow
X	move.l	D0,_base(A4)		* save for stack checking
X
X	lea	DOSName(A4),A1
X	moveq.l	#0,D0
X	callsys	OpenLibrary
X	move.l	D0,DOSBase(A4)
X	beq	NoDos
X
X	move.l	ThisTask(a6),a3		* Get our task ID
X	tst.l	pr_CLI(a3)		* Running from Workbench?
X	bne.s	getcom			* If no, skip to do CLI stuff
X	lea	pr_MsgPort(a3),a0	* Our process port
X	callsys	WaitPort		* Wait for Workbench startup message
X	lea	pr_MsgPort(a3),a0	* Get our message port again
X	callsys	GetMsg			* Get startup message
X	move.l	d0,WBenchMsg(a4)	* Save pointer to it
X	move.l	d0,-(sp)		* Save it as argv
X	moveq	#0,d0			* And push argc of 0 to indicate WB
X	move.l	d0,-(sp)		*
X	bra	cont			* Skip to init BSS and start prog
X
X*------ find command name:
Xgetcom:
X	move.l  pr_CLI(a3),a0
X	add.l	a0,a0
X	add.l	a0,a0
X	move.l	cli_CommandName(a0),a1
X	add.l	a1,a1
X	add.l	a1,a1
X
X*------ collect parameters:
X	move.l	d2,d0			* get command line length
X	moveq.l #0,d1
X	move.b	(a1)+,d1
X	move.l	a1,_ProgramName(A4)
X	add.l	d1,d0			* add length of command name
X	addq.l	#1,d0			* allow for space after command
X
X	clr.w	-(A7)			* set null terminator for command line
X	addq.l	#1,D0			* force to even number of bytes
X	andi.w	#$fffe,D0		* (round up)
X	sub.l	D0,A7			* make room on stack for command line
X	subq.l	#2,D0
X	clr.w	0(A7,D0)
X
X*------ copy command line onto stack
X	move.l	d2,d0			* get command line length
X	subq.l	#1,d0
X	add.l	d1,d2
X
Xcopy_line:
X	move.b	0(A2,D0.W),0(A7,D2.W)	* copy command line to stack
X	subq.l	#1,d2
X	dbf	d0,copy_line
X	move.l	d2,d0			* save offset to argv[1] - 1
X	clr.b	0(a7,d2.w) 		* Insert command name terminator
X	subq.l	#1,d2
X
Xcopy_cmd:
X	move.b	0(a1,d2.w),0(a7,d2.w)	* copy command name to stack
X	dbf	d2,copy_cmd
X	lea	1(a7,d0.w),a1		* get pointer to start of arguments
X	move.l	a7,a2			* get pointer for argv[0]
X
X	sub.l	#(MAXARGS*4),a7		* Reserve space for argv[]
X	move.l	a7,a3			* Save ptr to base of argv (&argv[0])
X	move.l	a2,(a7)			* Setup argv[0] to point to cmd line
X	lea	4(a7),a2		* Init base into array at argv[1]
X	moveq	#1,d2			* Initialise argc
X
X*
X* From here on down, A1 is pointer into command line
X*
Xbuild_argv:
X	bsr.s	getnext			* Read next character from line
X	bcs.s	doquote			* If quote, handle
X	beq.s	build_argv		* If white space, skip over it
X
X	lea	-1(a1),a0		* Get address of this parameter
X	bsr.s	bumpargv		* Store it to argv[] array
Xbuild_2:
X	bsr.s	getnext			* Get next character
X	bne.s	build_2			* If not white space, keep looking
X	clr.b	-1(a1)			* Zero-terminate current argument
X	bra.s	build_argv		* And go back to get next argument
X
Xdoquote:
X	move.l	a1,a0			* Get pointer to this argument
X	bsr.s	bumpargv		* Output it to argv[]
Xquote_2:
X	bsr.s	getnext			* Get next character
X	bcc.s	quote_2			* If not quote, keep looking
X	clr.b	-1(a1)			* Zero-terminate current argument
Xquote_3:
X	bsr.s	getnext			* Get next character
X	bne.s	quote_3			* Skip until space reached
X	beq.s	build_argv		* Go back and read next argument
X
Xbumpargv:
X	move.l	a0,(a2)+		* Output ptr to current argument
X	addq	#1,d2			* Increment argc
X	cmpi	#MAXARGS,d2		* Used up all our arguments yet?
X	bls.s	qrts			* If not, then return
X	moveq	#110,d0			* Else set return code
X	bra.s	exit2			* And exit
X
X*
X* Reads next character from command line. If zero, never returns, but
X* drops into call to main. Else, returns, with C=1 if character is quote,
X* Z=1 if character is white space.
X*
Xgetnext:
X	move.b	(a1)+,d0		* Get character from command line
X	beq.s	get_2			* Exit if end of line
X	cmp.b	#34,d0			* Check if quote
X	beq.s	isquote			*
X	cmp.b	#32,d0			* Check if space
X	beq.s	isspace			*
X	cmp.b	#9,d0			* Or tab
X	beq.s	isspace			*
X	cmp.b	#10,d0			* Or end of line
Xisspace:
X	andi	#$1E,ccr		* Clear carry flag, retaining Z
Xqrts	rts
X
Xisquote:
X	ori	#1,ccr			* Set carry flag
X	andi	#$FB,ccr		* Clear zero flag
X	rts				* And return
X
Xget_2:
X	move.l	a3,-(a7)		* Push argv onto stack
X	move.l	d2,-(a7)		* Push argc onto stack
X
Xcont:
X	lea	_BSSBAS,a3		* get base of BSS
X	moveq	#0,d1
X	move.l	#_BSSLEN,d0		* get length of BSS in longwords
X	bra.s	clr_lp			* and clear for length given
Xclr_bss move.l	d1,(a3)+
Xclr_lp	dbf	d0,clr_bss
X
Xdomain:
X	jsr	main(PC)		* Call main(argc,argv)
X	moveq.l #0,d0			* Set successful status
X	bra.s	exit2
X
XNoDos:
X	moveq.l	#100,d0			* Exit thread if no dos.library
X	bra.s	exit2			*
X
Xexit:
X_exit:
XXCEXIT:
X	move.l	4(SP),d0		* Extract return code
Xexit2:
X	move.l	d0,-(a7)
X	move.l	AbsExecBase.W,a6
X	move.l	DOSBase(A4),a1
X	callsys CloseLibrary		* Close Dos library
X
X*------ this rts sends us back to DOS:
X	tst.l	WBenchMsg(a4)		* Did we run from Workbench
X	beq.s	ExitToDOS		* If not, skip WB cleanup
X	move.l	SysBase(A4),a6		*
X	callsys	Forbid			* Stop Workbench unloading us too soon
X	move.l	WBenchMsg(a4),a1	*
X	callsys	ReplyMsg		* Return our startup msg
X
XExitToDOS:
X	move.l	(A7)+,D0
X	movea.l _StackPtr(a4),SP	* Restore stack ptr
X	movem.l (a7)+,d1-d6/a0-a6
X	rts
X
X*-----------------------------------------------------------------------
X* Global definitions
X*
X	csect	__MERGED,1,,2,2
X
X	xdef	NULL,SysBase,LoadAddress,DOSBase
X	xdef	_oserr,_OSERR,_ONBREAK
X	xdef	_ProgramName,_StackPtr,_base,WBenchMsg
X
XNULL	       dc.l    0
X_base	       dc.l    0
X_oserr	       equ     *
X_OSERR	       dc.l    0
X_ONBREAK       dc.l    0
XSysBase        dc.l    0
XLoadAddress    dc.l    0
X_StackPtr      dc.l    0
XDOSBase        dc.l    0
X_ProgramName   dc.l    0
XWBenchMsg      dc.l    0
XDOSName        dc.b    'dos.library',0
X
X	END
END_OF_FILE
if test 7425 -ne `wc -c <'src/small.a'`; then
    echo shar: \"'src/small.a'\" unpacked with wrong size!
fi
# end of 'src/small.a'
fi
if test -f 'src/system.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'src/system.h'\"
else
echo shar: Extracting \"'src/system.h'\" \(356 characters\)
sed "s/^X//" >'src/system.h' <<'END_OF_FILE'
X#include <exec/types.h>
X#include <exec/execbase.h>
X#include <libraries/dos.h>
X#include <libraries/dosextens.h>
X#include <intuition/intuition.h>
X#include <workbench/startup.h>
X#include <workbench/workbench.h>
X#include <proto/exec.h>
X#include <proto/dos.h>
X#include <proto/graphics.h>
X#include <proto/intuition.h>
X#include <proto/icon.h>
X#include <string.h>
END_OF_FILE
if test 356 -ne `wc -c <'src/system.h'`; then
    echo shar: \"'src/system.h'\" unpacked with wrong size!
fi
# end of 'src/system.h'
fi
echo shar: End of archive 1 \(of 2\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked both archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.misc.