Development

How-Tos

Define data structures in assembler

This is a macro defined in `exec/types.i` that allows you to build offsets to things: http://eab.abime.net/showpost.php?p=1278588&postcount=2

snippet.asm
  STRUCTURE MyStruct,0 ; Create a MyStruct constant with the value 0
    LONG SuperCat ; SuperCat EQU 0
    LONG SuperDog ; SuperDog EQU 4
    WORD Bird ; Bird EQU 8
    APTR OtherThing ; OtherThing EQU 10

Here's the list of all of the STRUCTURE, BITDEF, and ENUM macros, so I can stop opening types.i all the time:

snippet.asm
STRUCTURE <start label>,<offset> ; => <start label> EQU <offset>
FPTR/APTR/BPTR <label> ; => new label, advance offset by 4
BYTE/UBTYE <label> ; => advance by 1
WORD/UWORD/SHORT/USHORT <label> ; => advance by 2
BOOL <label> ; advance by 2
LONG/ULONG <label> ; => advance by 4
FLOAT/DOUBLE <label> ; => advance by 4
LABEL <label> ; => get current offset, great for _SIZEOF
STRUCT <label>,<size> ; => advance by <size>
ALIGNWORD/ALIGNLONG ; change offset to be word/long aligned
 
; ENUMs always start at 0. get rid of those magic numbers!
ENUM <name> ; => start a new enum, can only define once!
EITEM <name> ; => <name> EQU enum offset, add 1 to offset
 
; BITDEF makes two EQUs
BITDEF <prefix>,<identifier>,<bit>
; => <prefix>B_<identifier> EQU <bit>
; => <prefix>F_<identifier> EQU 1<<<bit>

Debug to text when system taken over

Writing to stdout won't work until you give everything back. But, as long as file access is still available, Write to a log file will work.

snippet.asm
; @inreg A0 null-terminated string to write
writeDebugString:
  MOVEM.L A1/D1-D3,-(SP)
 
  MOVE.L A0,A1
  MOVEQ #0,D3
.keepCheckingForNull
  TST.B (A1)+
  BNE .keepCheckingForNull
  MOVE.L A1,D3
  SUB.L A0,D3
  MOVE.L LogFileFH,D1
  MOVE.L A0,D2
  MOVE.L _DOSBase,A6
  CALLLIB _LVOWrite
 
  MOVEM.L (SP)+,A1/D1-D3
  RTS
 
partToDebug:
  MOVE.L #LogFileName,D1
  MOVE.L #MODE_NEWFILE,D2
  MOVE.L _DOSBase,A6
  CALLLIB _LVOOpen
  MOVE.L D0,LogFileFH
 
  MOVE.L #KeyboardDown,A0
  BSR writeDebugString
 
  MOVE.L LogFileFH,D1
  MOVE.L _DOSBase,A6
  CALLLIB _LVOClose

Recreate sprintf in assembler

Use RawDoFmt and PutStr:

snippet.asm
  MOVE.L #100,-(SP)
  MOVE.L #200,-(SP) ; 200 will be printed first
  LEA FormatString,A0
  MOVE.L SP,A1
  LEA stuffChar(pc),A2
  LEA StringBuffer,A3
  MOVE.L 4,A6
  CALLLIB _LVORawDoFmt
 
  LEA StringBuffer,A1
  MOVE.L A1,D1
  MOVE.L DosBase,A6
  CALLLIB _LVOPutStr ; => "200,100\n"
  ADD.L #8,SP
 
stuffChar: ;just recreate what's in the manual
  MOVE.B D0,(A3)+
  RTS
 
data:
FormatString dc.b "%ld,%ld",10,0
  CNOP 0,4
StringBuffer ds.b 32

You can also use printf in amiga.lib: http://amigadev.elowar.com/read/ADCD_2.1/Includes_and_Autodocs_3._guide/node0048.html

Write text to a bitplane

Use Move and Text with BitMap and RastPort structures:

snippet.c
  struct BitMap bitmap;
  struct RastPort rastPort;
 
  colors[0] = 0x0200;
  colors[1] = 0x0f00;
  colors[2] = 0x0f0f;
  colors[3] = 0x000f;
 
  bitmap.BytesPerRow = 40;
  bitmap.Rows = 256;
  bitmap.Depth = 1;
  bitmap.Planes[0] = bitplaneStart;
 
  InitRastPort(&rastPort);
  rastPort.BitMap = &bitmap;
 
  Move(&rastPort, 32, 32);
  Text(&rastPort, "Wow", 3);

You need to give up ownership of the blitter for this to work.

Access the hardware directly

Use a volatile pointer:

snippet.c
#include <stdio.h>
static volatile char *ciaa_sdr = (volatile char *) 0xbfec01;
 
int main(void) {
  int i;
  for (i = 0; i < 1000; ++i) {
    printf("%2x", *ciaa_sdr);
  }
}

Convert an FD file to an assembler-ready LVO

What the SPECIALS do:

  • Create an LVO file without XDEFs (you probably want this one): fd2pragma <fd file> to <path to write LVO file> SPECIAL 22
  • Create an LVO file with XDEFs fd2pragma <fd file> to <path to write LVO file> SPECIAL 20

FD files

Look like this:

* "cat.library"
##base _CatBase
##bias 30
*
##public
Meow()()
Hiss(duration,direction)(d0/d1)
  • They don't detail the return value or lack thereof.

Missing Assembler LVOs in the NDK 3.5

Call AmigaOS functions from assembler

To call a function, place the base address of the library in A6, then JSR to the LVO displacement from that address:

snippet.asm
LVODelay EQU -$c6
 
  MOVE.L #100,D1; wait 100 ticks
  MOVEA.L DOSBase,A6
  JSR LVODelay(A6)
 
DOSBase DS.L 1

Code examples

Converting an image for use

Linking to amiga.lib

Creating a Library

Custom Chips

Datatypes Library

The asm include headers need a ton of fixes for AsmPro:

  • There are EQUs with spaces in the math in datatypes/pictureclass.i
  • devices/printer.i will be included and there's a bunch of names that clash in there.

Examples

Issues

I could not get image loading and pixel retrieving working in assembler on OS 3.2.1. It would crash as soon as I called DoDTMethodA attempting the pixel read. I think I'm supposed to use DoMethod() from amiga.lib but I wasn't doing any linking.

Prepping artwork for raw use

Use ArtPRO:

  • Load the image. I've been able to load IFF ILBM and PNG images just fine.
  • Use the RAW saver to get the image data:
    • Output: Binary will get you individual bitplanes of data.
    • Blitword: None matches what Denise expects of bitplane data.
  • Use the PALETTE saver to get the palette data:
    • Output: Binary will get you data you can MOVE from one place to another.
      • Type: Copper will provide data you can drop right into a Copperlist.
      • Type: Pure will provide raw palette data. If it's a 4 bit color palette, the data will look like $0RGB.

You can use GIMP to turn an image into a decent indexed palette PNG: https://docs.gimp.org/en/gimp-image-convert-indexed.html

Assembler

Use INCBIN:

snippet.asm
SetUpDisplay:
  MOVE.L #Image,BPL1PTH
  MOVE.L #Image+(320/8)*256,BPL2PTH
  ; ...rest of planes
  ; copperlist is in A1
  LEA Palette,A0
  MOVE.L #31,D0
CopyPalette:
  MOVE.W (A0)+,(A1)+
  DBRA D0,CopyPalette
 
Image INCBIN "my_image.raw"
; copperlist format
Palette INCBIN "my_palette.pal"

Reference

Patterns

C

bsdsocket.library

Notes

  • If recv receives a negative value (or just a value with the high bit set), it seems to halt indefinitely, which is not good when used in AMOS.

FUNCDEF

For AsmPro:

snippet.asm
FUNCDEF MACRO
_LVO\1 EQU FUNC_CNT
FUNC_CNT SET FUNC_CNT-6 * Standard offset-6 bytes each
ENDM
FUNC_CNT SET -30 * Skip 4 standard vectors

Program Sections

When you build the executable, create different sections into which to load the data.

https://archive.org/details/AsmOne1.02Manual/page/n61/mode/2up

  • SECTION GraphicsStuff,DATA_C puts the following data into Chip RAM
  • SECTION OtherCode,CODE puts the following code into a new segment

AMOS Professional will only load the first CODE segment into memory when using assembled routines: https://www.ultimateamiga.co.uk/HostedProjects/AMOSFactory/AMOSProManual/14/1412.html