home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-01-05 | 34.5 KB | 1,076 lines |
- How to write demos that work (Version 3) - 31/12/92
- ===================================================
-
- (or How to bash the metal and get away with it)
-
- by Comrade J, Share and Enjoy (retired)
-
- Thanks to everyone on the internet for sending their suggestions,
- bug reports and comments to me on this article. I'll try and keep
- this up to date and posted here frequently. Coming soon, source
- code for a small intro using all these techniques that you can
- use as the base for whatever you want to do....
-
- --------------------------------------------------------------------
-
- 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.
-
- Read the "General Amiga Development Guidelines" in the new (grey)
- Hardware Reference Manual and follow them TO THE LETTER.
- If it says "Leave this bit cleared" then don't set it!
-
- 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,
-
- ... in the setup code
-
- move.l VBRBase(a0)
- move.l $6c(a0),old ; see under VBR below....
-
- ... 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
-
-
- It has been suggested to me that instead of using the GfxBase gb_ActiView
- I should instead use the Intuition ib_ViewLord view. This will work
- just as well, but there has been debate as to whether in the future
- with retargetable graphics (RTG) this will work in the same way. As the
- GfxBase is at a lower level than Intuition, I prefer to access it this
- way (but thank's for the suggestion Boerge anyway!).
-
-
- 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. Copper End
- ==============
- 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.
-
- Having just read through the new grey Hardware Reference Manual, I
- can find no mention of this at all. Odd. Perhaps I dreamt it?
- Who knows? :-) Certainly if you're using copperlists that get
- heavily modified two end commands will prevent a bogus SKIP
- command dropping the copper program counter off the end of your
- copperlist...
-
-
- 13. Vector Base Register (68010 and up)
- =======================================
-
- 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.
-
- Boerg Noest (borgen@stud.cs.uit.no) writes....
-
- > Next your text should mention VBR. It's easy - like this:
- > move.l 4.w a6
- > moveq #0,d0
- > btst.b #AFB_68010,AttnFlags+1(a6)
- > beq .done
- > movec vbr,d0
- >.done
- > move.l d0,VBRBase
- > rts
- >
- then you just
- > move.l VBRBase,a0
- move.l $6c(a0),oldinterrupt
- > move.l #myinterrupt,$6c(a0)
- >
-
- Ok. I don't know how many people use the VBR to offset their interrupts,
- I certainly don't as it breaks too much software on my 3000, and it
- only gives a minimal speed increase. The main benefit of the 68010
- over the 68000 is the loop cache mode. Common 3 word loops like:
-
- moveq #50,d0
- .lp move.b (a0)+,(a1)+ ; one word
- dbra d0,.lp ; two words
-
- are recognised as loops and speed up dramatically on 68010.
-
-
-
- 14 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.
-
- Another big source of blitter problems is using the blitter in interrupts.
-
- Most demos do all processing in the interrupt, with only a
-
- .wt btst #6,$bfe001 ; is left mouse button clicked?
- bne.s .wt
-
- loop outside of the interrupt. However, some demos do stuff outside the
- interrupt too. Warning. If you use blitter in both your interrupt
- and your main code, (or for that matter if you use the blitter via the
- copper and also in your main code), you may have big problems....
-
- Take this for example:
-
- lea $dff000,a5
- bsr WaitBlitterFinish ; check bits for blitter ready
- move.l #-1,BLTAFWM(a5) ; set FWM and LWM in one go
- move.l #source,BLTAPT(a5)
- move.l #dest,BLTDPT(a5)
- move.w #100111110000,BLTCON0(a5)
- move.w #0,BLTCON1(a5)
- move.w #64*height+width/2,BLTSIZE(a5) ; trigger blitter
-
- There is *nothing* stopping an interrupt, or copper, triggering a
- blitter operation between the WaitBlitterFinish call and
- your final BLTSIZE blitter trigger. This can lead to total system blowup.
-
- Code that may, by luck, work on standard speed machines may die horribly
- on faster processors due to timing differences causing this type of
- problem to occurr.
-
- The safest way to avoid this is to keep all your blitter calls together,
- use the copper exclusively, or write a blitter-interrupt routine to
- do your blits for you.
-
- Always remember to do two blitter-wait-checks... eg:
-
- btst.b #DMAB_BLTDONE-8,DMACONR(a1)
- btst.b #DMAB_BLTDONE-8,DMACONR(a1)
-
- The first may not give the correct result on machines with early
- (non Fat) Agnus chips (eg Amiga 1000, German A2000).
-
- 15 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.
-
- Under Kickstart 2.04 or greater, the Display Database can be accessed.
- Any program can enquire of the database what type of displays
- are available, so for example "I want a 50hz 15Khz PAL screen. Can
- I display it on this Amiga?" (Unfortunately it doesn't take
- an ASCII string like that, but it's not that more dificult). Of
- course many users will have the default monitor installed (PAL or
- NTSC) and not realise that they can have extra modes by dragging
- the monitor icon into their Monitors drawer, and of course
- this doesn't work on Kickstart 1.3 machines.
-
- 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!
-
-
-
- 16 Programming AGA hardware
- ===========================
- I've just got this interesting text file which I thought should be
- included with this document:
-
- The followings informations were gathered by Junkie/PMC Fr and Yragael.
-
- Junkie bought a 1200 some days ago and started quickly to dasm the
- copperlist of the workbench. Thanx to his work of prime importance and his
- impressive speed which leads me to dasm the copperlist too, I (Yragael)
- brings you the followings informations.
-
- More should follow as long as we will not get the hardware reference
- manual.
-
- We are waiting for your works on 1200 and your cooperation to the trip into
- the hardware of the A1200.
-
- (next issue: Sprite corrections, HAM8+, other graphic modes, 3 words
- copperlists ...)
-
- ***************************************************************************
-
- USING THE SUPERHIRES MODE
-
- To use the SuperHires mode (1280 pixels wide), just use the bit 6 of
- register $0100
-
- bit 6 | Mode SuperHires
- -----------------------
- 0 | Non selectionne
- -----------------------
- 1 | Selectionne
- -----------------------
-
- ***************************************************************************
-
- USING 8 BITPLANES
-
- The number of bitplanes available used to be no more than 7 and was coded
- using the bits 14 to 12 of register $0100. To use 8 bitplanes, just use
- bit 4 of register $0100. The value of bits 14 to 12 will then not be
- considered anymore.
-
- bit 4 | 8 bitplanes mode
- ------------------------
- 0 | Not selected
- ------------------------
- 1 | Selected
- ------------------------
-
- ***************************************************************************
-
- ACCEDING 24 BITS COLORS
-
- The 24 bits color is coded using 2 words:
-
- - the first receives the 4 low bits of each R, G and B componants
- - the second receives the 4 high bits of each R, G and B componants
-
- To modify a color using 24 bits coding, you must use 2 coppers-moves on the
- same color register. The first move must ABSOLUTELY be the move of the
- word of the 3*4 high bits, the second move is the move of the word of the
- 3*4 low bits.
-
- The copper knowns when the move regards the 3*4 low bits or the 3*4 high
- bits by checking the bit 9 of register $0106
-
- bit 9 | Componants access
- -----------------------------------------------------------------
- 0 | Access to the 4 low bits of componants R, G and B
- -----------------------------------------------------------------
- 1 | Access to the 4 high bits of componants R, G and B
- -----------------------------------------------------------------
-
- ex: change $0180 to $00123456 in the copperlist
-
- $01060000
- $01800135
- $01060200
- $01800246
-
- When you want to work using the 12 bits color coding mode, the 3*4 bits
- value you move to the color register is considered by the copper as the 3*4
- high bits. You don't have to care about $0106. It seems bit 9 of register
- $0106 is initialized to 0 at each copjmp.
-
- ***************************************************************************
-
- ACCEDING THE 256 COLORS PALETTE
-
- The amiga don't work with 256 separate color registers. A same color
- register is used several times to code several colors.
-
- The amiga just works with 8 differents palettes of 32 colors each, using
- color registers from $0180 to $01BE.
-
- You can choose the palette you want to access via the bits 11 to 14 of
- register $0106
-
-
- bit 14 | bit 13 | bit 12 | Selected palette
- --------------------------------------------------------
- 0 | 0 | 0 | Palette 0 (color 0 to 31)
- --------------------------------------------------------
- 0 | 0 | 1 | Palette 1 (color 32 to 63)
- --------------------------------------------------------
- 0 | 1 | 0 | Palette 2 (color 64 to 95)
- --------------------------------------------------------
- 0 | 1 | 1 | Palette 3 (color 96 to 125)
- --------------------------------------------------------
- 1 | 0 | 0 | Palette 4 (color 128 to 159)
- --------------------------------------------------------
- 1 | 0 | 1 | Palette 5 (color 160 to 191)
- --------------------------------------------------------
- 1 | 1 | 0 | Palette 6 (color 192 to 223)
- --------------------------------------------------------
- 1 | 1 | 1 | Palette 7 (color 224 to 255)
- --------------------------------------------------------
-
- ex: You want to change color 177 to $00123456
-
- Color 177 is color $01A2 of palette 5
-
- $01065000
- $01800246
- $01065200
- $01800135
-
- ***************************************************************************
-
- SWITCHING THE PALETTE
-
- You can switch colors. The definition of switching color A and color B is:
-
- - Color registers of colors A and B are NOT modified by the switching
- - Color A is displayed using the content of register of color B and
- vice-versa
-
- The switching of palette can't be used on just n colors of the palette.
- Once you choose a switching value, ALL the palette's colors will be
- switched. The switching value is the value separing the colors to be
- switched and is coded with bits 15 to 8 of register $010C.
-
- ex: You want all the colors separated by one color in the colorlist to be
- switched
-
- $0180 <--
- $0182 <--|--
- $0184 <-- |
- $0186 <-----
- $0188 <--------
- . |
- .
- .
-
- Value 2 will be stocked in bits 15 to 8.
-
- The switching works with the palette as if it was a circular palette. I
- mean if if the copper consider color 255 and must switch by 1 the colors,
- color $0180 will be assiocated to color 255.
-
- ***************************************************************************
-
- USING SPRITES IN LOWRES, HIRES AND SUPERHIRES
-
- To change the reolution of the sprite, just use bit 7 and 6 of register
- $0106
-
- bit 7 | bit 6 | Resolution
- --------------------------
- 0 | 0 | Lowres
- --------------------------
- 1 | 0 | Hires
- --------------------------
- 0 | 1 | Lowres
- --------------------------
- 1 | 1 | SuperHires
- --------------------------
-
- ***************************************************************************
-
- USING 16, 32 AND 64 PIXELS WIDE SPRITES
-
- Well, I still have bug there with sprites in 32 or 64 pixels. Sorry but
- the followings informations may have to be corrected.
-
- Use bit 3 and 2 of register $01FC
-
- bit 3 | bit 2 | Wide
- -------------------------
- 0 | 0 | 16 pixels
- -------------------------
- 1 | 0 | 32 pixels
- -------------------------
- 0 | 1 | 32 pixels
- -------------------------
- 1 | 1 | 64 pixels
- -------------------------
-
- The copper doesn't read the spritelist in the same way regarding the wide
- you choose for your sprite
-
- 16 pixels wide reading:
-
- word C1, word C2
- word A1, word B1
- .
- .
- .
- word An, word Bn
- $0000 0000
-
- C1=first control word
- C2=second control word
-
- Ai and Bi are combined via OR to form the sprite
-
- 32 pixels wide reading:
-
- long C1, long C2
- long A1, long B1
- .
- .
- .
- long An, long Bn
- $0000 0000 0000 00000
-
- C1=first control long
- the first control word is the high word of C1. The low word of C1 must
- contain the second control word.
- C2=second control long
- the second control word is the high word of C2. Low word of C2 is $0000
-
- Ai and Bi are combined via OR to form the sprite
-
- 64 pixels wide reading:
-
- double C1, double C2
- double A1, double B1
- .
- .
- .
- double An, double Bn
- $0000 0000 0000 00000 0000 0000 0000 00000
-
- C1=first control double
- C1=W3:W2:W1:W0 (Wi=words)
- W3 is first control word
- W2 and W1 are second control word
- C2=second control double
- C2=W3:W2:W1:W0 (Wi=words)
- W3 is second control word
-
- Ai and Bi are combined via OR to form the sprite
-
- ***************************************************************************
-
- CHANGING THE SPRITE PALETTE
-
- It is possible to choose the color palette of the sprite. This is done by
- the bits 7 and 4 of register $010C.
-
- bit 7 | bit 6 | bit 5 | bit 4 | Starting color of the sprite's palette
- -------------------------------------------------------------------------
- 0 | 0 | 0 | 0 | $0180/palette 0 (coulor 0)
- -------------------------------------------------------------------------
- 0 | 0 | 0 | 1 | $01A0/palette 0 (color 15)
- -------------------------------------------------------------------------
- 0 | 0 | 1 | 0 | $0180/palette 1 (color 31)
- -------------------------------------------------------------------------
- 0 | 0 | 1 | 1 | $01A0/palette 1 (color 47)
- -------------------------------------------------------------------------
- 0 | 1 | 0 | 0 | $0180/palette 2 (color 63)
- -------------------------------------------------------------------------
- 0 | 1 | 0 | 1 | $01A0/palette 2 (color 79)
- -------------------------------------------------------------------------
- 0 | 1 | 1 | 0 | $0180/palette 3 (color 95)
- -------------------------------------------------------------------------
- 0 | 1 | 1 | 1 | $01A0/palette 3 (color 111)
- -------------------------------------------------------------------------
- 1 | 0 | 0 | 0 | $0180/palette 4 (color 127)
- -------------------------------------------------------------------------
- 1 | 0 | 0 | 1 | $01A0/palette 4 (color 143)
- -------------------------------------------------------------------------
- 1 | 0 | 1 | 0 | $0180/palette 5 (color 159)
- -------------------------------------------------------------------------
- 1 | 0 | 1 | 1 | $01A0/palette 5 (color 175)
- -------------------------------------------------------------------------
- 1 | 1 | 0 | 0 | $0180/palette 6 (color 191)
- -------------------------------------------------------------------------
- 1 | 1 | 0 | 1 | $01A0/palette 6 (color 207)
- -------------------------------------------------------------------------
- 1 | 1 | 1 | 0 | $0180/palette 7 (color 223)
- -------------------------------------------------------------------------
- 1 | 1 | 1 | 1 | $01A0/palette 7 (color 239)
- -------------------------------------------------------------------------
-
- ***************************************************************************
-
-
- That's all. Thanx you VERY MUCH to Junkie/PMC Fr for his work.
-
- Written by Yragael
- Chaos. Live it. Learn it. Be it.
-
- _\!/_ The Illuminated Ones _\!/_
- /!\ ««««««««««»»»»»»»»»» /!\
-
- Interesting, eh?
-
-
- 17 Keyboard Timings
- ===================
-
- If you have to read the keyboard by hardware, be very careful
- with your timings. Not only do different processor speeds affect
- the keyboard timings (for example, in the game F-15 II Strike Eagle
- on an Amiga 3000 the key repeat delay is ridiculously slow, you
- ttyyppee lliikkee tthhiiss aallll tthhee ttiimmee. You use
- up an awful lot of Sidewinders very quickly!)
-
- Again, here's something from Boerge:
-
- >Third, you should warn about f**king up the keyboard read timing. My keyboard
- >absolutely does not work with just reading the $bfxxxx turning it to output,
- >and writing the reply, and turning it to input again. I do not have any code
- >that is especially good, but for now I use this:
- > move.b $bfec01,d0 ;get keycode
- > not.b d0
- > lsr.b #1,d0 ;test up/down flag
- > bcs.s .NoStore ;if up, ignore
- >
- > move.b d0,Key
- >.NoStore
- >
- >;handshake
- > bset #6,$bfee01 ;output
- > clr.b $bfec01
- > moveq #4-1,d0
- >.L1 move.b VHPOSR,d1
- >.L2 cmp.b VHPOSR,d1
- > beq.b .L2
- > dbra d0,.L1
- >
- > bclr #6,$bfee01 ;input again
-
- Remember though, if you have system interrupts and workbench enabled,
- keys can fall-through to workbench. For example, press Amiga-Q in
- your demo and you may find Workbench closed on return!
-
-
- 18 How to break out of never-ending loops
- =========================================
-
- Another great tip for Boerge here:
-
- >This is a simple tip I have. I needed to be able to break out of my
- >code if I had neverending loops. I also needed to call my exit code when I did
- >this. Therefore I could not just exit from the keyboard interrupt which I have
- >taken over(along with the rest of the machine). My solution wa to enter
- >supervisor mode before I start my program, and if I set the stack back then
- >I can do an RTE in the interrupt and just return from the Supervisor() call.
- >This is snap'ed from my code:
- >
- > lea .SupervisorCode,a5
- > move.l sp,a4 ;
- > move.l (sp),a3 ;
- > EXEC Supervisor
- > bra ReturnWithOS
- >
- >.SupervisorCode
- > move.l sp,crashstack ; remember SSP
- > move.l USP,a7 ; swap USP and SSP
- > move.l a3,-(sp) ; push return address on stack
- >
- >that last was needed because it was a subroutine that RTSes (boy did I have
- >porblems working out my crashes before I fixed that)
- >Then I have my exit code:
- >
- >ReturnWithOS
- > tst.l crashstack
- > beq .nocrash
- > move.l crashstack,sp
- > clr.l crashstack
- > RTE ; return from supervisor mode
- >.nocrash
- >
- >my exit code goes on after this.
- >
- >This made it possible to escape from an interrupt without having to care
- >for what the exception frames look like.
-
-
-
-
- 19. Version numbers!
- ====================
-
- Put version numbers in your code. This allows the CLI version command
- to determine easily the version of both your source and executable
- files. Some directory utilities allow version number checking too (so
- you can't accidentally copy a newer version of your source over
- an older one, for example). Of course, if you pack your files the
- version numbers get hidden. Leaving version numbers unpacked
- was going to be added to PowerPacker, but I don't know if this is
- done yet.
-
- A version number string is in the format
-
- $VER: howtocode3.txt 3.0 31/12/92.
- ^ ^ ^Version number (date is optional)
- | |
- | | File Name
- |
- | Identifier
-
- The Version command searches for $VER and prints the string it finds
- following it.
-
- For example, adding the line to the begining of your source file
-
- ; $VER: MyFunDemo.s 3.0 31/12/92
-
- and somewhere in your code
-
- dc.b "$VER: MyFunDemo 3.0 31/12/92",0
-
- means if you do VERSION MySource you will get:
-
- MyFunDemo.s 3.0 31/12/92
-
- and if you assemble and do Version MyFunDemo, you'll get
-
- MyFunDemo 3.0 31/12/92
-
- Try doing version howtocode3.txt and see what you get :-)
-
- This can be very useful for those stupid demo compilations
- where everything gets renamed to 1, 2, 3, etc...
-
- Just do version 1 to get the full filename (and real date)
-
-
-
-
- Thanks to everyone who has replied. Any more questions, queries,
- or "CJ, you got it wrong again!" type mail to the email
- address below....
-
- Happy new year!!!!
-
-
-
-
- --------------------------------------------------------------------
-
- 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! Hopefully
- this will grow into a big file that demo coders can 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.
-
-