[comp.sys.amiga.programmer] Copper mystery

d85-jmh@nada.kth.se (Jan-Olof Hendig) (03/28/91)

Here is a non amiga friendly assembler program taken from the the german
publication 'Amiga Magazin 6/90'.

	org $40000

x:
	move #4000,$dff09a ; Kill multitasking
	move.l #cop,$dff084 ; Put address of copperlist in COPADR2!!!
	
waitm:
	btst #6,$bfe001 ; wait for user to press left mb
	bne.s waitm
	rts	; the end

cop: ; copperlist starts here
	dc.w $180,$f00 ; set background to red
	dc.w $700f,-2  ; wait for line $70
	dc.w $180,$fff ; set background to white
	dc.w $e00f,-2  ; wait for line $e0
	dc.w $180,f00  ; background to red 
	dc.w $ffff,-2  ; WAIT for impossible event

This rather 'dirty' program raises some questions that the article I took the
listing from and the old Hardware manual fail to explain. Mind you, my german
is not as good as it should be.

Question number one:
Why does the program work at all ? The address to the copperlist is put
into COPADR2, but the program doesn't access COPJMP2 and neither does the
system copperlist, so how come that the list is activated at all. My version
of the hardware manual doesn't say anything about this, but maybe I didn't
read it well enough.

Question number two:
The program exits without restoring multitasking, still multitasking starts
again when the program ends. Why?
	

No flames please, just constructive answers.

Jan-Olof Hendig

djh@neuromancer.metaphor.com (Dallas J. Hodgson) (03/28/91)

<example of dirty code deleted>

If this program does indeed work, it's only because the vertical blank
interrupt is assuming the responsibility of strobing COPJMP1 or 2. COPJMP1
points to a special "pre-Copper" copper list whose main purpose seems to be
setting up SimpleSprites for the graphics library. It strobes COPJMP2 at the
bottom of it's list.

When the program exits, Exec, DOS, or the CLI can enable whatever interrupts
it likes as a matter of course. I wouldn't depend on this however, it's
purely a SIDE EFFECT.
-- 
+----------------------------------------------------------------------------+
| Dallas J. Hodgson               |     "These days, you have to be pretty   |
| Metaphor Computer Systems       |      technical before you can even       |
| Mountain View, Ca.              |      aspire to crudeness."               | 
| USENET : djh@metaphor.com       |            - William Gibson              |
+============================================================================+
| "The views I express are my own, and not necessarily those of my employer" |
+----------------------------------------------------------------------------+

bairds@eecs.cs.pdx.edu (Shawn L. Baird) (03/28/91)

d85-jmh@nada.kth.se (Jan-Olof Hendig) writes:

>x:
>	move #4000,$dff09a ; Kill multitasking

I don't have my hardware manuals at hand, but do copper interrupts still
occur with this instruction? Is the INTREQ or DMACON? DMACON, I think,
which will just disable some sort of DMA activity (probably the screen
or something. does the screen data go bye-bye for the duration of this
program?)

>	move.l #cop,$dff084 ; Put address of copperlist in COPADR2!!!

If interrupts are still taking place, it could be something to do with
that. Perhaps the Amiga OS uses COPADDR2 for the user copperlist or one
of the two interlace frames. I wish I had my manuals close by.

>	
>waitm:
>	btst #6,$bfe001 ; wait for user to press left mb
>	bne.s waitm
>	rts	; the end

Right here rts returns to some routine set up by the Amiga OS. This
routine, I would assume, probably does some cleanup, like restoring DMA
and starting multi-tasking. If multi-tasking was stopped by the program
it wouldn't make sense to leave it that way. Alternately, it may just be
chance due to the context switch going to another process (because the
OS is now running after the program ends and now the OS decides to run
another process out of its group that are still there) or some such.

>This rather 'dirty' program raises some questions that the article I took the
>listing from and the old Hardware manual fail to explain. Mind you, my german
>is not as good as it should be.

Personally, when writing a program that takes over the machine (as I have
been practicing recently) I do a few things. First, I save a pointer to the
old copper, which can be found in the GfxBase structure (this works on 2.0
as well, and I've seen some demos where the screen wasn't restored
properly under 2.0). Next, I call Forbid() to disable everything but
interrupts. I then disable all DMA and then restore DMA to the copper,
the blitter, bitplanes and audio, which is usually all I use. I make all of
my OS calls before shutting down with Forbid() by the way. Calls such as
AllocMem, etc. Upon restoration I try to reverse the process, enabling DMA,
putting the saved copper into the register and strobing it and then calling
Permit(). This is my guess as to what a compliant assembly language program
that wants to return the OS when it finishes does. If anyone has any
suggestions as to what else I might want to try to help save, be my guest.
I assume (I haven't tried it yet) that I should be leery of OS calls while
in a Forbid()den state, such as disk I/O, but I'm not sure yet. Any info
would be appreciated.

>No flames please, just constructive answers.

I hope this was at least somewhat constructive and maybe even helpful. ;)

>Jan-Olof Hendig
---
 Shawn L. Baird, bairds@eecs.ee.pdx.edu, Wraith on DikuMUD
 The above message is not licensed by AT&T, or at least, not yet.

mykes@amiga0.SF-Bay.ORG (Mike Schwartz) (03/29/91)

In article <1991Mar27.211732.2436@kth.se> d85-jmh@nada.kth.se (Jan-Olof Hendig) writes:
>
>Here is a non amiga friendly assembler program taken from the the german
>publication 'Amiga Magazin 6/90'.
>
>	org $40000
>
>x:
>	move #4000,$dff09a ; Kill multitasking
>	move.l #cop,$dff084 ; Put address of copperlist in COPADR2!!!
>	
>waitm:
>	btst #6,$bfe001 ; wait for user to press left mb
>	bne.s waitm
>	rts	; the end
>
>cop: ; copperlist starts here
>	dc.w $180,$f00 ; set background to red
>	dc.w $700f,-2  ; wait for line $70
>	dc.w $180,$fff ; set background to white
>	dc.w $e00f,-2  ; wait for line $e0
>	dc.w $180,f00  ; background to red 
>	dc.w $ffff,-2  ; WAIT for impossible event
>
>This rather 'dirty' program raises some questions that the article I took the
>listing from and the old Hardware manual fail to explain. Mind you, my german
>is not as good as it should be.
>
>Question number one:
>Why does the program work at all ? The address to the copperlist is put
>into COPADR2, but the program doesn't access COPJMP2 and neither does the
>system copperlist, so how come that the list is activated at all. My version
>of the hardware manual doesn't say anything about this, but maybe I didn't
>read it well enough.
>
>Question number two:
>The program exits without restoring multitasking, still multitasking starts
>again when the program ends. Why?
>	
>
>No flames please, just constructive answers.
>
>Jan-Olof Hendig

This rather 'dirty' program is what hard disk installable game advocates suggest
be done.

To answer your questions, the example does not work for all the reasons you state.
I doubt the programmer tested it, but it does illustrate the concept of putting
the OS to sleep.

--
********************************************************
* Appendix A of the Amiga Hardware Manual tells you    *
* everything you need to know to take full advantage   *
* of the power of the Amiga.  And it is only 10 pages! *
********************************************************

jesup@cbmvax.commodore.com (Randell Jesup) (03/29/91)

>>Question number two:
>>The program exits without restoring multitasking, still multitasking starts
>>again when the program ends. Why?

	Two things happen: if you Wait() while disabled, exec re-enables
interrupts for you.  Second, Disable() is remembered as part of your task.
During task removal, exec re-enables interrupts, removes Forbid()s, etc
(since they're stored in the task structure, this is almost automatic).

-- 
Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com  BIX: rjesup  
Thus spake the Master Ninjei: "To program a million-line operating system
is easy, to change a man's temperament is more difficult."
(From "The Zen of Programming")  ;-)

zap@lysator.liu.se (Zap Andersson) (03/29/91)

bairds@eecs.cs.pdx.edu (Shawn L. Baird) writes:

>d85-jmh@nada.kth.se (Jan-Olof Hendig) writes:

>>x:
>>	move #4000,$dff09a ; Kill multitasking

UGLIEST I've SEEN TODAY! BLEACH!

>Personally, when writing a program that takes over the machine (as I have
>been practicing recently) I do a few things. First, I save a pointer to the
>old copper, which can be found in the GfxBase structure (this works on 2.0
>as well, and I've seen some demos where the screen wasn't restored
>properly under 2.0). Next, I call Forbid() to disable everything but
>interrupts. I then disable all DMA and then restore DMA to the copper,
>the blitter, bitplanes and audio, which is usually all I use. I make all of
>my OS calls before shutting down with Forbid() by the way. Calls such as
>AllocMem, etc. Upon restoration I try to reverse the process, enabling DMA,
>putting the saved copper into the register and strobing it and then calling
>Permit(). This is my guess as to what a compliant assembly language program
>that wants to return the OS when it finishes does. If anyone has any
>suggestions as to what else I might want to try to help save, be my guest.
>I assume (I haven't tried it yet) that I should be leery of OS calls while
>in a Forbid()den state, such as disk I/O, but I'm not sure yet. Any info
>would be appreciated.

There is no restricion in calling OS stuff while in a Forbid(), since the OS
is smarther than that: Forbid() only turns off multitasking while YOUR process wants the processor! I.e. you may forbid all you like, but when you do any kind
of waiting-function, such as WaitTOF(), WaitPort() or similiar (I use a lot of WaitTOF()  in my hacks) the OS is running. But YOUR process should NEVER notice this, since it has MAXIMUM priority. Yes, that is really what forbid does,
crank up your process's priority to infinity. But, as all good multitaskers,
nomatter how high priority, you don't get the processor while waiting for
something.


>>No flames please, just constructive answers.

>I hope this was at least somewhat constructive and maybe even helpful. ;)

>>Jan-Olof Hendig
>---
> Shawn L. Baird, bairds@eecs.ee.pdx.edu, Wraith on DikuMUD
> The above message is not licensed by AT&T, or at least, not yet.
-- 
* * * * * * * * * * * * * * * * *          (This rent for space)
* My signature is smaller than  * Be warned! The letter 'Z' is Copyright 1991
* yours!  - zap@lysator.liu.se  * by Zap Inc. So are the colors Red, Green and
* * * * * * * * * * * * * * * * * Greenish-yellow (Blue was taken by IBM) 
--
* * * * * * * * * * * * * * * * *          (This rent for space)
* My signature is smaller than  * Be warned! The letter 'Z' is Copyright 1991
* yours!  - zap@lysator.liu.se  * by Zap Inc. So are the colors Red, Green and
* * * * * * * * * * * * * * * * * Greenish-yellow (Blue was taken by IBM) 

dillon@overload.Berkeley.CA.US (Matthew Dillon) (03/31/91)

In article <545@lysator.liu.se> zap@lysator.liu.se (Zap Andersson) writes:
>bairds@eecs.cs.pdx.edu (Shawn L. Baird) writes:
>>d85-jmh@nada.kth.se (Jan-Olof Hendig) writes:
>>
>>properly under 2.0). Next, I call Forbid() to disable everything but
>>interrupts. I then disable all DMA and then restore DMA to the copper,
>>the blitter, bitplanes and audio, which is usually all I use. I make all of
>>
>There is no restricion in calling OS stuff while in a Forbid(), since the OS
>is smarther than that: Forbid() only turns off multitasking while YOUR process wants the processor! I.e. you may forbid all you like, but when you do any kind
>of waiting-function, such as WaitTOF(), WaitPort() or similiar (I use a lot of WaitTOF()  in my hacks) the OS is running. But YOUR process should NEVER notice this, since it has MAXIMUM priority. Yes, that is really what forbid does,
>crank up your process's priority to infinity. But, as all good multitaskers,
>nomatter how high priority, you don't get the processor while waiting for
>something.
>
>>>Jan-Olof Hendig
>>---
>> Shawn L. Baird, bairds@eecs.ee.pdx.edu, Wraith on DikuMUD
>> The above message is not licensed by AT&T, or at least, not yet.
>--
>* * * * * * * * * * * * * * * * *	    (This rent for space)
>* My signature is smaller than  * Be warned! The letter 'Z' is Copyright 1991
>* yours!  - zap@lysator.liu.se  * by Zap Inc. So are the colors Red, Green and
>* * * * * * * * * * * * * * * * * Greenish-yellow (Blue was taken by IBM)

    Essentially, you are correct, Forbid() is a wonderful way to take
    over the machine... but you also want to increase your task priority
    (or decrease other task's priorities) so that when the operation you
    run is complete, EXEC will *immediately* give you the CPU back.

    I.E. you make a DOS call:	Read(....), say, when that Read is done
    and DOS replies the packet, you want your task to IMMEDIATELY continue
    running and not allow other tasks (such as the input.device) to
    necessarily get CPU.

    Actually, as per my previous message, all that is really necessary
    is that you make your task the highest priority, period.

    I am happy to see that others have caught on to this excellent method.

    It doesn't break the machine
    It doesn't break the OS
    nor memory
    nor resources (you just obtain them normally)
    nor devices and handlers (i.e. the hard disk still works)
    the user doesn't have to reboot
    the game can be installed on an HD
    It doesn't require taking the machine completely over
    You get all the CPU when you need it
    ... and the machine goes back to normal when you quit

					-Matt
--

    Matthew Dillon	    dillon@Overload.Berkeley.CA.US
    891 Regal Rd.	    uunet.uu.net!overload!dillon
    Berkeley, Ca. 94708
    USA

Ed_Meyer@mindlink.UUCP (Ed Meyer) (04/01/91)

> dillon@overload.Berkeley.CA.US writes:
> 
>     Actually, as per my previous message, all that is really necessary
>     is that you make your task the highest priority, period.
> 
>     I am happy to see that others have caught on to this excellent method.
> 
>     It doesn't break the machine
>     It doesn't break the OS
>     nor memory
>     nor resources (you just obtain them normally)
>     nor devices and handlers (i.e. the hard disk still works)
>     the user doesn't have to reboot
>     the game can be installed on an HD
>     It doesn't require taking the machine completely over
>     You get all the CPU when you need it
>     ... and the machine goes back to normal when you quit
> 
>                                         -Matt
> --
> 
>     Matthew Dillon          dillon@Overload.Berkeley.CA.US
>     891 Regal Rd.           uunet.uu.net!overload!dillon
>     Berkeley, Ca. 94708
>     USA

Matt, I think I saw somewhere, "A genius sees the obvious."

Ed Meyer

honp9@menudo.uh.edu (Jason L. Tibbitts III) (04/02/91)

In article <5343@mindlink.UUCP> Ed_Meyer@mindlink.UUCP (Ed Meyer) writes:
>> dillon@overload.Berkeley.CA.US writes:
>> 
>>     Actually, as per my previous message, all that is really necessary
>>     is that you make your task the highest priority, period.
>> 
>>     I am happy to see that others have caught on to this excellent method.
[...]
>>                                         -Matt

I hate to do this, but what happens if your hard disk controller employs
delayed writes?  (Some do.)  If you are the highest priority task and the
OS returns control to you before a write occurs, then when does it happen?
Probably the next time you WAIT(), but that might be a long time.

I'd like to know more on how the machine functions when your task is CPU
intensive and running at maximum priority.

-- 
Jason L. Tibbitts III  | Moderator: comp.sys.amiga.reviews
"Blob Shop Programmers:| Send submissions to HONP9@menudo.uh.edu
 Because We're Bored!" | Check comp.sys.amiga.reviews for submissions
Disclaimer: Opinions...| guide, disclaimers, etc.               Fnord.

jesup@cbmvax.commodore.com (Randell Jesup) (04/02/91)

In article <1991Apr2.005933.28315@menudo.uh.edu> honp9@menudo.uh.edu (Jason L. Tibbitts III) writes:
>I hate to do this, but what happens if your hard disk controller employs
>delayed writes?  (Some do.)  If you are the highest priority task and the
>OS returns control to you before a write occurs, then when does it happen?
>Probably the next time you WAIT(), but that might be a long time.

	You force a flush (ACTION_FLUSH) before going back into your tight
loop.

-- 
Randell Jesup, Keeper of AmigaDos, Commodore Engineering.
{uunet|rutgers}!cbmvax!jesup, jesup@cbmvax.commodore.com  BIX: rjesup  
Disclaimer: Nothing I say is in anything other than my personal opinion.
Thus spake the Master Ninjei: "To program a million-line operating system
is easy, to change a man's temperament is more difficult."
(From "The Zen of Programming")  ;-)

peterk@cbmger.UUCP (Peter Kittel GERMANY) (04/02/91)

In article <20197@cbmvax.commodore.com> jesup@cbmvax.commodore.com (Randell Jesup) writes:
>
>	Two things happen: if you Wait() while disabled, exec re-enables
>interrupts for you.  Second, Disable() is remembered as part of your task.
>During task removal, exec re-enables interrupts, removes Forbid()s, etc
>(since they're stored in the task structure, this is almost automatic).

Ha! Still someone around who claims there is no resource tracking in 
Amiga OS??? Look: we have at least *some* of it! :-)))

(Sorry, couldn't resist)

-- 
Best regards, Dr. Peter Kittel  // E-Mail to  \\  Only my personal opinions... 
Commodore Frankfurt, Germany  \X/ {uunet|pyramid|rutgers}!cbmvax!cbmger!peterk

dillon@overload.Berkeley.CA.US (Matthew Dillon) (04/03/91)

In article <1991Apr2.005933.28315@menudo.uh.edu> honp9@menudo.uh.edu (Jason L. Tibbitts III) writes:
>In article <5343@mindlink.UUCP> Ed_Meyer@mindlink.UUCP (Ed Meyer) writes:
>>> dillon@overload.Berkeley.CA.US writes:
>>>
>>>	Actually, as per my previous message, all that is really necessary
>>>	is that you make your task the highest priority, period.
>>>
>>>	I am happy to see that others have caught on to this excellent method.
>[...]
>>>					    -Matt
>
>I hate to do this, but what happens if your hard disk controller employs
>delayed writes?  (Some do.)  If you are the highest priority task and the
>OS returns control to you before a write occurs, then when does it happen?
>Probably the next time you WAIT(), but that might be a long time.
>
>I'd like to know more on how the machine functions when your task is CPU
>intensive and running at maximum priority.
>
>--
>Jason L. Tibbitts III	| Moderator: comp.sys.amiga.reviews

    Yes, something like that could indeed happen in which case the
    operation gets delayed, possibly for a long time.  I think it's
    a non-problem in terms of writes, though, a game doesn't normally
    need to write to disk during critical action, and when it is doing
    something like displaying the title screen or saving the game
    it can easily run at a normal priority.

				    -Matt

>"Blob Shop Programmers:| Send submissions to HONP9@menudo.uh.edu
> Because We're Bored!" | Check comp.sys.amiga.reviews for submissions
>Disclaimer: Opinions...| guide, disclaimers, etc.		 Fnord.

--

    Matthew Dillon	    dillon@Overload.Berkeley.CA.US
    891 Regal Rd.	    uunet.uu.net!overload!dillon
    Berkeley, Ca. 94708
    USA

greg@ccwf.cc.utexas.edu (Greg Harp) (04/03/91)

In article <1991Apr2.005933.28315@menudo.uh.edu> honp9@menudo.uh.edu 
  (Jason L. Tibbitts III) writes:
>>> dillon@overload.Berkeley.CA.US writes:
>>> 
>>>     Actually, as per my previous message, all that is really necessary
>>>     is that you make your task the highest priority, period.
>>> 
>>>     I am happy to see that others have caught on to this excellent method.
>>>                                         -Matt

>I hate to do this, but what happens if your hard disk controller employs
>delayed writes?  (Some do.)  If you are the highest priority task and the
>OS returns control to you before a write occurs, then when does it happen?
>Probably the next time you WAIT(), but that might be a long time.

I'd say you have a much better chance of having that write occur at some 
later time than if the program you ran chewed up and spit out the OS. :)

Actually, since the program should only pop its priority up when it needs it
(likely not 100% of the time -- loading the next level/screen doesn't take
100% of the CPU or any fancy copper tricks, FrEx) the write would probably
occur later without complications.  

At least that way the user has the option of getting some work done between
chokeholds on the CPU.  If they aren't running anything else then they still
have the entire machine to devote to loading.

>Jason L. Tibbitts III  | Moderator: comp.sys.amiga.reviews
>"Blob Shop Programmers:| Send submissions to HONP9@menudo.uh.edu
> Because We're Bored!" | Check comp.sys.amiga.reviews for submissions
>Disclaimer: Opinions...| guide, disclaimers, etc.               Fnord.

-- 
       Greg Harp       |"How I wish, how I wish you were here.  We're just two
                       |lost souls swimming in a fishbowl, year after year,
greg@ccwf.cc.utexas.edu|running over the same ground.  What have we found?
  s609@cs.utexas.edu   |The same old fears.  Wish you were here." - Pink Floyd

jbickers@templar.actrix.gen.nz (John Bickers) (04/04/91)

Quoted from <1991Apr2.005933.28315@menudo.uh.edu> by honp9@menudo.uh.edu (Jason L. Tibbitts III):
> I'd like to know more on how the machine functions when your task is CPU
> intensive and running at maximum priority.

    Some of the more polite coder demos nowadays do this. I guess
    people with hardware problems doing this would be in the same sort
    of boat as folks who have problems with non-word-aligned addressing
    on some accelerator boards, etc.

> Jason L. Tibbitts III  | Moderator: comp.sys.amiga.reviews
--
*** John Bickers, TAP, NZAmigaUG.        jbickers@templar.actrix.gen.nz ***
***         "Patterns multiplying, re-direct our view" - Devo.          ***