Skip to content

Instantly share code, notes, and snippets.

@appblue
Last active August 30, 2024 17:11
Show Gist options
  • Save appblue/e11db468070c72461442df2403aa8f93 to your computer and use it in GitHub Desktop.
Save appblue/e11db468070c72461442df2403aa8f93 to your computer and use it in GitHub Desktop.
Amiga 4K Intro Template

Example m68k startup code for 4k demo on Amiga

;              T         T               T

; Compact demo-startup by Blueberry/Loonies
; Version 1.5, October 7, 2014
; Public Domain

;; ********** System constants **********

; Exec
SU_Supervisor = -30
SU_OldOpenLibrary = -408
SU_CacheClearU = -636
SU_TaggedOpenLibrary = -810
; Graphics
SU_OpenFont = -72
SU_LoadView = -222
SU_WaitTOF = -270

SU_lib_Version = $14
SU_eb_AttnFlags = $128
SU_gb_ActiView = $22
SU_gb_copinit = $26
SU_tf_CharData = $22
IVBLIT = 156


; Cache flush macro
; Potentially trashes D0-D1/A0-A1/A6

	if	COMPATIBILITY=0
CACHEFLUSH	macro
	endm
	endc

	if	COMPATIBILITY=1
CACHEFLUSH	macro
	move.l	$4.w,a6
	cmp.w	#37,SU_lib_Version(a6)
	blo.b	.noflush\@
	jsr	SU_CacheClearU(a6)
.noflush\@:
	endm
	endc

	if	COMPATIBILITY=2
CACHEFLUSH	macro
	move.l	$4.w,a6
	jsr	SU_CacheClearU(a6)
	endm
	endc

DMA_OFF	=	$00ff-(COPPER<<7)-(BLITTER<<6)-(SPRITE<<5)


; Entry point

	if	FASTMEM
	section	Code,code_f
	else
	section	Code,code
	endc

Startup:
	if	SECTIONHACK<>0
	if	SECTIONHACK=1
	; Read section pointers from hunk structure
	move.l	Startup-4(pc),d0
	lsl.l	#2,d0
	addq.l	#4,d0
	lea.l	ChipPtr(pc),a1
	move.l	d0,(a1)
	endc
	else
	move.l	#Chip,ChipPtr
	endc

	; Open topaz
	if	TOPAZ
	move.l	$4.w,a6
	move.l	156(a6),a6	; graphics.library
	lea.l	TextAttr(pc),a0
	lea.l	TopazName(pc),a4
	move.l	a4,(a0)
	jsr	SU_OpenFont(a6)
	move.l	d0,a0
	move.l	SU_tf_CharData(a0),TopazCharData-TopazName(a4)
	endc

	; Call precalc code
	bsr.w	_Precalc

	; Retrieve Vector Base Register
	move.l	$4.w,a6
	if	COMPATIBILITY=1
	suba.l	a2,a2
	btst.b	#0,SU_eb_AttnFlags+1(a6)
	beq.b	.no010
	endc
	if	COMPATIBILITY>=1
	lea.l	GetVBR(pc),a5
	jsr	SU_Supervisor(a6)
.no010:	endc

	; Clear display
	move.l	156(a6),a6	; graphics.library
	if	COMPATIBILITY>=1
	move.l	SU_gb_ActiView(a6),d7
	suba.l	a1,a1
	jsr	SU_LoadView(a6)
	lea.l	$dff000,a3
	move.w	#$0020,$1dc(a3)	; Ensure PAL
	jsr	SU_WaitTOF(a6)
	jsr	SU_WaitTOF(a6)
	else
	jsr	SU_WaitTOF(a6)
	lea.l	$dff000,a3
	endc
	move.w	#$3fdf,$09a(a3)
	move.w	#DMA_OFF,$096(a3)

	; Init interrupt
	lea.l	InterruptHandler(pc),a4
	if	COMPATIBILITY>=1
	move.l	$6c(a2),a5
	move.l	a4,$6c(a2)
	movem.l	d7/a2/a3/a5/a6,-(a7)
	else
	move.l	$6c.w,a5
	move.l	a4,$6c.w
	movem.l	a3/a5/a6,-(a7)
	endc
	move.l	a7,-(a4)	; StackStore

	bsr.w	_Main

StartupEnd:
	move.l	StackStore(pc),a7

	; Restore interrupt
	if	COMPATIBILITY>=1
	movem.l	(a7)+,a1/a2/a3/a4/a6
	move.l	a4,$6c(a2)
	else
	movem.l	(a7)+,a3/a4/a6
	move.l	a4,$6c.w
	endc

	; Restore display
	move.w	#$a00c,$09a(a3)
	move.w	#$001f,$096(a3)
	move.w	#$81e0,$096(a3)
	if	COPPER
	move.l	SU_gb_copinit(a6),$080(a3)
	endc
	if	COMPATIBILITY>=1
	jsr	SU_LoadView(a6)
	endc

; In principle, we should close graphics.library and topaz.font here,
; but since they are always in use, it makes no difference whatsoever,
; so we don't bother.

	bra.w	_Exit


	if	COMPATIBILITY>=1
GetVBR:
	movec	vbr,a2
	rte
	endc

	if	TOPAZ
TextAttr:
	dc.l	0
	dc.w	8
	dc.b	0,0
TopazCharData:	dc.l	0
TopazName:	dc.b	'topaz.font',0
	endc

	even

VBlank:	dc.l	0
	if	SECTIONHACK>=0
ChipPtr:	dc.l	0
	endc
StackStore:	dc.l	0
InterruptHandler:
	movem.l	d0-a6,-(a7)
	if	FPUINT
	fsave	-(a7)
	fmovem.x	fp0-fp7,-(a7)
	endc

	lea.l	VBlank(pc),a0
	addq.l	#1,(a0)

	bsr.w	_Interrupt
	lea.l	$dff000,a3

	if	RMBPAUSE
	; RMB pause
.rmb:	btst	#10,$016(a3)
	bne.b	.normb
	move.w	#$0020,$09c(a3)
	move.w	#$0020,$09c(a3)

	btst.b	#6,$bfe001
	bne.b	.rmbloop2
.rmbloop:
	moveq.l	#$0020,d0
	and.w	$dff01e,d0
	beq.b	.rmbloop
	bsr.w	_Interrupt
	lea.l	$dff000,a3
 	bra.b	.rmb
.rmbloop2:
	moveq.l	#$0020,d0
	and.w	$dff01e,d0
	beq.b	.rmbloop2
	bsr.w	_Interrupt
	lea.l	$dff000,a3
	btst.b	#6,$bfe001
	bne.b	.rmb
	move.w	#$0020,$09c(a3)
	move.w	#$0020,$09c(a3)
	if	FPUINT
	fmovem.x	(a7)+,fp0-fp7
	frestore	(a7)+
	endc
	movem.l	(a7)+,d0-a6
	rte
.normb:
	endc

	move.w	#$0020,$09c(a3)
	if	COMPATIBILITY>=1
	move.w	#$0020,$09c(a3)
	endc

	if	FPUINT
	fmovem.x	(a7)+,fp0-fp7
	frestore	(a7)+
	endc
	movem.l	(a7)+,d0-a6

	btst.b	#6,$bfe001
	bne.b	.end
	lea.l	StartupEnd(pc),a1
	move.l	a1,2(a7)
.end:
	rte

Example:

;              T         T               T

; Compact demo-startup by Blueberry/Loonies
; Example usage source code
; Version 1.5, March 10, 2015
; Public Domain

; Set demo compatibility
; 0: 68000 only, Kickstart 1.3 only, PAL only
; 1: All CPUs, Kickstarts and display modes
; 2: 68010+, Kickstart 2.04+, all display modes
COMPATIBILITY	=	1

; Set to 1 to require fast memory
FASTMEM	=	0

; Set to 1 to enable pause on right mouse button
; with single-step on left mouse button
RMBPAUSE	=	1

; Set to 1 if you use FPU code in your interrupt
FPUINT	=	0

; Set to 1 if you use the copper, blitter or sprites, respectively
COPPER	=	1
BLITTER	=	0
SPRITE	=	0

; Set to 1 to get address of topaz font data in TopazCharData
TOPAZ	=	0

; Section hack provides a pointer to the chip section in ChipPtr
; Set to 1 when writing the object file to avoid the relocation
; Set to -1 if no chip section pointer is needed
SECTIONHACK	=	0


	; Demo startup must be first for section hack to work
	include	Inc:DemoStartup.S


_Precalc:
	; Called as the very first thing, before system shutdown

	; Example: Copy copperlist to chipram
	lea.l	CopperData(pc),a0
	move.l	ChipPtr(pc),a1
	lea.l	Copper-Chip(a1),a1
	moveq.l	#(CopperData_End-CopperData)/4-1,d7
.loop:	move.l	(a0)+,(a1)+
	dbf	d7,.loop

	rts


_Exit:
	; Called after system restore

	; Example: Cache flush test
	move.w	#1000-1,d7
.code:	move.l	#1,d2
	lea.l	.code+2(pc),a0
	addq.l	#1,(a0)
	CACHEFLUSH
	dbf	d7,.code
	; D2 should be 1000 here

	moveq.l	#0,d0
	rts


_Main:
	; Main demo routine, called by the startup.
	; Demo will quit when this routine returns.

	; Example: Set copper address
	move.l	ChipPtr(pc),a1
	lea.l	Copper-Chip(a1),a1
	move.l	a1,$dff080

MainLoop:
	; Example: Fill screen gradually
	move.l	VBlank(pc),d0
	move.l	ChipPtr(pc),a1
	lea.l	Bitplane-Chip(a1),a1
	st.b	(a1,d0.l)

	bra.w	MainLoop


_Interrupt:
	; Called by the vblank interrupt.

	; Example: Set bitplane pointer
	move.l	ChipPtr(pc),a1
	lea.l	Bitplane-Chip(a1),a1
	move.l	a1,$dff0e0

	rts


	; Example: Copperlist to display one bitplane

CopperData:
	dc.l	$008e2c81,$00902cc1
	dc.l	$00920038,$009400d0
	dc.l	$01001200,$01020000,$01060000,$010c0011
	dc.l	$01080000,$010a0000
	dc.l	$01800abc,$01820123
	dc.l	$01fc0000
	dc.l	$fffffffe
CopperData_End:


	; Place fast-mem space at the end of the code section to have
	; the cruncher remove it.

	; Example: Dummy space

DummySpace:
	ds.b	10000

	align	0,4


	; Place all chip space in the single chip section.
	; Define no other sections.

	section	chip,bss_c
Chip:

	; Example: Single bitplane
Copper:
	ds.b	CopperData_End-CopperData
Bitplane:
	ds.b	320*256/8

Additional comments from web

I managed to shave off 22 bytes in demostartup.s :D

  • save 2 bytes Remove one move in SECTIONHACK by changing:
move.l d0,a0
lea.l ChipPtr(pc),a1
move.l a0,(a1)

to

lea.l ChipPtr(pc),a1
move.l d0,(a1)
  • save 6 bytes: remove move.w #$3fdf,$9a(a3) and add dc.l $9a3fdf in the copperlist remove move.w #$0020,$1dc(a3) and add dc.l $1dc0020 in the copperlist remove move.w #$007f,$96(a3) and add dc.l $096007f in the copperlist

  • save 4*2 bytes: replace lea $dff000,a3 with lea $dff096,a3 Correct all instructions with a3 access.

  • save 2*2 bytes in the interrupt handler replace lea $dff000,a3 with lea $dff09c,a3 Correct all instructions with a3 access.

  • save 2 bytes in memory add dc.w $0200 after the VBlank pointer

lea.l vblank(pc),a0
addq.l 1,(a0)+
...
move.w (a0),$9c(a3)
move.w (a0),$9c(a3)

Access to ROM libraries

I realized (some time ago) that the old trick of reading GraphicsBase from offset 156 of ExecBase works on all Amigas. I have now updated the startup code accordingly, saving some bytes (especially in compatibility mode 1).

I looked a bit into this. IntuitionBase seems to be available at offset 468 from GraphicsBase (gb_IData) on KS3.0 and KS3.1, but no such luck on KS1.3 or KS2.0. I couldn't find DosBase anywhere.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment