This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
amiga:development_environments:basic:amos_professional:extension_development [2023/02/04 13:17] – Topaz | amiga: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 | + | [[amiga: |
+ | |||
+ | ## Original Notes | ||
+ | |||
+ | [+Music.s](https:// | ||
## 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 | + | 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' |
* https:// | * https:// | ||
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' | + | You can `Rbsr` and other branch related jumps to your own stuff, but you **can' |
## 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 # | and.w # | ||
add.w d1, | add.w d1, | ||
- | move.l a1, | + | move.l a1, |
moveq # | moveq # | ||
rts | rts | ||
Line 99: | Line 103: | ||
moveq # | moveq # | ||
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, | ||
+ | MOVE.L A1, | ||
+ | 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 " | ||
+ | Print " | ||
``` | ``` | ||
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' | ||
+ | |||
+ | --- | ||
+ | |||
+ | ## 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"," | ||
+ | | ||
+ | ; if something that returns nothing and just has side effects | ||
+ | AddTokenInstruction MyNewInstruction | ||
+ | dc.b "my new instructio" | ||
+ | ``` | ||
+ | |||
+ | * 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 | ||
+ | ``` |