**This is an old revision of the document!**

Original notes

These are detailed in +Music.s. I add them here as I use them.

Defining Tokens

Return value and parameter lists

Don't forget the terminating -1! If you built it and forgot it, trying to start AMOS Pro will do nothing. Replace with you known good copy and reboot, then try again.

Return value

  • I - none
  • 0 - long
  • 2 - string*

Parameters

  • 0 - long
  • 2 - string*
String parameters

Strings are stored in AMOS with a word for string length (so strings can be up to 65535 characters in length), and then the null-terminated string itself.

Your own routines

You can Rbsr and other branch related jumps to your own stuff, but you can't Rjsr to your routines! Only to built-in AMOS routines. Use Rbsr and its equivalent!

Built-in Routines

`L_Ram*`

These call exec/AllocMem for you through AMOS.

  • L_RamChip == PUBLIC|CLEAR|CHIP
  • L_RamChip2 == PUBLIC|CHIP
  • L_RamFast == PUBLIC|CLEAR
  • L_RamFast2 == PUBLIC
snippet.asm
  MOVE.L #400,D0
  Rjsr L_RamFast
  BNE RamAllocated
  ; couldn't get RAM, D0 is 0
RamAllocated:
  ; D0 contains address of RAM

Free it with L_RamFree:

snippet.asm
  MOVE.L D0,A1
  MOVE.L #length,D0
  Rjsr L_RamFree

L_Demande and HiChaine

When you want to demand string space, you apply for it with L_Demande.

The requested length goes into D3. It does not have to be even. You get the base address in both A0 and A1.

This is an AMOS string, so the first two bytes are the size of the string as a word. Then the string comes after.

Then, you have to eventually hand HiChaine(A5) (be sure to preserve A5) the ending address of the string, rounded up to the nearest 2. I guess this is so it can be tracked in the garbage collector.

Make sure you don't try to allocate a zero width string with this! It will fail hard.

Writing out a routine in +CompExt.s with comments to understand this:

snippet.asm
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
;	=COMP ERR$
; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	Lib_Par	CompErr
; - - - - - - - - - - - - -
	Dload	a2 ; get the data area
	moveq	#0,d3 ; clean out d3
	move.w	LErreur-CD(a2),d3 ; this is the length of the error string as a word
	beq.s	.Vide ; if it's zero there's nothing to do
	Rjsr	L_Demande ; get string space, put the address in a0 and a1
	move.w	d3,d0 ; preserve existing length in d0
	move.l	a0,d3 ; move the address into d3
	move.w	d0,(a1)+ ; put the length into the start of the string
	subq.w	#1,d0 ; reduce the length by 1
	lea	Erreur-CD(a2),a0 ; load the error string address into a0
.Loop1	move.b	(a0)+,(a1)+ ; copy a bit from a0 to a1
	dbra	d0,.Loop1 ; decrement d0. if d0 is greater than 0, go to loop
	move.w	a1,d1; put the current target address into a1
	and.w	#$0001,d1 ; keep the lowest bit
	add.w	d1,a1 ; add the current address to a1
	move.l	a1,HiChaine(a5) ; mark our completed string
	moveq	#2,d2
	rts
.Vide	move.l	ChVide(a5),d3 ; return empty string
	moveq	#2,d2
	rts

Returning an empty string

Send ChVide(A5) to D3. “vide” in French is “empty” so that makes sense.

Compiler

Your extension will likely crash when used in a compiled program at first. Ensure you have your compiler set up properly:

Then, test the following:

  • Can your compiled code simply include your extension?
  • Can it run a single command in your extension?
    • If you have code that Rbccs to a different location, does that work?
    • If that doesn't work, what can you bisect out to get it to work?

Tips and Tricks

  • Memory blocks and Peek/Deek/Leek are one of the few ways you have of debugging things. Don't worry about allocating RAM and not freeing it at this point. You'll likely be rebooting very soon anyway…
  • Bisecting your changes is a must! You're going to be rebooting your machine a lot.
  • Don't forget to put the address registers back on the stack!
    • Ensure you test closing AMOS after you do stuff. Some bad things only happen once AMOS itself is unloaded.
      • Look for A4-A6 and D6-D7 not being restored, or A3 not being completely unwound for functions.
  • When adding new tokens, double-check that you are putting the label in the right spot!
snippet.asm
; functions
dc.w L_Nul,L_ThisWillReturnAValue
 
; instructions
dc.w L_ThisReturnsGarbage,L_Nul
  • Keep a known good copy of your extension around! If your startup routine is suddenly failing, you'll need to reboot and restore the known good copy.
    • This is because the Library_Digest executable seems to load AMOS config and will OOM if the extension is broken? Or maybe this just needs a reboot. Or a rewrite in C.
  • Set up AMOS assigns in your build script.
  • Did you Dload A3 into code that takes function parameters? You need to preserve and restore A3, otherwise AMOS will crash.
  • Checking a memory area to see if something needs to be freed? Be sure to clear that memory to avoid double frees.
  • Extension titles are one line only. They stop rendering at any lower ASCII character.
  • Did I mention you're going to be rebooting a lot? Setting up an ASSIGN to your code, Leaving your code file Out on the desktop, and whatever else you can do to get back into coding is necessary.
    • Of course, if you're cross-compiling, this is less of an issue.
  • You don't seem to be able to INCLUDE a file that contains Lib_Def code.
  • If you discovered you had been unwinding stacks incorrectly or anything else that could screw AMOS up, just reboot.