home *** CD-ROM | disk | FTP | other *** search
- How to write demos that work (Version 2)
- ========================================
-
- (or How to bash the metal and get away with it)
-
- by Comrade J, Share and Enjoy (retired)
-
-
- Are you fed up of downloading a new demo, running it and finding
- your Amiga power light sitting there flashing at you? Are you
- tired of the contents of your chipram flashing through the bitplane
- registers in a rather random fashion when you run 'Duffex's
- Megademo'?
-
- Do you want demos that actually run? Because I do. I'm fed up
- completely with all these rubbish coders who can't do their job
- properly...
-
- Now, since those long days and nights bashing away at Share and Enjoy
- demos I've been involved in all sorts of Amiga programming, involving
- new AGA machines, CD, 16-bit audio and all sorts of other
- wonderful things that I can't talk about, both via the OS and at a
- hardware level.
-
- Most demos I've seen use similar startup code to that I was using back
- in 1988. Hey guys, wake up! The Amiga has changed quite a bit since
- then.
-
- So. Here are some tips on what to do and what not to do:
-
-
-
-
-
- 1. RTFM.
- ========
-
- Read the F**king manuals. All of them. Borrow them off friends or from
- your local public library if you have to. Make sure you follow the
- hardware rules to the letter. If it says "Leave this bit cleared" then
- don't set it!
-
- There is a lot of useful informatiton in the 'boring' OS Rom Kernal
- Manuals that you may be suprised to know.
-
- Read the "General Amiga Development Guidelines" in the new (grey)
- Hardware Reference Manual and follow them TO THE LETTER.
-
- Don't use self-modifying code. A common bit of code I see is:
-
- ... in the setup code
-
- move.l $6c.w,old
-
- ... at the end of the interrupt
-
- movem.l (sp)+,a0-a6/d0-d7
- dc.w $4ef9 ; jmp instruction
- old dc.l 0 ; self modifying!!!!
-
- DONT DO THIS!
-
- This is much better (although it still hits $6c which is not a
- good thing - It's much better to use AddIntServer() to call your
- interrupts, but more on that next time....)
-
- ... in the setup code
-
- move.l $6c.w,old
-
- ... at the end of the interrupt
-
- movem.l (sp)+,a0-a6/d0-d7
- move.l old,-(sp) ; push old address to stack
- rts
-
- ... in your data section
-
- old dc.l 0
-
-
- 68020 and above processors with cache enabled often barf at the first
- piece of code (the cache still contains the JMP 0 instruction
- which isn't then altered), but the second piece works fine on the '040.
-
-
-
-
-
- 2. Proper Copper startup.
- =========================
-
- IF you are going to use the copper then this is how you should set it
- up. The current workbench view and copper address are stored, the
- system frozen, and then the copper enabled. On exit the workbench
- view is restored.
-
- This guarantees your demo will run on an AGA (Amiga 1200) machine,
- even if set into some weird screenmode before running your code.
-
- Otherwise under AGA, the hardware registers can be in some strange states
- before your code runs, beware!
-
- The LoadView(NULL) forces the display to a standard, empty position,
- flushing the crap out of the hardware registers: Note. There is
- a bug in the V39 OS on Amiga 1200/4000 and the sprite resolution is
- *not* reset, you will have to do this manually if you use sprites...
-
- Two WaitTOF() calls are needed after the LoadView to wait for both the
- long and short frame copperlists of interlaced displays to finish.
-
-
- I'm writing this code off the top of my head, if you spot any obvious bugs
- email me at the address below, or leave mail to me on Bad Dreams BBS.
-
- include "exec/macros.i"
- include "exec/funcdef.i" ; keep code simple and
- include "exec/exec_lib.i" ; easy to read - use
- include "graphics/gfxbase.i" ; the includes!
- include "graphics/gfx_lib.i"
- include "misc/easystart.i" ; Allows startup from
- ; icon
-
- section mycode,code ; need not be in chipram
-
- StartCopper:
- move.l 4.w,a6 ; get ExecBase
- lea gfxname,a1 ; graphics name
- moveq #0,d0 ; any version
- jsr _LVOOpenLibrary(a6)
- tst.l d0
- beq End ; failed to open? Then quit
- move.l d0,gfxbase
- move.l d0,a6
- move.l gb_ActiView(a6),wbview
- ; store current view address
- ; gb_ActiView = 32
-
- move.w #0,a1 ; clears full long-word
- jsr _LVOLoadView(a6) ; Flush View to nothing
-
- jsr _LVOWaitTOF(a6) ; Wait once
- jsr _LVOWaitTOF(a6) ; Wait again.
-
- ; Now you can hit the copper!
-
- move.l 4.w,a6
- jsr _LVOForbid(a6) ; Suspend multitasking!
-
- move.l mycopper,$dff080 ; bang it straight in.
- ; (DO NOT F**K WITH GFXBASE!)
-
- *** DO YOUR FUNKY STUFF HERE ***
-
-
- CloseDown: move.l 4.w,a6
- jsr _LVOPermit(a6) ; Enable multitasking
-
- move.l wbview,a1
- move.l gfxbase,a6
- jsr _LVOLoadView(a6) ; Fix view
-
- move.l gb_copinit(a6),$dff080 ; Kick it into life
- ; copinit = 36
- move.l a6,a1
- move.l 4.w,a6
- jsr _LVOCloseLibrary(a6) ; EVERYONE FORGETS THIS!!!!
-
- End: rts
-
- section mydata,data_C ; keep data & code seperate!
-
- copperlist dc.w $180,0 ; background black
- dc.w $5c07,$fffe ; wait for $5c07,$fffe
- dc.w $180,$ff0 ; background yellow
- dc.w $ffff,$fffe
- dc.w $ffff,$fffe ; Copper end (always do two
- ; copper end cmds!)
-
- wbview dc.l 0
- wbcop dc.l 0
- gfxbase dc.l 0
- gfxname dc.b "graphics.library",0
-
-
- 3. Your code won't run from an icon.
- ====================================
-
- You stick an icon for your new demo (not everyone uses the CLI!) and
- it either crashes or doesn't give back all the RAM it uses. Why?
-
- Icon startup needs specific code to reply to the workbench message.
- With the excellent Hisoft Devpac assember, all you need to do is add
- the line
-
- include "misc/easystart.i"
-
- and it magically works!
-
- For those without Devpac, here is the relevent code:
-
- ---------------------------------------------------------
-
- * some startup code to make a Workbench execute look like the CLI
- * based loosely on RKM Vol 1 page 4-36
-
- * Include this at the front of your program
- * after any other includes
- * note that this needs exec/exec_lib.i
-
- IFND EXEC_EXEC_I
- include "exec/exec.i"
- ENDC
- IFND LIBRARIES_DOSEXTENS_I
- include "libraries/dosextens.i
- ENDC
-
-
- movem.l d0/a0,-(sp) save initial values
- clr.l returnMsg
-
- sub.l a1,a1
- move.l 4.w,a6
- jsr _LVOFindTask(a6) find us
- move.l d0,a4
-
- tst.l pr_CLI(a4)
- beq.s fromWorkbench
-
- * we were called from the CLI
- movem.l (sp)+,d0/a0 restore regs
- bra end_startup and run the user prog
-
- * we were called from the Workbench
- fromWorkbench
- lea pr_MsgPort(a4),a0
- move.l 4.w,a6
- jsr _LVOWaitPort(A6) wait for a message
- lea pr_MsgPort(a4),a0
- jsr _LVOGetMsg(A6) then get it
- move.l d0,returnMsg save it for later reply
-
- * do some other stuff here RSN like the command line etc
- nop
-
- movem.l (sp)+,d0/a0 restore
- end_startup
- bsr.s _main call our program
-
- * returns to here with exit code in d0
- move.l d0,-(sp) save it
-
- tst.l returnMsg
- beq.s exitToDOS if I was a CLI
-
- move.l 4.w,a6
- jsr _LVOForbid(a6)
- move.l returnMsg(pc),a1
- jsr _LVOPermit(a6)
-
- exitToDOS
- move.l (sp)+,d0 exit code
- rts
-
- * startup code variable
- returnMsg dc.l 0
-
- * the program starts here
- even
- _main
-
- ---------------------------------------------------------
-
-
-
-
- 4. How do I tell if I'm running on an Amiga 1200/4000?
- ======================================================
-
- Do *NOT* check library revision numbers, V39 OS can and does
- run on standard & ECS chipset machines (This Amiga 3000
- is currently running V39).
-
- This code will check for AGA
-
- move.w $dff07c,d0
- cmp.b #$f8,d0
- bne.s .notaga
-
- ; Do your funky AGA Stuff in here!
-
- .notaga
-
-
-
-
-
- 5. Use Relocatable Code
- =======================
-
- If you write demos that run from a fixed address you should be shot.
- NEVER EVER DO THIS. It's stupid and completely unnecessary.
-
- If you require bitplanes to be on a 64Kb boundary then try the
- following (in pseudo-code because I'm too lazy to write it in asm
- for you):
-
- for c=0 to (top of chip ram) step 65536
-
- if AllocAbs(c,NUMBER_OF_BYTES_YOU_WANT) == TRUE then goto ok:
-
- next c:
-
- print "sorry. No free ram. Close down something and retry demo!"
- stop
-
- ok: Run_Outrageous_demo with mem at c
-
- Keep your code in multiple sections. Several small sections are
- better than one large section, they will more easilly fit in and run
- on a system with fragmented memory.
-
-
-
-
- 6. Don't Crunch demos!
- ======================
-
- Don't ever use Tetrapack or Bytekiller based packers. They are crap.
- Many more demos fall over due to being packed with crap packers than
- anything else. If you are spreading your demo by electronic means
- (which most people do now, the days of the SAE Demodisks are long
- gone!) then assemble your code, and use LHARC to archive it, you
- will get better compression with LHARC than with most runtime
- packers.
-
- If you *have* to pack your demos, then use Powerpacker 4+, Turbo
- Imploder or Titanics Cruncher, which I've had no problems with myself.
-
-
-
-
- 7. Don't use the K-Seka assembler!
- ==================================
-
- It's dead and buried. Get a life, get a real assembler. Hisoft Devpac
- is probably the best all-round assembler, although I use ArgAsm
- which is astonishingly fast.
-
-
-
- 8. Don't use the hardware unless you have to!
- =============================================
-
- This one is aimed particularly at utility authors. I've seen some
- *awfully* written utilities, for example (although I don't want
- to single them out as there are plenty of others) the Kefrens
- IFF converter.
-
- There is NO REASON why this has to have it's own copperlist. A standard
- OS-friendly version opening it's own screen works perfectly (I
- still use the original SCA IFF-Converter), and multitasks properly.
-
-
- 9. Beware bogus input falling through to Workbench
- ==================================================
-
- If you keep multitasking enabled and run your own copperlist remember
- that any input (mouse clicks, key presses, etc) fall through to the
- workbench. The correct way to get around this is to add an input
- server to the IDCMP food chain (see - you *do* have to read the
- other manuals!) at a high priority to grab all input events before
- workbench/cli can get to them.
-
- Look at the sourcecode for Protracker for an excellent example of
- how to do the job properly. Well done Lars!
-
-
-
- 10. Have fun!
- =============
-
- Too many people out there (particularly the American OS-Lamic
- Fundamentalists) try to tell us that you should never program at a hardware
- level. If you're programming for fun, ignore them! But try and put
- a little thought into how your code will work on other machines,
- nothing annoys people more than downloading 400Kb of demo and then
- finding it blows up on their machines. I'm not naming any names, but
- there are quite a few groups who I have no intention of downloading
- their demos again because I know it's a waste of download. With
- the launch of the Amiga 1200 you cannot just write for 1.3 Amiga
- 500's any more. Let's go out there and write some shit hot demos!
-
-
- 11. Don't Publish Code you haven't checked!
- ===========================================
-
- Thanks to Timo Rossi for spotting the stupid bug in my copper
- setup routine (using LOFList instead of copinit). Funnily enough
- my own setup routine uses the correct copinit code:
-
- Please ignore the original file and use this instead.
-
-
-
-
- 12. Read this, it's new!
- ========================
-
- A few points I've been asked to clear up:
-
- Always use two copper end commands ie $FFFF,$FFFE,$FFFF,$FFFE.
- Why? I'm not sure, but it definately said in the Harwdare
- Ref book that you should, ISTR that some Amiga 1000's had a dodgy
- copper that could overrun the first Copper End. If you look
- at OS copperlists they all have (or at least did when I last looked!)
- two END commands.
-
- The 68010 and above processors have a Vector Base Register (VBR)
- that allows the exception vector table to be placed anywhere in
- RAM, including fast ram. This gives some speed benefits to systems
- with this running, but at a cost.
-
- Anything that accesses the interrupt locations directly, for example:
-
- move.l $6c.w,old
- move.l MyWickedInterruptCode,$6c.w
-
- won't work... Unfortunately this includes 99.9% of demos.
-
- I'm not going to tell you how to use the VBR to calculate
- this, if you want to learn, get the excellent book 680x0 Programming
- By Example, by Stan Kelly-Bootle (Howard Sams & Co). He gets paid
- for telling you how to do this and I don't :-)
-
- Plus that's not the best way to use interrupts on the Amiga. You
- *should* use the Exec.Library function AddIntServer, but I know
- most of you have a theological dislike of Library routines, only
- opening the graphics.library to viciously poke it!
-
- 13 Using the blitter.
- =====================
-
- If you are using the blitter in your code and you are leaving the
- system intact (as you should) always use the graphics.library
- functions OwnBlitter() and DisownBlitter() to take control
- of the blitter. Remember to free it for system use, many system
- functions (including floppy disk data decoding) use the blitter.
-
- Another big mistake I've seen is with blitter/processor timing.
-
- Assuming that a particular routine will be slow enough that a blitter
- wait is not needed is silly. Always check for blitter finished, and
- wait if you need to.
-
- Don't assume the blitter will always run at the same speed too. Think
- about how your code would run if the processor or blitter were running
- at 100 times the current speed. As long as you keep this in mind,
- you'll be in a better frame of mind for writing compatable code.
-
-
- 14 NTSC
- =======
-
- As an European myself, I'm naturally biased agains the inferior video
- system, but even though the US & Canada have a relatively minor Amiga
- community compared with Europe (Sorry, it's true :-) we should still
- help them out, even though they've never done a PAL Video Toaster for
- us (sob!).
-
- You have two options.
-
- Firstly, you could write your code only to use the first 200 display
- lines, and leave a black border at the bottom. This annoys PAL owners,
- who rightly expect things to have a full display. It took long enough
- for European games writers to work out that PAL displays were better.
-
- You could write code that automatically checked which system it is
- running on and ran the correct code accordingly:
-
- (How to check: Note, this is probably not the officialy supported method,
- but so many weird things happen with new monitors on AGA machines that
- I prefer this method, it's simpler, and works under any Kickstart)
-
- move.l 4.w,a6 ; execbase
- cmp.b #50,PowerSupplyFrequency(a6) ; 531(a6)
- beq.s .pal
-
- jmp I'm NTSC (or more accurately, I'm running from 60Hz power)
- .pal jmp I'm PAL (or I'm running from 50hz power).
-
-
- If people have already switched modes to PAL, or if they are running
- some weird software like the ICD Flicker Free Video Prefs thingy, then
- this completely ignores them, but that serves them right for trying
- to be clever :-)
-
- Probably better would be to check VBlankFrequency(a6) [530(a6)]
- as well, if both are 60Hz then it's definately a NTSC machine. If
- one or more are 50Hz, then it's probably a better idea to run in PAL.
-
- Now, if you want to force a machine into the other display system
- you need some magic pokes: Here you go (beware other bits in
- $dff1dc can do nasty things. One bit can reverese the polarity
- on the video sync, not to healthy for some monitors I've heard...)
-
- To turn a NTSC system into PAL (50Hz)
-
- move.w #32,$dff1dc ; Magically PAL
-
- To turn a PAL system into NTSC (60Hz)
-
- move.w #0,$dff1dc ; Magically NTSC
-
- Remember: Not all displays can handle both display systems!
- Commdore 1084/1084S, Philips 8833/8852 and multisync monitors
- will, and very few TV's will handle PAL signals (especially
- if being used with a NTSC Amiga modulator). I gather that
- most NTSC machines are Amiga 2000's, so perhaps this isn't
- a problem.
-
- So come on you NTSC users, tell us how you would prefer
- the demos written!
-
-
- Thanks to everyone who has replied. Any more questions, queries,
- or "CJ, you got it wrong again!" type mail to the email
- address below....
-
-
- --------------------------------------------------------------------
-
- This text is Copyright (C) 1992 Share and Enjoy, but may be freely
- distributed in any electronic form.
-
- All opinions expressed in this article are my own, and in no way
- reflect those of Share and Enjoy or any BBS this file may be found
- on.
-
- I didn't write this for fun, I wrote it for you to use!
-
- If you strongly disagree with anything I write, or you want to send me
- some source or demos to test on Amiga 1200/4000 etc, or you have
- questions about Amiga programming, or suggestions for future articles,
- or just want to chat about the best way to optimise automatic copperlist
- generation code, then contact me via email at:
-
- comradej@althera.demon.co.uk or by email at Bad Dreams BBS.
-
-