 		IFND	MACRO_I
MACRO_I		equ	1

;--------------	define a pixel size to both BYTE,WORD and LONG sizes
DEFINE		MACRO
\1		equ	\2
\1.B		equ	(\2)/8
\1.W		equ	(\2)/16
\1.L		equ	(\2)/32
		ENDM

;--------------	some standard defines
CSI		equ	$9b		; 'Control Sequence Indicator'
ESC		equ	$1b		; 'ANSI ESCape character'
VERTICALTAB	equ	$0b		; 'VERTICAL TABulator' (Eine Zeile Hoch)
PALID		equ	$FFFFFFDE	; Anfang Pal-Bildschirm
CENDVALUE	equ	$FFFFFFFE	; Ende Copperliste (auch Macro cend)

;--------------	all registers mask
ALLREGISTERS	REG	D0-D7/A0-A6

;--------------	standard boolean registers
TRUE 		equ	1
FALSE		equ	0
		IFND	NULL
NULL		equ	0
		ENDC

;--------------	push/pop all registers on the stack
PUSHALL		MACRO
		pushm	d0-d7/a0-a6
		ENDM

PULLALL		MACRO
		popm	d0-d7/a0-a6
		ENDM

;--------------	call function \1 (optional: load library \2)
;--------------	NOTE: (to my mind) better than DOSCALL and stuff like that
;--------------	because a6 is only loaded if necesarry
;--------------	
CALL		MACRO
		IFEQ	NARG-2
		movea.l	\2,a6
		ENDC
		jsr	(_LVO\1,a6)
		ENDM

;--------------	print \1 using arguments \2 (optional: dosBase = \3)
DPRINTF		MACRO
		pushm	d0-d3/a0-a1/a6
		IFGT	NARG-1
		move.l	#\2,D2
		ELSE
		moveq	#0,d2
		ENDC
		move.l	#\1,d1
		IFGT	NARG-2
		CALL	VPrintf,\3
		ELSE
		CALL	VPrintf,<(dosBase,pc)>
		ENDC
		popm	d0-d3/a0-a1/a6
		ENDM

;--------------	branch to \2 if \1 is uppercase
;--------------	
IFUCASE		MACRO
		cmpi.b	#'a',\1
		blo\0	\2
		cmpi.b	#'z',\1
		bgt\0	\2
		ENDM

;--------------	make data register \1 uppercase
UCASE		MACRO
		cmpi.b	#'a',\1
		blo.b	.UCASE\@
		cmpi.b	#'z',\1
		bgt.b	.UCASE\@
		subi.b	#('a'-'A'),\1
.UCASE\@	
		ENDM

;--------------	make data register \1 lowercase
LCASE		MACRO
		cmpi.b	#'A',\1
		blo.b	.LCASE\@
		cmpi.b	#'Z',\1
		bgt.b	.LCASE\@
		addi.b	#('a'-'A'),\1
.LCASE\@	
		ENDM

;--------------	branch to \2 if \1 is a digit
IFDIGIT		MACRO
		cmpi.b	#'0',\1
		blo.b	.DIGIT\@
		cmpi.b	#'9',\1
		bgt.b	.DIGIT\@
		bra	\2
.DIGIT\@	
		ENDM

;--------------	move BPTR \1 to APTR \2 (scratches d0)
BMOVE		MACRO
		move.l	\1,d0
		lsl.l	#2,d0
		move.l	d0,\2
		ENDM

;--------------	convert BSTR \1 to ASTR \2 (d0.b is set to the string size)
B2ASTR		MACRO
		IFNC	'\2','a0'
		push	a0
		ENDC
		move.l	\1,d0
		lsl.l	#2,d0
		movea.l	d0,a0
		move.b	(a0)+,d0
		IFNC	'\2',a0
		move.l	a0,\2
		pop	a0
		ENDC
		ENDM

;--------------	some "antique" defines
exec.base	equ	4
execBase	equ	4
customBase	equ	$dff000
custom.chips	equ	$dff000

;--------------	cleanup memory area starting at \1, size=\2
CLEARSECTION	MACRO
		pushm	a0/d0
		lea	\1,a0
		move.l	#(\2)-1,d0
.CLS\@		clr.b	(a0)+
		dbra	d0,.CLS\@
		popm	a0/d0
		ENDM

;--------------	define an AmigaDOS style version string \1
VERSION		MACRO
		db	0,'$VER: \1',0
		even
		ENDM

BRF		MACRO
		IFEQ	NARG-3
		tst	\1
		ELSE
		tst\3	\1
		ENDC
		beq\0	\2
		ENDM

;--------------	BRanch\0 to \2 if \1[\3] is TRUE
BRT		MACRO
		IFEQ	NARG-3
		tst	\1
		ELSE
		tst\3	\1
		ENDC
		bne\0	\2
		ENDM

;--------------	BRanch\0 to \1 on Low Bit Clear in \2
BRLBC		MACRO
		btst	#0,\1
		beq\0	\2
		ENDM	

;--------------	BRanch\0 to \1 on Low Bit Set in \2
BRLBS		MACRO
		btst	#0,\1
		bne\0	\2
		ENDM

;--------------	BRanch\0 to \1 on Bit \1 Set in \2
BRBS		MACRO
		btst	\1,\2
		bne\0	\3
		ENDM

;--------------	BRanch\0 to \1 on Bit \1 Clear in \2
BRBC		MACRO
		btst	\1,\2
		beq\0	\3
		ENDM

;--------------	compare <ea>-values \1,\2 size=\0 ; scratches d0 or \3
COMPARE		MACRO
		IFEQ	NARG-3
		move\0	\1,\3
		cmp\0	\2,\3
		ELSE
		move\0	\1,d0
		cmp\0	\2,d0
		ENDC
		ENDM

;--------------	
;--------------	branch to \4 if \1 matches \3 any comparison
;-------------- possible comparisons are ==, !=, <, <=, >, >=
BRANCH		MACRO	; \1=Wert 1,\2=Condition Code,\3=Wert 2,\4=Label,[\5=Größe Vergleich]
		IFEQ	NARG-5
		COMPARE\5 \1,\3
		ELSE
		COMPARE	\1,\3
		ENDC
		IFC	'\2','=='
		beq\0	\4
		ENDC
		IFC	'\2','!='
		bne\0	\4
		ENDC
		IFC	'\2','<='
		bls\0	\4
		ENDC
		IFC	'\2','<'
		blo\0	\4
		ENDC
		IFC	'\2','>='
		bhs\0	\4
		ENDC
		IFC	'\2','>'
		bhi\0	\4
		ENDC
		ENDM

;--------------	openlib \1 and put the base to \2 (version \3)
OPENLIB		MACRO
		lea	\1,a1
		IFEQ	NARG-3
		moveq	#\3,d0
		ELSE
		moveq	#0,d0
		ENDC
		CALL	OpenLibrary,<(execBase).w>
		move.l	d0,\2
		tst.l	d0
		ENDM

;--------------	"save" closing of library \1
CLOSELIB	MACRO
		tst.l	\1
		beq.b	.Closelib\@
		movea.l	\1,a1
		CALL	CloseLibrary,<(execBase).w>
.Closelib\@	
		ENDM

;--------------	clear stack memory sized \1 in stack register \2
CLEARSTACK	MACRO
		movem.l	d0/\2,-(sp)
		move.w	#(\1)/2-1,d0
.CLRSTK\@	move.w	#0,(\2)+
		dbra	d0,.CLRSTK\@
		movem.l	(sp)+,d0/\2
		ENDM

;--------------	create stack sized \1 in stack register \2
;--------------	NOTE: this stack has positive offsets, which means you 
;--------------	can directly access it with STRUCTURE macros
CREATESTACK	MACRO
		link	\2,#-\1
		subi.l	#\1,\2
		CLEARSTACK \1,\2
		ENDM

;--------------	remove local stack sized \1 in stack register \2
ENDSTACK	MACRO
		addi.l	#\1,\2
		unlk	\2
		ENDM

;--------------	minimal function head for function \1 using register mask \2
;--------------	you *MUST* use DONE (or ENDSUB) to end this function;
;--------------	else the assembler will give you a warning
XENTRY		MACRO
		IFEQ	NARG-2			; Wenn es 2 Argumente gibt
\1_regs		reg	\2			; Register sichern
\1		movem.l	\1_regs,-(sp)		; Register auf den Stack
		ELSE				; Sonst
\1						; Nur den Funktionsnamen definieren	
		ENDC				; Ende
ENTRYohneDONEfür	set	\1_done	
		ENDM

;--------------	all-purpose function entry macro. Defines function named \1 
;--------------	saving the registers \2. Optional: stacksize \3, stackregister \4
;--------------	you *MUST* use DONE (or ENDSUB) to end this function;
;--------------	else the assembler will give you a warning
ENTRY		MACRO
		IFD	IS_LINKABLE
		xdef	\1
		ENDC	
		XENTRY	\1,\2
		IFEQ	NARG-4
\1_stksize	equ	\3
\1_stkreg	equr	\4
		CREATESTACK \3,\4
		ENDC
		ENDM
 
;--------------	end a function created with ENTRY or XENTRY macros;
;--------------	it cleans up the stack (if one exists) and restores the
;--------------	saved register list
ENDSUB		MACRO
		IFNC	'','\1'
		IFND	\1
		FAIL	Die Funktion \1 existiert nicht
		ENDC
		IFND	\1_done
\1_done		
		ENDC
		ELSE
.function_done
		ENDC
		IFD	\1_stksize
		ENDSTACK \1_stksize,\1_stkreg
		ENDC
		IFD	\1_regs
		movem.l	(sp)+,\1_regs
		ENDC
		ENDM

;--------------	same as ENDSUB but returns with RTS
DONE		MACRO
		ENDSUB	\1
		rts
		ENDM

;--------------	same as ENDSUB but returns with RTE
DONEEXCEPTION	MACRO
		ENDSUB	\1
		rte
		ENDM

;--------------	don't use this: internal DEBUG macro
DEBUGALLOWED	MACRO
		IFD	DEBUG_MODE
__DEBUG_VAR	
		IFC	'\1',''
		DC.L	$7F000
		ELSE
		DC.L	\1
		ENDC
		ENDC
		ENDM	

DEBUG		MACRO
		IFD	DEBUG_MODE
		move.l	a0,-(sp)
		move.l	\1,-(sp)
		movea.l	(__DEBUG_VAR),a0
		move.l	(sp)+,(a0)+
		IFGT	NARG-1
		move.l	\2,(a0)+
		ENDC	
		IFGT	NARG-2
		move.l	\3,(a0)+
		ENDC	
		IFGT	NARG-3
		move.l	\4,(a0)+
		ENDC	
		IFGT	NARG-4
		move.l	\5,(a0)+
		ENDC	
		IFGT	NARG-5
		move.l	\6,(a0)+
		ENDC	
		move.l	a0,(__DEBUG_VAR)
		move.l	(sp)+,a0
		ENDC
		ENDM

;--------------	set or clear flag \3 if \1 matches \2 using comparison \3
SETFLAG		MACRO
		COMPARE\0 \1,\3
		IFC	'\2','=='
		seq	\4
		ENDC
		IFC	'\2','!='
		sne	\4
		ENDC
		IFC	'\2','<='
		sls	\4
		ENDC
		IFC	'\2','<'
		slo	\4
		ENDC
		IFC	'\2','>='
		sge	\4
		ENDC
		IFC	'\2','>'
		sgt	\4
		ENDC
		ENDM

;--------------	BROKEN::::::::::::::::::::::::::::::::::::::::::::::::
IIF		MACRO	;\1=ConditionCode,\2=Befehle
IIF_FLAG	SET	0
		IFC	'\1','EQ'
IIF_FLAG	SET	1
		bne.b	.iif\@
		ENDC
		IFC	'\1','NE'
IIF_FLAG	SET	1
		beq.b	.iif\@
		ENDC
		IFC	'\1','LS'
IIF_FLAG	SET	1
		bgt.b	.iif\@
		ENDC
		IFC	'\1','LO'
IIF_FLAG	SET	1
		bge.b	.iif\@
		ENDC
		IFC	'\1','HS'
IIF_FLAG	SET	1
		blo.b	.iif\@
		ENDC
		IFC	'\1','HI'
IIF_FLAG	SET	1
		bls.b	.iif\@
		ENDC
		IFNE	IIF_FLAG-1
		FAIL 	Ungültiger Conditioncode '\1' für IIF-Makro
		ENDC
\2
		IFEQ	NARG-3
		bra.b	.else\@
.iif\@
\3		**** BROKEN, DON'T USE ****
.else\@
		ELSE
.iif\@
		ENDC
		ENDM

;--------------	optimized clear for data registers
CLEAR_DATAREG	MACRO
		IFC	\*UPPER(\0),.L
		moveq	#0,\1
		ELSE
		clr\0	\1
		ENDC
		ENDM

;--------------	optimized clear for addr registers
CLEAR_ADDRREG	MACRO
		IFC	\*UPPER(\0),.B
		clr.b	\1,\1
		ELSE
		suba\0	\1,\1
		ENDC
		ENDM

;--------------	clear Dx/Ax/anything else
CLEAR_ANYTHING	MACRO
		IFNC	'','\1'
		IFEQ	\*STRLEN(\1)-3
		IFC	\*UPPER(\*LEFT(\1,1)),D
		CLEAR_DATAREG\0	\1		
		MEXIT
		ENDC
		IFC	\*UPPER(\*LEFT(\1,1)),A
		CLEAR_ADDRREG\0	\1
		MEXIT
		ENDC
		ENDC
		clr\0	\1
		ENDC
		ENDM

;--------------	optimized clear [up to 16 arguments]
OPTIMIZED_CLEAR	MACRO
		CLEAR_ANYTHING\0 \1
		CLEAR_ANYTHING\0 \2
		CLEAR_ANYTHING\0 \3
		CLEAR_ANYTHING\0 \4
		CLEAR_ANYTHING\0 \5
		CLEAR_ANYTHING\0 \6
		CLEAR_ANYTHING\0 \7
		CLEAR_ANYTHING\0 \8
		CLEAR_ANYTHING\0 \9
		CLEAR_ANYTHING\0 \(10)
		CLEAR_ANYTHING\0 \(11)
		CLEAR_ANYTHING\0 \(12)
		CLEAR_ANYTHING\0 \(13)
		CLEAR_ANYTHING\0 \(14)
		CLEAR_ANYTHING\0 \(15)
		CLEAR_ANYTHING\0 \(16)
		ENDM

;--------------	required, because in exec/macros.i another 'CLEAR' is defined
CLEAR		SETMAC	OPTIMIZED_CLEAR

;--------------	exchange two variables using stack (don't use stack relative args)
XCHG		MACRO	;Op1,Op2
		IFC	\*UPPER(\0),.B
		move.w	d0,-(sp)
		move.b	\1,d0
		move.b	\2,\1
		move.b	d0,\2
		move.w	(sp)+,d0
		ELSE
		move\0	\1,-(sp)
		move\0	\2,\1
		move\0	(sp)+,\2
		ENDC
		ENDM

;--------------	same as ++/-- in C
INC		MACRO
		addq\0	#1,\1
		ENDM
DEC		MACRO
		subq\0	#1,\1
		ENDM

;--------------	index calculation for an 2 dimensional array. BROKEN
;--------------	
;--------------	INDEX \1=result,\2=x,\3=xsize,\4=xmin,[\5=xmax,\6=y,\7=ysize,\8=ymin]
;--------------	
;--------------	Dabei ist 
;--------------	
;--------------	  x/y : Die Elementnummer
;--------------	  xsize/ysize : Die Größe eines Elements dieses Typs
;--------------	  xmin/ymin : Der Minimalwert für das Element
;--------------	  xmax/ymax : Der Maximalwert für das Element
;--------------	
;--------------	Eine eindimensionale Liste ist dabei So aufgebaut
;--------------	
;--------------	[ Element=0, index=xmin, 	,offset=0]
;--------------	[ Element=1, index=xmin+xsize	,offset=xsize]
;--------------	[ Element=2, index=xmin+2*xsize	,offset=2*xsize]
;--------------	 ...
;--------------	
;--------------	Eine zweidimensionale Liste ist dabei so aufgebaut
;--------------	
;--------------	[ Element=0/0, index=xmin,		,offset=0]
;--------------	[ Element=0/1, index=xmin+xsize		,offset=xsize]
;--------------	[ Element=0/2, index=xmax+2*xsize	,offset=2*xsize]
;--------------	 ...
;--------------	[ Element=1/0, index=xmin+(xmin-xmax)*xsize ,offset=(xmin-xmax)*xsize]
;--------------	 ...
;--------------	
INDEX		MACRO
		move.l	#((\2)-(\4))*(\3),\1	; Result = X-Offset
		ENDM

;--------------	Verschiedene direkte 'Branch on Condition'-Befehle, die nicht wie
;--------------	'BRANCH' extra-komische Vergleiche anstellen müßen.
BRNE		MACRO
		cmp\4	\1,\2
		bne\0	\3
		ENDM

BREQ		MACRO
		cmp\4	\1,\2
		beq\0	\3
		ENDM

BRLO		MACRO
		cmp\4	\1,\2
		blo\0	\3
		ENDM

BRLS		MACRO
		cmp\4	\1,\2
		bls\0	\3
		ENDM

BRGT		MACRO
		cmp\4	\1,\2
		bgt\0	\3
		ENDM

BRGE		MACRO
		cmp\4	\1,\2
		bge\0	\3
		ENDM

BREQ0		MACRO
		tst\3	\1
		beq\0	\2
		ENDM

BRNE0		MACRO
		tst\3	\1
		bne\0	\2
		ENDM

ADDO		MACRO
		IFC	\*LEFT(\1,1),#
		IFLE	\*RIGHT(\1,\*STRLEN(\1)-1)-8
		addq\0	\1,\2
		ELSE
		addi\0	\1,\2
		ENDC
		ELSE
		add\0	\1,\2
		ENDC
		ENDM

SUBO		MACRO
		IFC	\*LEFT(\1,1),#
		IFLE	\*RIGHT(\1,\*STRLEN(\1)-1)-8
		subq\0	\1,\2
		ELSE
		subi\0	\1,\2
		ENDC
		ELSE
		sub\0	\1,\2
		ENDC
		ENDM

;--------------	copy string \1 to string \2 (both arguments Ax)
STRCPY		MACRO	; sourcereg, targetreg
.strcpy\@	move.b	(\1)+,(\2)+
		bne.s	.strcpy\@
		ENDM

;--------------	cpu status bits
		BITDEF	CPUSTATE,EXTENDED,4	; X
		BITDEF	CPUSTATE,NEGATIVE,3	; N
		BITDEF	CPUSTATE,ZERO,2		; Z
		BITDEF	CPUSTATE,OVERFLOW,1	; V
		BITDEF	CPUSTATE,CARRY,0	; C


;--------------	my REMHEAD macro. Only difference to exec/list.i : uses local
;--------------	labels
MYREMHEAD	MACRO	; A0-list A1-(destroyed) D0=node
		MOVE.L	(A0),A1
		MOVE.L	(A1),D0
		BEQ.B	.REMHEAD\@
		MOVE.L	D0,(A0)
		EXG.L	D0,A1
		MOVE.L	A0,LN_PRED(A1)
.REMHEAD\@
		ENDM

;--------------	define an intuition-style alert()
DEFINE_ALERT	MACRO
		dc.w	10
		dc.b	15,'\1',0,0
		ENDM

		ENDC
;--------------	
