Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
amiga:development_environments:basic:amos_professional:extension_development [2023/02/04 13:17] Topazamiga:development_environments:basic:amos_professional:extension_development [2024/03/18 21:15] (current) Topaz
Line 1: Line 1:
-Original notes+AMOS Professional Extension Development
  
-These are detailed in [+Music.s](https://github.com/AOZ-Studio/AMOS-Professional-Official/blob/master/extensions/%2BMusic.s). I add them here as I use them.+[[amiga:development_environments:basic:amos_professional|AMOS Professional]] extensions are written in [[m68k:development:m68k_assembly_language|Motorola 68000 Assembly Language]].  
 + 
 +## Original Notes 
 + 
 +[+Music.s](https://github.com/AOZ-Studio/AMOS-Professional-Official/blob/master/extensions/%2BMusic.s) contains instructions for how to make an extension. I've added my own notes below and clarified some of the existing information.
  
 ## Defining Tokens ## Defining Tokens
Line 22: Line 26:
 ##### String parameters ##### 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.+Strings are stored in AMOS with a word for string length (so strings can be up to 65535 characters in length), and then the string itself. I'm not sure if they're null terminated.
  
 * https://www.ultimateamiga.co.uk/HostedProjects/AMOSFactory/AMOSProManual/14/1407.html * https://www.ultimateamiga.co.uk/HostedProjects/AMOSFactory/AMOSProManual/14/1407.html
Line 28: Line 32:
 ## Your own routines ## 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!+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! The Compiler will let you know of this mistake **very quickly**.
  
 ## Built-in Routines ## Built-in Routines
Line 62: Line 66:
 When you want to demand string space, you apply for it with `L_Demande`. 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.+The requested length goes into D3. It has 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. 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.+Then, you have to eventually hand `HiChaine(A5)` (be sure to preserve A5) the ending address of the string.
  
 Make sure you don't try to allocate a zero width string with this! It will fail hard. Make sure you don't try to allocate a zero width string with this! It will fail hard.
Line 93: Line 97:
  and.w #$0001,d1 ; keep the lowest bit  and.w #$0001,d1 ; keep the lowest bit
  add.w d1,a1 ; add the current address to a1  add.w d1,a1 ; add the current address to a1
- move.l a1,HiChaine(a5) ; mark our completed string+ move.l a1,HiChaine(a5) ; update the high end of string memory
  moveq #2,d2  moveq #2,d2
  rts  rts
Line 99: Line 103:
  moveq #2,d2  moveq #2,d2
  rts  rts
 +```
 +
 +Here's a better version:
 +
 +```asm
 +    ; D4 contains your string length
 +    MOVE.L D4,D3
 +    AND.W #$FFFE,D3
 +    ADDQ #2,D3 ; round up to the nearest 2
 +
 +    Rjsr L_Demande ; string is in A0/A1
 +    LEA 2(A0,D3.W),A1
 +    MOVE.L A1,HiChaine(A5)
 +    MOVE.L A0,A1 ; put A1 back
 +    MOVE.W D4,(A0)+ ; put length of string at start of memory
 +.stringstuff
 +    MOVE.B (A2)+,(A0)+
 +    BNE .stringstuff ; copy until null terminator
 +```
 +
 +You know your string code is working if you can do this:
 +
 +```basic
 +A$=My String Function$ ' returns "wow"
 +Print "cat" + A$ + "dog" ' "catwowdog"
 ``` ```
  
Line 151: Line 180:
 * You don't seem to be able to `INCLUDE` a file that contains `Lib_Def` code. * 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. * If you discovered you had been unwinding stacks incorrectly or anything else that could screw AMOS up, just reboot.
 +* **Don't use A5 for stuff!** Unless you put it back right away. That's where extension memory is located.
 +
 +---
 +
 +## How-Tos
 +
 +### Add a new command to be used in the Editor
 +
 +These use a bunch of macros I built for the BSD Socket extension:
 +
 +* Add a new function definition to the token table:
 +
 +```asm
 +C_Tk dc.w 1,0
 +;...
 +  ; if something that accepts parameters and returns a value
 +  AddTokenFunction MyNewFunction
 +  dc.b "my new functio","n"+$80,"00,0",-1
 +  
 +  ; if something that returns nothing and just has side effects
 +  AddTokenInstruction MyNewInstruction
 +  dc.b "my new instructio"."n"+$80,"I",-1
 +```
 +
 +* Add a new `Lib_Par` section to the bottom of the file
 +
 +```asm
 +  Lib_Par MyNewFunction
 +  
 +  PreserveStackFunction
 +  RestoreStackFunction
 +  Ret_Int
 +```
 +
 +* For functions with more than one parameter, peel off the parameters from `A3` in reverse order:
 +
 +```asm
 +  ; takes four parameters
 +  Lib_Par MyNewFunction
 +  
 +  PreserveStackFunction
 +  
 +  MOVE.L D3,D4 ; last parameter
 +  MOVE.L (A3)+,D3 ; second-to-last
 +  MOVE.L (A3)+,D2 ; second-to-first
 +  MOVE.L (A3)+,D1 ; first
 +  
 +  RestoreStackFunction
 +  Ret_Int
 +```
 +
 +* If returning an integer, put it in `D3`:
 +
 +```asm
 +  Lib_Par MyNewFunction
 +  
 +  PreserveStackFunction
 +  MOVE.L (A0),D3 ; return value
 +  RestoreStackFunction
 +  Ret_Int
 +```