Beyond Brown

When brown just isn't enough

Migrating from Devpac to rmac

Introduction

So, you have come to the conclusion that it is time to leave Devpac/GenST behind and use rmac instead. Congratulations!

You have probably already heard about how rmac is incredibly fast, because it was written by Landon “Dadhacker” Dwyer to be used on 1980s machines. The project has since passed thru multiple hands, and more processor architectures and platforms have been added.

Today, rmac supports

  • 6502
  • 68000
  • 68020
  • 68030
  • 68040
  • 68060
  • 68881
  • 68882
  • 56001
  • The Atari Jaguar GPU, DSP and Object Processor

It is also very mature, and in active development.

Resources

The official rmac website

http://rmac.is-slick.com/

The rmac manual

For when you’ve read this document and want to go more in-depth

http://rmac.is-slick.com/manual/rmac.html

Quickstart

To assemble your source file example.s into the Atari ST executable example.tos:

rmac -p -v example.s -o example.tos

(technically, the -v switch isn’t necessary, but it outputs interesting verbose information after assembly)

General stuff

Directives and periods

All rmac directives have have a “.” prefix. However, rmac will often (but not always) accept directives without the period. Prefix assembler directives with “.” when in doubt.

Example

; Devpac
dc.b 1,2,3
even

; rmac
.dc.b 1,2,3
.even

Labels

All rmac labels are suffixed with a colon (”:“). This lets rmac have labels indented, which is not possible in Devpac.

Example

; Devpac
loop
  nop
  bra loop

; rmac
loop:
  nop
  bra loop

Assembler specific stuff

Forced errors

; Devpac
fail This code went BOINK!

; rmac
.error "This code went BOINK!""

Structs

; Devpac
rsreset
symbol1:    rs.l 1
symbol2:    rs.w 5
struct_size equ rscount

; rmac
.abs
symbol1:    ds.l 1
symbol2:    ds.w 5
struct_size .equ ^^abscount
.text

Conditional assembly

If not 0

;Devpac
one_nop_please equ 1
ifne one_nop_please
  nop
endc

;rmac
one_nop_please .equ 1
.if one_nop_please
  nop
.endif

If 0

;Devpac
dont_nop_here .equ 1
ifeq dont_nop_here
  nop
endc

;rmac
dont_nop_here .equ 1
.if dont_nop_here=0
  nop
.endif

As you probably already know, Devpac interprets “ifne” as “if not equal to zero”, and “ifeq” as “if equal to zero”. In rmac, things are a bit more sane.

If defined

;Devpac
ifd MY_DEFINE
  ; do some stuff
endc

;rmac
.if ^^defined MY_DEFINE
  ; do some stuff
.endif

If not defined

;Devpac
ifnd MY_DEFINE
  ; do some stuff
endc

;rmac
.if !(^^defined MY_DEFINE)
  ; do some stuff
.endif

String equality

; Devpac
ifc "string1", "string2"
  ; strings are identical
endc
ifnc "string1", "string2"
  ; strings are not identical
endc
;rmac

.if ^^streq "string1", "string2"
  ; strings are identical
.endif
.if !(^^streq "string1", "string2")
  ; strings are not identical
.endif

Macros

Macro with parameters

As long as the parameters aren’t named:

;Devpac
mWaitForTimer macro
  move.w #\1,d0
  jsr waitforvblwaiter
endm

;rmac
.macro mWaitForTimer
  move.w #\1,d0
  jsr waitforvblwaiter
.endm

Macro with named parameters

Simply can’t be done in Devpac. Replace with numbered parameters.

;rmac
.macro mWaitForTimer time, timezone, day
  move.w #\{time},d0
  move.w #\{timezone},d1
  move.w #\{day},d2
  jsr waitforvblwaiter
.endm

;Devpac
mWaitForTimer macro
  move.w #\1,d0
  move.w #\2,d1
  move.w #\3,d2
  jsr waitforvblwaiter
endm

Macro with parameters treated as hexadecimal in rmac

;rmac - will not work!
.macro PutValInD0
  move.l #$\1,d0
.endm

PutValInD0 1000

Because parameters are always converted to hex internally, this fails. The solution is to not re-interpret it as hex inside the macro, but to pass the parameter as hex, like this:

;rmac - works fine
.macro PutValInD0
  move.l #\1,d0
.endm

PutValInD0 $1000

Sections

In rmac, the target CPU is set using what is basically a section. In Devpac, it’s done using command-line parameters or the GUI.

Because rmac supports so many different CPUs and architectures, we need to start our source code with that LOOKS like a section (“.68000” or “.6502”), but it’s actually a directive for what code to generate, see below

;Devpac
section code
  nop
section data
  dc.b 13,10
section bss
  ds.l 4
;rmac

.68000  ; Sets target CPU to 68000, not used in Devpac
.text
  nop
.data
  dc.b 13,10
.bss
  ds.l 4

Rept/Endr

rmac can have nested .rept/.endr directives, Devpac can not. There’s really no workaround, except for a special case where what is being repeated is a single dc.x value - in which case we could use a dcb.x (which would also work in rmac, btw):

;Devpac
rept 4
  dcb.b 1,7 ; byte value 1, repeated 7 times
  dcb.b 5,7 ; byte value 5, repeated 7 times
endr

;rmac
.rept 4
  .rept 7
    .dc.b 1
  .endr
  .rept 7
    .dc.b 5
  .endr
.endr

Other

Order of evaluations in rmac

In rmac, expressions are evaluated from left to right and without respect to operator precedence. Two workarounds are available:

Workaround A

Use parentheses to force the order of evaluation you want

Workaround B

Use the -4 commandline parameter to force C-style order of evaluation.

Excellence in Art

Self-taught masturbator