; ----------------------------------------------------------------------------
;                           dA JoRMaS: Major Release
;
;        (C) 2004 Vesuri/dA JoRMaS (Vesa Halttunen <vesuri@jormas.com>)
; ----------------------------------------------------------------------------
;      This source code is provided strictly for the purpose of education.
;
;              You are NOT allowed to sell or modify this code or
;      use any part of it in your own programs (modified or unmodified)
;                 without a written permission from the author.
; ----------------------------------------------------------------------------
FINALVERSION		equ	1
STARTPATTERN		equ	1
PATTERNLENGTH		equ	64
BZ_PLANEWIDTH		equ	32
BZ_PLANEHEIGHT		equ	256
BZ_PLANESIZE		equ	BZ_PLANEWIDTH*BZ_PLANEHEIGHT
BZ_PLANES		equ	4
CH_PLANEWIDTH		equ	24
CH_PLANEHEIGHT		equ	85
CH_PLANESIZE		equ	CH_PLANEWIDTH*CH_PLANEHEIGHT
CH_PLANES		equ	4
CH_CHUNKY_WIDTH		equ	CH_PLANEWIDTH/2*8
CH_CHUNKY_HEIGHT	equ	CH_PLANEHEIGHT
CH_CHUNKY_SIZE		equ	CH_CHUNKY_WIDTH*CH_CHUNKY_HEIGHT
CH_SOURCE_WIDTH		equ	128
CH_SOURCE_HEIGHT	equ	128
CH_SOURCE_SIZE		equ	CH_SOURCE_WIDTH*CH_SOURCE_HEIGHT
CT_MAX_OFFSET		equ	16320+2
CT_ANGLE_RANGE		equ	128
CS_PLANEWIDTH		equ	44
CS_PLANEHEIGHT		equ	208
CS_PLANESIZE		equ	CS_PLANEWIDTH*CS_PLANEHEIGHT
CS_PLANES		equ	1
CS_BUILDING_SIZE	equ	25
CS_CLIP			equ	-18
CS_SINUS		equ	-16
CS_COSINUS		equ	-14
CS_X			equ	-12
CS_Z			equ	-10
CS_OCTANTS		equ	-8
CS_OLDX			equ	-4
CS_OLDY			equ	-2
CS_BLITTER_CLEAR	equ	112
CLIP_LEFT_EDGE		equ	(1<<0)
CLIP_RIGHT_EDGE		equ	(1<<1)
CLIP_TOP_EDGE		equ	(1<<2)
CLIP_BOTTOM_EDGE	equ	(1<<3)
DP_PLANEWIDTH		equ	32
DP_PLANEHEIGHT		equ	256
DP_PLANESIZE		equ	DP_PLANEWIDTH*DP_PLANEHEIGHT
DP_PLANES		equ	5
FW_PLANEWIDTH		equ	40
FW_PLANEHEIGHT		equ	256
FW_PLANESIZE		equ	FW_PLANEWIDTH*FW_PLANEHEIGHT
FW_PLANES		equ	2
FW_BLITTER_CLEAR	equ	128
FW_STARTING_ROW		equ	16
FW_ENDING_ROW		equ	240
FW_NUMBER_OF_FONTS	equ	95
FW_NUMBER_OF_PARTICLES	equ	80
FS_PLANEWIDTH		equ	32
FS_PLANEHEIGHT		equ	256
FS_PLANESIZE		equ	FS_PLANEWIDTH*FS_PLANEHEIGHT
FS_PLANES		equ	4
HO_PLANEWIDTH		equ	40
HO_PLANEHEIGHT		equ	256
HO_PLANESIZE		equ	HO_PLANEWIDTH*HO_PLANEHEIGHT
HO_PLANES		equ	5
HO_HORIZON_PLANES	equ	4
HO_GRADIENT_HEIGHT	equ	16
HO_MINXX		equ	-10
HO_MINXY		equ	-8
HO_MAXXX		equ	-6
HO_MAXXY		equ	-4
HO_SUBSTRACT		equ	-2
HO_TABLE_COORDINATES	equ	0
HO_TABLE_HEIGHT		equ	4
HO_TABLE_Z		equ	6
HO_TABLE_ZOOM		equ	8
HO_TABLE_SIZE		equ	12
IR_PLANEWIDTH		equ	44
IR_PLANEHEIGHT		equ	320
IR_PLANESIZE		equ	IR_PLANEWIDTH*IR_PLANEHEIGHT
IR_PLANES		equ	6
IR_RADIUS		equ	23
IR_MAX			equ	125
IR_SOURCE_HEIGHT	equ	272
IP_PLANEWIDTH		equ	40
IP_PLANEHEIGHT		equ	232
IP_PLANESIZE		equ	IP_PLANEWIDTH*IP_PLANEHEIGHT
IP_PLANES		equ	2
RO_PLANEWIDTH		equ	36
RO_PLANEHEIGHT		equ	258
RO_PLANESIZE		equ	RO_PLANEWIDTH*RO_PLANEHEIGHT
RO_PLANES		equ	2
RO_SIZE			equ	16
RO_RESOLUTION		equ	16
RO_NUMPOINTS		equ	7
SW_PLANEWIDTH		equ	32
SW_PLANEHEIGHT		equ	256
SW_PLANESIZE		equ	SW_PLANEWIDTH*SW_PLANEHEIGHT
SW_PLANES		equ	1
SW_ANGLE		equ	4
SW_WIDTH		equ	32
SW_HEIGHT		equ	512
SW_BITMAP_HEIGHT	equ	1620
SW_NUMBER_OF_FONTS	equ	95
SV_PLANEWIDTH		equ	32
SV_PLANEHEIGHT		equ	160
SV_PLANESIZE		equ	SV_PLANEWIDTH*SV_PLANEHEIGHT
SV_PLANES		equ	4
SV_STENCIL_WIDTH	equ	32
SV_STENCIL_HEIGHT	equ	256
SV_STENCIL_SIZE		equ	SV_STENCIL_WIDTH*SV_STENCIL_HEIGHT
SV_OLDX			equ	-2
SV_OLDY			equ	-4
SV_XANGLESIN		equ	0
SV_XANGLECOS		equ	2
SV_YANGLESIN		equ	4
SV_YANGLECOS		equ	6
SV_ZANGLESIN		equ	8
SV_ZANGLECOS		equ	10
SV_XX			equ	0
SV_XY			equ	2
SV_XZ			equ	4
SV_YX			equ	6
SV_YY			equ	8
SV_YZ			equ	10
SV_ZX			equ	12
SV_ZY			equ	14
SV_ZZ			equ	16
SV_XXXY			equ	18
SV_YXYY			equ	22
SV_ZXZY			equ	26
SV_X			equ	0
SV_Y			equ	2
SV_Z			equ	4
SV_X_Y			equ	6
SV_NORMAL_SHIFT		equ	7
SV_DISTANCE_MAX		equ	1505
SV_DISTANCE_MIN		equ	295
JL_PLANES		equ	3
JL_PLANEWIDTH		equ	44
JL_PLANEHEIGHT		equ	64
JL_PLANESIZE		equ	JL_PLANEWIDTH*JL_PLANEHEIGHT
VV_PLANEWIDTH		equ	44
VV_PLANEHEIGHT		equ	256
VV_PLANESIZE		equ	VV_PLANEWIDTH*VV_PLANEHEIGHT
VV_PLANES		equ	1

	incdir	"include:"
	include "JoRMaS.i"

	section	FastCode,Code

	nop
	; Tooltypes and command line arguments only handled in final version
	; ------------------------------------------------------------------
	ifne	FINALVERSION
	bsr	SystemStartUp
	endc

	; Allocate memory and setup copperlists etc.
	; ------------------------------------------
	bsr	StartUp

	; Main loop
	; ---------
main:	tst.b	quit
	bne	done

	; Check whether a new part should be initialized
	; -----------------------------------------------
script:	lea	parts,a0
	add.l	part,a0
	move.l	sc_position,d0
	move.l	(a0)+,d1
	bmi	noinit
	cmp.l	d0,d1
	bhi	noinit
	clr.l	part_vbi
	lea	custom,a6
	; Disable the (possible) blitter interrupt during init
	; ----------------------------------------------------
	move.w	#INTF_BLIT,d0
	move.w	d0,intena(a6)
	waitb
	move.w	d0,intreq(a6)
	move.w	d0,intreq(a6)
	; Use the "no effects" copperlist
	; -------------------------------
	move.l  #ne_cl,cop1lch(a6)
	move.w	#0,copjmp1(a6)
	addq.l	#8,part
	clr.b	render
	clr.l	part_main
	; Initialize the effect
	; ---------------------
	move.l	(a0),a0
	jsr	(a0)
	bra.s	script

noinit:	tst.b	render
	bne	main

	; Check whether there is a main function to run and if so run it
	; --------------------------------------------------------------
	move.l	part_main,d0
	beq	main
	move.l	d0,a0
	jsr	(a0)
	bra	main

	; Restore system to normal state
	; ------------------------------
done:	bsr	ShutDown

	tst.l	loop
	bne	main

die:	rts

	; Level 3 Interrupt
	; -----------------
interrupt_level3:
	move.l	d0,-(sp)

	; Check whether the interrupt is blitter or vertical blank
	; --------------------------------------------------------
	move.w	intreqr+custom,d0
	and.w	#INTF_VERTB,d0
	bne	VBI

	; Blitter interrupt
	; -----------------
	movem.l	a0-a1/a6,-(sp)

	; Clear interrupt request
	; -----------------------
	lea	custom,a6
	move.w	#INTF_BLIT,d0
	move.w	d0,intreq(a6)
	move.w	d0,intreq(a6)

	; Next pass
	; ---------
	moveq	#0,d0
	add.b	#1,ch_c2p_pass
	cmp.b	#8,ch_c2p_pass
	beq.w	ch_bp8
	cmp.b	#7,ch_c2p_pass
	beq.w	ch_bp7
	cmp.b	#6,ch_c2p_pass
	beq.w	ch_bp6
	cmp.b	#5,ch_c2p_pass
	beq.w	ch_bp5
	cmp.b	#4,ch_c2p_pass
	beq.w	ch_bp4
	cmp.b	#3,ch_c2p_pass
	beq.w	ch_bp3

ch_bp2:	; Pass 2:
	; First half of the buffer: upper bits (3 & 2)
	; 000044449999dddd22226666bbbbffff
	; --------------------------------
	lea	ch_tempbuffer1,a0
	lea	ch_tempbuffer2,a1
	waitb
	move.w	#4,bltamod(a6)
	move.w	#4,bltbmod(a6)
	move.w	d0,bltdmod(a6)
	move.l	a0,bltapth(a6)
	addq	#4,a0
	move.l	a0,bltbpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#%1111000011110000,bltcdat(a6)
	move.w	#SRCA|SRCB|DEST|ANBC|ABC|ABNC|NABNC,bltcon0(a6)
	move.w	#(4<<BSHIFTSHIFT),bltcon1(a6)
	move.w	#((CH_CHUNKY_SIZE/4/2)<<6)|2,bltsize(a6)
	bra	ch_bld

ch_bp3:	; Pass 3:
	; Second half of the buffer: lower bits (1 & 0)
	; 000044449999dddd22226666bbbbffff
	; --------------------------------
	lea	ch_tempbuffer1+CH_CHUNKY_SIZE-4-2,a0
	lea	ch_tempbuffer2+CH_CHUNKY_SIZE-2,a1
	waitb
	move.l	a0,bltapth(a6)
	addq	#4,a0
	move.l	a0,bltbpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#(4<<ASHIFTSHIFT)|SRCA|SRCB|DEST|ANBC|ABC|ABNC|NABNC,bltcon0(a6)
	move.w	#BLITREVERSE,bltcon1(a6)
	move.w	#((CH_CHUNKY_SIZE/4/2)<<6)|2,bltsize(a6)
	bra	ch_bld
	
ch_bp4:	; Pass 4:
	; First quarter of the buffer: bit 3
	; 0022446699bbddff
	; ----------------
	lea	ch_tempbuffer2,a0
	lea	ch_planes,a1
	add.l	ch_planes_add,a1
	waitb
	move.w	#2,bltamod(a6)
	move.w	#2,bltbmod(a6)
	move.w	d0,bltdmod(a6)
	move.l	a0,bltapth(a6)
	addq	#2,a0
	move.l	a0,bltbpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#%1100110011001100,bltcdat(a6)
	move.w	#SRCA|SRCB|DEST|ANBC|ABC|ABNC|NABNC,bltcon0(a6)
	move.w	#(2<<BSHIFTSHIFT),bltcon1(a6)
	move.w	#((CH_CHUNKY_SIZE/4/2)<<6)|1,bltsize(a6)
	bra	ch_bld

ch_bp5:	; Pass 5:
	; Second quarter of the buffer: bit 2
	; 0022446699bbddff
	; ----------------
	lea	ch_tempbuffer2+CH_CHUNKY_SIZE/2,a0
	lea	ch_planes+CH_CHUNKY_SIZE/4,a1
	add.l	ch_planes_add,a1
	waitb
	move.w	#2,bltamod(a6)
	move.w	#2,bltbmod(a6)
	move.w	d0,bltdmod(a6)
	move.l	a0,bltapth(a6)
	addq	#2,a0
	move.l	a0,bltbpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#%1100110011001100,bltcdat(a6)
	move.w	#SRCA|SRCB|DEST|ANBC|ABC|ABNC|NABNC,bltcon0(a6)
	move.w	#(2<<BSHIFTSHIFT),bltcon1(a6)
	move.w	#((CH_CHUNKY_SIZE/4/2)<<6)|1,bltsize(a6)
	bra	ch_bld

ch_bp6:	; Pass 6:
	; Third quarter of the buffer: bit 1
	; 0022446699bbddff
	; ----------------
	lea	ch_tempbuffer2+CH_CHUNKY_SIZE-2-2,a0
	lea	ch_planes+CH_CHUNKY_SIZE-2,a1
	add.l	ch_planes_add,a1
	waitb
	move.l	a0,bltapth(a6)
	addq	#2,a0
	move.l	a0,bltbpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#(2<<ASHIFTSHIFT)|SRCA|SRCB|DEST|ANBC|ABC|ABNC|NABNC,bltcon0(a6)
	move.w	#BLITREVERSE,bltcon1(a6)
	move.w	#((CH_CHUNKY_SIZE/4/2)<<6)|1,bltsize(a6)
	lea	-CH_CHUNKY_SIZE/2-2(a0),a0
	lea	-CH_CHUNKY_SIZE/4(a1),a1
	bra	ch_bld

ch_bp7:	; Pass 7:
	; Fourth quarter of the buffer: bit 0
	; 0022446699bbddff
	; ----------------
	lea	ch_tempbuffer2+CH_CHUNKY_SIZE/2-2-2,a0
	lea	ch_planes+CH_CHUNKY_SIZE*3/4-2,a1
	add.l	ch_planes_add,a1
	waitb
	move.l	a0,bltapth(a6)
	addq	#2,a0
	move.l	a0,bltbpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#(2<<ASHIFTSHIFT)|SRCA|SRCB|DEST|ANBC|ABC|ABNC|NABNC,bltcon0(a6)
	move.w	#BLITREVERSE,bltcon1(a6)
	move.w	#((CH_CHUNKY_SIZE/4/2)<<6)|1,bltsize(a6)
	bra	ch_bld

ch_bp8:	; Pass 8: everything done - buffers will be changed in VBI
	; --------------------------------------------------------

ch_bld:	movem.l	(sp)+,a0-a1/a6
	move.l	(sp)+,d0
	rte
	rte

	; Vertical Blank Interrupt
	; ------------------------
VBI:	move.l	a0,-(sp)

	; Left mouse button pressed?
	; --------------------------
	btst	#6,$bfe001
	bne.s	.nolmb
	move.b	#1,quit
	clr.l	loop
.nolmb:	tst.b	quit
	bne.w	VBIok

	; Check whether there is a VBI function to run and if so run it
	; -------------------------------------------------------------
	move.l	part_vbi,d0
	beq	VBIok
	move.l	d0,a0
	jsr	(a0)

VBIok:	lea	custom,a0
	move.w	#INTF_VERTB,intreq(a0)
	move.w	#INTF_VERTB,intreq(a0)
	move.l	(sp)+,a0
	move.l	(sp)+,d0
	rte
	rte

	; Clear memory
	; ------------
clearmemory:
	add.l	#511,d7
	and.l	#$fffffe00,d7
	add.l	d7,a0
	lsr.l	#8,d7
	lsr.l	d7
	subq	#1,d7
	moveq	#0,d0
	moveq	#0,d1
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	moveq	#0,d5
	moveq	#0,d6
	sub.l	a1,a1
.loop:	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	movem.l	d0-d6/a1,-(a0)
	dbra	d7,.loop
	rts

	; Bitmapzoomer
	; ------------
bitmapzoomer:
	; Clear memory
	; ------------
	lea	bz_cl,a0
	move.l	#bz_requirements_chipmem,d7
	bsr	clearmemory
	lea	bz_mulu_planewidth,a0
	move.l	#bz_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	bz_ct,a0
	lea	bz_cl,a1
	move.w	#(bz_ct_data-bz_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Decrunch bitmap
	; ---------------
	lea	bz_bitmap,a0
	lea	bz_bitmap_stc,a1
	bsr	decrunch

	; Screen setup
	; ------------
	move.l	#bz_planes,d0
	lea	bz_cl_bpl1pth,a0
	moveq	#BZ_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#BZ_PLANEWIDTH,d0
	dbra	d7,.setplanesloop

	; Copy the ordered table to the bitmap zoomer table
	; -------------------------------------------------
	lea	table_order,a0
	lea	bz_srcoffsets,a1
	lea	bz_destoffsets,a2
	moveq	#16-1,d7
.bztf:	move.l	(a0),(a1)+
	move.l	(a0)+,(a2)+
	move.l	(a0),60(a1)
	move.l	(a0)+,60(a2)
	move.l	(a0),124(a1)
	move.l	(a0)+,124(a2)
	move.l	(a0),188(a1)
	move.l	(a0)+,188(a2)
	dbra	d7,.bztf

	; Remove pixels from the bitmap zoomer table
	; ------------------------------------------
	lea	bz_destoffsets,a0
	move.l	#255-1,d7
.bzt:	move.b	(a0)+,d0
	move.l	a0,a1
	move.l	d7,d6
	cmp.b	#128,d0
	bcs.s	.bztl
.bztr:
.bztrl:	move.b	(a1)+,d1
	cmp.b	d0,d1
	bcs.s	.bztrn
	subq	#1,d1
	move.b	d1,-1(a1)
.bztrn:	dbra	d6,.bztrl
	bra.s	.bztnx
.bztl:
.bztll:	move.b	(a1)+,d1
	cmp.b	d0,d1
	bhi.s	.bztln
	addq	#1,d1
	move.b	d1,-1(a1)
.bztln:	dbra	d6,.bztll
.bztnx:	dbra	d7,.bzt

	; Set palette
	; -----------
	lea	bz_bitmap+4*32*256,a0
	lea	bz_cl_palette+2,a1
	moveq	#16-1,d7
.cppal:	move.w	(a0)+,(a1)
	addq	#4,a1
	dbra	d7,.cppal

	move.l	#$fffffffe,bz_cl_data

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	bz_mulu_planewidth,a0
	move.l	#BZ_PLANEHEIGHT-1,d7
.mulu:	move.w	d0,(a0)+
	add.w	#BZ_PLANEWIDTH,d0
	dbra	d7,.mulu
	rts

bitmapzoomer_go:
	move.l  #bz_cl,cop1lch+custom
	move.l	#bitmapzoomer_main,part_main
	move.l	#bitmapzoomer_vbi,part_vbi
	rts

bitmapzoomer_main:
	tst.b	bz_wait
	bne	bz_ok
	lea	bz_srcoffsets,a0
	lea	bz_destoffsets,a1
	lea	bz_planes,a2
	lea	custom,a6

	; Zooming in our out?
	; -------------------
	tst.b	bz_direction
	bne	bz_out
	; Zooming in: Get destination pixel to add
	; ----------------------------------------
	moveq	#0,d0
	move.l	#255,d1
	sub.b	bz_current,d1
	move.b	(a1,d1.w),d0

	; Check whether the pixel is on the left or on the right half
	; -----------------------------------------------------------
	cmp.b	#128,d0
	bcs.s	bz_il
	; Blit width in words
	; -------------------
	move.w	#255,d1
	sub.w	d0,d1
	lsr.w	#4,d1
	addq	#1,d1
	; Modulo in bytes
	; ---------------
	move.w	#BZ_PLANEWIDTH,d2
	sub.w	d1,d2
	sub.w	d1,d2

	; How many pixels of the original are preserved
	; ---------------------------------------------
	and.w	#15,d0
	
	; Calculate blitter mask
	; ----------------------
	move.l	#$ffff7fff,d3
	lsr.w	d0,d3
	swap	d3

	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	#(1<<BSHIFTSHIFT),bltcon1(a6)
	move.w	#-1,bltadat(a6)
	move.l	d3,bltafwm(a6)
	move.w	d2,bltbmod(a6)
	move.w	d2,bltcmod(a6)
	move.w	d2,bltdmod(a6)
	add.w	d2,a2
	move.l	a2,bltbpth(a6)
	move.l	a2,bltcpth(a6)
	move.l	a2,bltdpth(a6)
	or.w	#(0<<6),d1
	move.w	d1,bltsize(a6)
	bra.w	bz_in

bz_il:	; Blit width in words
	; -------------------
	move.w	d0,d1
	lsr.w	#4,d1
	move.w	d1,d4
	add.w	d1,d4
	addq	#1,d1
	; Modulo in bytes
	; ---------------
	move.w	#BZ_PLANEWIDTH,d2
	sub.w	d1,d2
	sub.w	d1,d2

	; How many pixels of the original are preserved
	; ---------------------------------------------
	not.w	d0
	and.w	#15,d0

	; Calculate blitter mask
	; ----------------------
	move.l	#$fffffffe,d3
	lsl.w	d0,d3
	swap	d3

	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	#(1<<BSHIFTSHIFT)|BLITREVERSE,bltcon1(a6)
	move.w	#-1,bltadat(a6)
	move.l	d3,bltafwm(a6)
	move.w	d2,bltbmod(a6)
	move.w	d2,bltcmod(a6)
	move.w	d2,bltdmod(a6)
	add.w	d4,a2
	add.l	#BZ_PLANES*BZ_PLANESIZE-BZ_PLANEWIDTH,a2
	move.l	a2,bltbpth(a6)
	move.l	a2,bltcpth(a6)
	move.l	a2,bltdpth(a6)
	or.w	#(0<<6),d1
	move.w	d1,bltsize(a6)

bz_in:	; Get source and destination pixel to add
	; ---------------------------------------
	moveq	#0,d0
	moveq	#0,d1
	move.l	#255,d2
	sub.b	bz_current,d2
	move.b	(a0,d2.w),d0
	move.b	(a1,d2.w),d1
	; Calculate first word of the source bitmap
	; -----------------------------------------
	lea	bz_bitmap,a0
	move.w	d0,d2
	lsr.w	#4,d2
	add.w	d2,a0
	add.w	d2,a0
	; Calculate first word of the destination bitmap
	; ----------------------------------------------
	lea	bz_planes,a1
	move.w	d1,d2
	lsr.w	#4,d2
	add.w	d2,a1
	add.w	d2,a1
	; Calculate destination pixel mask
	; --------------------------------
	and.w	#15,d0
	and.w	#15,d1
	move.l	#$8000,d2
	lsr.w	d1,d2
	; Calculate shift
	; ---------------
	move.w	d1,d4
	sub.w	d0,d4
	bpl	bz_sp
	and.w	#15,d4
	ror.w	#4,d4
	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	d4,bltcon1(a6)
	move.w	#-1,bltadat(a6)
	move.l	d2,bltafwm(a6)
	move.w	#32-4,bltbmod(a6)
	move.w	#BZ_PLANEWIDTH-4,bltcmod(a6)
	move.w	#BZ_PLANEWIDTH-4,bltdmod(a6)
	move.l	a0,bltbpth(a6)
	subq	#2,a1
	move.l	a1,bltcpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#(0<<6)+2,bltsize(a6)
	bra	bz_dn
bz_sp:	and.w	#15,d4
	ror.w	#4,d4
	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	d4,bltcon1(a6)
	move.w	d2,bltadat(a6)
	move.l	#-1,bltafwm(a6)
	move.w	#32-2,bltbmod(a6)
	move.w	#BZ_PLANEWIDTH-2,bltcmod(a6)
	move.w	#BZ_PLANEWIDTH-2,bltdmod(a6)
	move.l	a0,bltbpth(a6)
	move.l	a1,bltcpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#(0<<6)+1,bltsize(a6)
	bra	bz_dn
	
bz_out:	; Zooming out: Get destination pixel to remove
	; --------------------------------------------
	moveq	#0,d0
	moveq	#0,d1
	move.b	bz_current,d1
	move.b	(a1,d1.w),d0

	; Check whether the pixel is on the left or on the right half
	; -----------------------------------------------------------
	cmp.b	#128,d0
	bcs.s	bz_ol
	; Blit width in words
	; -------------------
	move.w	#255,d1
	sub.b	d0,d1
	lsr.w	#4,d1
	addq	#1,d1
	; Modulo in bytes
	; ---------------
	move.w	#BZ_PLANEWIDTH,d2
	sub.w	d1,d2
	sub.w	d1,d2

	; How many pixels of the original are preserved
	; ---------------------------------------------
	and.w	#15,d0
	
	; Calculate blitter mask
	; ----------------------
	move.l	#$fffeffff,d3
	lsr.w	d0,d3

	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	#(1<<BSHIFTSHIFT)|BLITREVERSE,bltcon1(a6)
	move.w	#-1,bltadat(a6)
	move.l	d3,bltafwm(a6)
	move.w	d2,bltbmod(a6)
	move.w	d2,bltcmod(a6)
	move.w	d2,bltdmod(a6)
	add.l	#BZ_PLANES*BZ_PLANESIZE-2,a2
	move.l	a2,bltbpth(a6)
	move.l	a2,bltcpth(a6)
	move.l	a2,bltdpth(a6)
	or.w	#(0<<6),d1
	move.w	d1,bltsize(a6)
	bra.s	bz_dn

bz_ol:	; Blit width in words
	; -------------------
	move.b	d0,d1
	lsr.w	#4,d1
	addq	#1,d1
	; Modulo in bytes
	; ---------------
	move.w	#BZ_PLANEWIDTH,d2
	sub.w	d1,d2
	sub.w	d1,d2

	; How many pixels of the original are preserved
	; ---------------------------------------------
	and.w	#15,d0
	sub.w	#15,d0
	neg.w	d0

	; Calculate blitter mask
	; ----------------------
	move.l	#$7fffffff,d3
	lsl.w	d0,d3

	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	#(1<<BSHIFTSHIFT),bltcon1(a6)
	move.w	#-1,bltadat(a6)
	move.l	d3,bltafwm(a6)
	move.w	d2,bltbmod(a6)
	move.w	d2,bltcmod(a6)
	move.w	d2,bltdmod(a6)
	move.l	a2,bltbpth(a6)
	move.l	a2,bltcpth(a6)
	move.l	a2,bltdpth(a6)
	or.w	#(0<<6),d1
	move.w	d1,bltsize(a6)

bz_dn:	add.b	#1,bz_current
	bne.s	bz_ok
	tst.b	bz_direction
	beq.s	.dirok
	move.b	#255,bz_current
	bra.s	bz_ok
.dirok:	eor.b	#1,bz_direction
	move.w	#1,bz_wait
bz_ok:	move.b	#1,render
	rts

bitmapzoomer_vbi:
	movem.l	d1-d4/d7/a1,-(sp)

	tst.w	bz_wait
	beq.s	.nwait
	add.w	#1,bz_wait
	cmp.w	#190,bz_wait
	bne	.nrend
	clr.w	bz_wait
.nwait:	lea	bz_cl_data,a0
	lea	bz_mulu_planewidth,a1
	tst.b	bz_direction
	bne.s	.out
	move.l	#255,d0
	sub.b	bz_current,d0
	bra.s	.curro
.out:	moveq	#0,d0
	move.b	bz_current,d0
.curro:	move.l	d0,d1
	lsr.w	d0
	add.w	#$28,d0
	lsl.w	#8,d0
	or.w	#1,d0
	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bplcon0,(a0)+
	move.w	bz_cl_bplcon0+2,(a0)+

	move.w	#255,d7
	sub.w	d1,d7
	bne.s	.nzero
	moveq	#1,d7
.nzero:	move.w	#$ff00,d2
	divu	d7,d2
	ext.l	d2
	moveq	#0,d1
	subq	#1,d7
.loop:	move.l	d1,d3
	add.l	d2,d1
	move.l	d1,d4
	lsr.w	#8,d3
	lsr.w	#8,d4
	sub.w	d3,d4
	add.w	d4,d4
	move.w	(a1,d4.w),d4
	add.w	d4,d4
	add.w	d4,d4
	sub.w	#BZ_PLANEWIDTH,d4
	move.w	#bpl1mod,(a0)+
	move.w	d4,(a0)+
	move.w	#bpl2mod,(a0)+
	move.w	d4,(a0)+
	add.w	#$100,d0
	cmp.w	#1,d0
	bne.w	.nspec
	move.l	#$ffd1fffe,(a0)+
.nspec:	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	dbra	d7,.loop
	move.w	#bplcon0,(a0)+
	move.w	#0,(a0)+
	move.l	#$fffffffe,(a0)+

	tst.b	render
	beq.s	.nrend
	clr.b	render
.nrend:	movem.l	(sp)+,d1-d4/d7/a1
	rts

	; 2x2 chunky zoom & rotate
	; ------------------------
zoomrotate:
	; Clear memory
	; ------------
	lea	ch_cl,a0
	move.l	#ch_requirements_chipmem,d7
	bsr	clearmemory
	lea	ch_planes_add,a0
	move.l	#zr_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	ch_ct,a0
	lea	ch_cl,a1
	move.w	#(ch_ct_data-ch_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Screen setup
	; ------------
	move.l	#ch_planes,d0
	lea	ch_cl_bpl1pth,a0
	moveq	#CH_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#CH_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Create copperlist
	; -----------------
	lea	ch_cl_data,a0
	move.l	#$a801-(CH_PLANEHEIGHT<<8),d0
	move.l	#CH_PLANEHEIGHT-1,d7
.cop:	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bpl1mod,(a0)+
	move.w	#-CH_PLANEWIDTH,(a0)+
	move.w	#bpl2mod,(a0)+
	move.w	#-CH_PLANEWIDTH,(a0)+
	add.w	#$100,d0
	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bpl1mod,(a0)+
	clr.w	(a0)+
	move.w	#bpl2mod,(a0)+
	clr.w	(a0)+
	add.w	#$100,d0
	dbra	d7,.cop
	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bplcon0,(a0)+
	move.w	#0,(a0)+
	move.l	#$fffffffe,(a0)+

	; Decrunch source image
	; ---------------------
	lea	zr_source,a0
	lea	zr_source_stc,a1
	bsr	decrunch

	; Expand the source image
	; -----------------------
	lea	zr_source,a0
	lea	zr_source_exp,a1
	move.l	a1,a2
	move.l	a1,a3
	move.l	a1,a4
	add.l	#1*CH_SOURCE_SIZE*2,a2
	add.l	#2*CH_SOURCE_SIZE*2,a3
	add.l	#3*CH_SOURCE_SIZE*2,a4
	move.l	#CH_SOURCE_SIZE-1,d7
.cpchk:	move.b	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	move.w	d0,d3
	and.w	#$8,d0
	and.w	#$4,d1
	and.w	#$2,d2
	and.w	#$1,d3
	lsl.w	#3,d0
	lsl.w	#2,d1
	add.w	d2,d2
	or.w	d1,d0
	or.w	d2,d0
	or.w	d3,d0
	move.w	d0,d1
	add.w	d1,d1
	or.w	d1,d0
	move.w	d0,d1
	lsl.w	#8,d0
	or.w	d1,d0
	move.w	d0,(a1)+
	move.w	d0,(a2)+
	move.w	d0,(a3)+
	move.w	d0,(a4)+
	dbra	d7,.cpchk

	; Prepare Z&R row writing code
	; ----------------------------
	lea	zr_writerow,a0
	moveq	#CH_CHUNKY_WIDTH-1,d7
.zr:	move.l	#$32e80000,(a0)+	; move.w n(a0),(a1)+
	dbra	d7,.zr

	move.l	#-$e0000,zr_angle_add
	rts

zoomrotate_go:
	move.w	#INTF_SETCLR|INTF_BLIT,intena+custom
	move.l  #ch_cl,cop1lch+custom
	move.l	#zoomrotate_main,part_main
	move.l	#zoomrotate_vbi,part_vbi
	rts

zoomrotate_main:
	; If chunky to planar is in progress do nothing
	; ---------------------------------------------
	tst.b	ch_c2p_pass
	beq.s	.c2p
	rts

	; Initiate chunky to planar (rest of it is in the blitter interrupt)
	; ------------------------------------------------------------------
.c2p:	move.b	#1,ch_c2p_pass

	lea	custom,a6
	; Pass 1:
	; 000000009999999922222222bbbbbbbb44444444dddddddd66666666ffffffff
	; ----------------------------------------------------------------
	lea	ch_chunky,a0
	move.l	ch_add,d0
	; Store so that this value will be used even if blit finishes early
	; -----------------------------------------------------------------
	move.l	d0,ch_add_current
	add.l	d0,a0
	lea	ch_tempbuffer1,a1
	waitb
	move.l	#-1,bltafwm(a6)
	move.w	#8,bltamod(a6)
	move.w	#8,bltbmod(a6)
	move.w	#0,bltdmod(a6)
	move.l	a0,bltapth(a6)
	addq	#8,a0
	move.l	a0,bltbpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#%1111111100000000,bltcdat(a6)
	move.w	#SRCA|SRCB|DEST|ANBC|ABC|ABNC|NABNC,bltcon0(a6)
	move.w	#(8<<BSHIFTSHIFT),bltcon1(a6)
	move.w	#((CH_CHUNKY_SIZE*2/8/2)<<6)|4,bltsize(a6)

	lea	zr_writerow+2,a0
	lea	sinus,a1
	move.w	zr_angle,d0
	add.w	d0,d0
	move.w	zr_zoom,d2
	move.w	d0,d1
	add.w	#512,d1
	and.w	#2046,d1
	move.w	(a1,d0.w),d0
	move.w	(a1,d1.w),d1
	; Leave room for zooming out
	; --------------------------
	asr.w	#3,d0
	asr.w	#3,d1
	; Apply zoom to dx/2 and dy/2
	; ---------------------------
	muls	d2,d0
	muls	d2,d1
	asr.l	#8,d0
	asr.l	#8,d1
	; Centering: x = -CHUNKY_HEIGHT/2*dy + CHUNKY_WIDTH/2*dx
	;            y =  CHUNKY_HEIGHT/2*dx + CHUNKY_WIDTH/2*dy
	; This is inverse to what is done in the main loop - going "backwards"
	; --------------------------------------------------------------------
	moveq	#CH_CHUNKY_HEIGHT,d2
	moveq	#CH_CHUNKY_HEIGHT,d3
	muls	d1,d2
	muls	d0,d3
	asl.l	#3,d2
	asl.l	#3,d3
	neg.l	d3
	moveq	#CH_CHUNKY_WIDTH,d4
	moveq	#CH_CHUNKY_WIDTH,d5
	muls	d0,d4
	muls	d1,d5
	asl.l	#3,d4
	asl.l	#3,d5
	sub.l	d4,d2
	sub.l	d5,d3
	; Centering in texture
	; --------------------
	add.l	#(CH_SOURCE_WIDTH/2)<<16,d2
	add.l	#(CH_SOURCE_HEIGHT/2)<<16,d3
	move.l	#$7fffff,d4
	; Get dx, dy
	; ----------
	asl.l	#4,d0
	asl.l	#4,d1
	; Store x, y, dx and dy for the main loop
	; ---------------------------------------
	move.l	d2,a2
	move.l	d3,a3
	move.l	d0,a4
	move.l	d1,a5
	; For calculating offsets for one row use x=y=0
	; ---------------------------------------------
	moveq	#0,d2
	moveq	#0,d3
	; Extra wanking: delta and wanker :)
	; ----------------------------------
	move.l	#$800,a6
	moveq	#0,d5
	moveq	#CH_CHUNKY_WIDTH-1,d7
.chx:	and.l	d4,d2
	and.l	d4,d3
	move.l	d3,d6
	swap	d2
	swap	d6
	lsl.w	#7,d6
	or.w	d2,d6
	add.w	d6,d6
	move.w	d6,(a0)
	swap	d2
	addq	#4,a0
	add.l	d0,d2
	add.l	d5,d2
	add.l	a6,d5
	add.l	d1,d3
	dbra	d7,.chx

	move.l	a2,d2
	move.l	a3,d3
	lea	ch_chunky,a1
	lea	zr_source_exp,a2
	; Use the other buffer for rendering chunky
	; -----------------------------------------
	move.l	ch_add_current,d0
	eor.l	#CH_CHUNKY_SIZE*2,d0
	add.l	d0,a1
	moveq	#CH_PLANEHEIGHT-1,d7
	; One row of Z&R data is written here using move.b n(a0),(a1)+
	; ------------------------------------------------------------
zr_lp:	and.l	d4,d2
	and.l	d4,d3
	swap	d2
	move.l	d3,d6
	swap	d6
	lsl.w	#7,d6
	or.w	d2,d6
	add.w	d6,d6
	lea	(a2,d6.w),a0
	swap	d2
zr_writerow:
	ds.l	CH_CHUNKY_WIDTH
	; To advance to the next row: x-=dy, y+=dx
	; ----------------------------------------
	sub.l	a5,d2
	add.l	a4,d3
	dbra	d7,zr_lp
	rts

zoomrotate_vbi:
	movem.l	a1-a2/d1-d2/d7,-(sp)

	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#3,d0
	bcs.s	.fade
	cmp.w	#116,d0
	bcs	.npal
.fade:	mulu	#6,d0
	addq	#6,d0
	sub.w	tp_wait,d0
	cmp.w	#16,d0
	bhi.s	.fdout
	lsl.w	#4,d0
	; Fade palette in
	; ---------------
	lea	zr_palette,a0
	lea	table_fade,a1
	add.w	d0,a1
	lea	ch_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl1:	move.w	#$fff,d0
	sub.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	#$fff,d1
	sub.w	d0,d1
	move.w	d1,(a2)
	addq	#4,a2
	dbra	d7,.fdpl1
	bra.s	.npal

.fdout:	move.w	#119*6-1,d1
	sub.w	d0,d1
	bmi.s	.npal
	cmp.w	#16,d1
	bhi.s	.npal
	lsl.w	#4,d1
	; Fade palette out
	; ----------------
	lea	zr_palette,a0
	lea	table_fade,a1
	add.w	d1,a1
	lea	ch_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl2:	move.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,(a2)
	addq	#4,a2
	dbra	d7,.fdpl2

.npal:	; Update parameters
	; -----------------
	add.l	#$800,zr_angle_add
	move.l	zr_angle_add,d0
	add.l	d0,zr_angle
	and.l	#$3ffffff,zr_angle
	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#96,d0
	bcs.s	.out
	sub.w	#4,zr_zoom
	bra.s	.zoomd
.out:	add.w	#1,zr_zoom
.zoomd:	and.w	#2047,zr_zoom

	; C2P done?
	; ---------
	cmp.b	#8,ch_c2p_pass
	bne.s	.vbiok

	; Display the rendered buffer
	; ---------------------------
	move.l	#ch_planes,d0
	add.l	ch_planes_add,d0
	lea	ch_cl_bpl1pth,a0
	moveq	#CH_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#CH_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Switch buffers
	; --------------
	eor.l	#CH_PLANES*CH_PLANESIZE,ch_planes_add
	eor.l	#CH_CHUNKY_SIZE*2,ch_add
	clr.b	ch_c2p_pass
.vbiok:	movem.l	(sp)+,a1-a2/d1-d2/d7
	rts

	; 2x2 chunky sphere mapping
	; -------------------------
spheremapping:
	; Clear memory
	; ------------
	lea	ch_cl,a0
	move.l	#ch_requirements_chipmem,d7
	bsr	clearmemory
	lea	ch_planes_add,a0
	move.l	#sm_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	ch_ct,a0
	lea	ch_cl,a1
	move.w	#(ch_ct_data-ch_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Screen setup
	; ------------
	move.l	#ch_planes,d0
	lea	ch_cl_bpl1pth,a0
	moveq	#CH_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#CH_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Create copperlist
	; -----------------
	lea	ch_cl_data,a0
	move.l	#$a801-(CH_PLANEHEIGHT<<8),d0
	move.l	#CH_PLANEHEIGHT-1,d7
.cop:	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bpl1mod,(a0)+
	move.w	#-CH_PLANEWIDTH,(a0)+
	move.w	#bpl2mod,(a0)+
	move.w	#-CH_PLANEWIDTH,(a0)+
	add.w	#$100,d0
	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bpl1mod,(a0)+
	clr.w	(a0)+
	move.w	#bpl2mod,(a0)+
	clr.w	(a0)+
	add.w	#$100,d0
	dbra	d7,.cop
	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bplcon0,(a0)+
	move.w	#0,(a0)+
	move.l	#$fffffffe,(a0)+

	; Decrunch source image
	; ---------------------
	lea	sm_source,a0
	lea	sm_source_stc,a1
	bsr	decrunch

	; Expand the source image
	; -----------------------
	lea	sm_source,a0
	lea	sm_source_exp,a1
	move.l	a1,a2
	move.l	a1,a3
	move.l	a1,a4
	add.l	#1*CH_SOURCE_SIZE*2,a2
	add.l	#2*CH_SOURCE_SIZE*2,a3
	add.l	#3*CH_SOURCE_SIZE*2,a4
	move.l	#CH_SOURCE_SIZE-1,d7
.cpchk:	move.b	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	move.w	d0,d3
	and.w	#$8,d0
	and.w	#$4,d1
	and.w	#$2,d2
	and.w	#$1,d3
	lsl.w	#3,d0
	lsl.w	#2,d1
	add.w	d2,d2
	or.w	d1,d0
	or.w	d2,d0
	or.w	d3,d0
	move.w	d0,d1
	add.w	d1,d1
	or.w	d1,d0
	move.w	d0,d1
	lsl.w	#8,d0
	or.w	d1,d0
	move.w	d0,(a1)+
	move.w	d0,(a2)+
	move.w	d0,(a3)+
	move.w	d0,(a4)+
	dbra	d7,.cpchk

	; Decrunch sphere mapping code
	; ----------------------------
	lea	sm_write,a0
	lea	sm_write_stc,a1
	bsr	decrunch
	move.w	#$4e75,sm_write_end
	rts

spheremapping_go:
	move.w	#INTF_SETCLR|INTF_BLIT,intena+custom
	move.l  #ch_cl,cop1lch+custom
	move.l	#spheremapping_main,part_main
	move.l	#spheremapping_vbi,part_vbi
	rts
	
spheremapping_main:
	; If chunky to planar is in progress do nothing
	; ---------------------------------------------
	tst.b	ch_c2p_pass
	beq.s	.c2p
	rts

	; Initiate chunky to planar (rest of it is in the blitter interrupt)
	; ------------------------------------------------------------------
.c2p:	move.b	#1,ch_c2p_pass

	lea	custom,a6
	; Pass 1:
	; 000000009999999922222222bbbbbbbb44444444dddddddd66666666ffffffff
	; ----------------------------------------------------------------
	lea	ch_chunky,a0
	move.l	ch_add,d0
	; Store so that this value will be used even if blit finishes early
	; -----------------------------------------------------------------
	move.l	d0,ch_add_current
	add.l	d0,a0
	lea	ch_tempbuffer1,a1
	waitb
	move.l	#-1,bltafwm(a6)
	move.w	#8,bltamod(a6)
	move.w	#8,bltbmod(a6)
	move.w	#0,bltdmod(a6)
	move.l	a0,bltapth(a6)
	addq	#8,a0
	move.l	a0,bltbpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#%1111111100000000,bltcdat(a6)
	move.w	#SRCA|SRCB|DEST|ANBC|ABC|ABNC|NABNC,bltcon0(a6)
	move.w	#(8<<BSHIFTSHIFT),bltcon1(a6)
	move.w	#((CH_CHUNKY_SIZE*2/8/2)<<6)|4,bltsize(a6)

	lea	sm_source_exp,a0
	add.w	sm_x,a0
	add.w	sm_y,a0
	lea	ch_chunky,a1
	; Use the other buffer for rendering chunky
	; -----------------------------------------
	move.l	ch_add_current,d0
	eor.l	#CH_CHUNKY_SIZE*2,d0
	add.l	d0,a1
	jmp	sm_write

spheremapping_vbi:
	movem.l	a1-a2/d1-d2/d7,-(sp)

	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#3,d0
	bcs.s	.fade
	cmp.w	#112,d0
	bcs	.npal
.fade:	mulu	#6,d0
	addq	#6,d0
	sub.w	tp_wait,d0
	cmp.w	#16,d0
	bhi.s	.fdout
	lsl.w	#4,d0
	; Fade palette in
	; ---------------
	lea	sm_palette,a0
	lea	table_fade,a1
	add.w	d0,a1
	lea	ch_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl1:	move.w	#$fff,d0
	sub.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	#$fff,d1
	sub.w	d0,d1
	move.w	d1,(a2)
	addq	#4,a2
	dbra	d7,.fdpl1
	bra.s	.npal

.fdout:	move.w	#115*6-1,d1
	sub.w	d0,d1
	bmi.s	.npal
	cmp.w	#16,d1
	bhi.s	.npal
	lsl.w	#4,d1
	; Fade palette out
	; ----------------
	lea	sm_palette,a0
	lea	table_fade,a1
	add.w	d1,a1
	lea	ch_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl2:	move.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,(a2)
	addq	#4,a2
	dbra	d7,.fdpl2

.npal:	; Update parameters
	; -----------------
	lea	sinus,a0
	move.w	sm_xsinus,d0
	move.w	(a0,d0.w),d0
	add.w	#$8000,d0
	lsr.w	#8,d0
	lsr.w	d0
	sub.w	#$40,d0
	and.w	#$fe,d0
	move.w	d0,sm_x
	move.w	sm_ysinus,d0
	move.w	(a0,d0.w),d0
	add.w	#$8000,d0
	lsr.w	#2,d0
	sub.w	#$2000,d0
	and.w	#$7f00,d0
	move.w	d0,sm_y

	add.w	#8,sm_xsinus
	add.w	#6,sm_ysinus
	and.w	#2046,sm_xsinus
	and.w	#2046,sm_ysinus
	
	; C2P done?
	; ---------
	cmp.b	#8,ch_c2p_pass
	bne.s	.vbiok

	; Display the rendered buffer
	; ---------------------------
	move.l	#ch_planes,d0
	add.l	ch_planes_add,d0
	lea	ch_cl_bpl1pth,a0
	moveq	#CH_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#CH_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Switch buffers
	; --------------
	eor.l	#CH_PLANES*CH_PLANESIZE,ch_planes_add
	eor.l	#CH_CHUNKY_SIZE*2,ch_add
	clr.b	ch_c2p_pass
.vbiok:	movem.l	(sp)+,a1-a2/d1-d2/d7
	rts

	; 2x2 chunky color tunnel
	; -----------------------
colortunnel:
	; Clear memory
	; ------------
	lea	ch_cl,a0
	move.l	#ch_requirements_chipmem,d7
	bsr	clearmemory
	lea	ch_planes_add,a0
	move.l	#ct_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	ch_ct,a0
	lea	ch_cl,a1
	move.w	#(ch_ct_data-ch_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Screen setup
	; ------------
	move.l	#ch_planes,d0
	lea	ch_cl_bpl1pth,a0
	moveq	#CH_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#CH_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Create copperlist
	; -----------------
	lea	ch_cl_data,a0
	move.l	#$a801-(CH_PLANEHEIGHT<<8),d0
	move.l	#CH_PLANEHEIGHT-1,d7
.cop:	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bpl1mod,(a0)+
	move.w	#-CH_PLANEWIDTH,(a0)+
	move.w	#bpl2mod,(a0)+
	move.w	#-CH_PLANEWIDTH,(a0)+
	add.w	#$100,d0
	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bpl1mod,(a0)+
	clr.w	(a0)+
	move.w	#bpl2mod,(a0)+
	clr.w	(a0)+
	add.w	#$100,d0
	dbra	d7,.cop
	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bplcon0,(a0)+
	move.w	#0,(a0)+
	move.l	#$fffffffe,(a0)+

	; Copy palette
	; ------------
	lea	ct_palette,a0
	lea	ch_cl_palette+2,a1
	moveq	#16-1,d7
.pallp:	move.w	(a0)+,(a1)
	addq	#4,a1
	dbra	d7,.pallp

	; Create multiply table
	; ---------------------
	lea	ct_mult_16,a0
	moveq	#0,d0
	moveq	#16-1,d7
.mult1:	moveq	#1,d1
	moveq	#16-1,d6
.mult2:	move.l	d0,d2
	mulu	d1,d2
	addq	#8,d2
	lsr.w	#4,d2
	move.b	d2,(a0)+
	addq	#1,d1
	dbra	d6,.mult2
	addq	#1,d0
	dbra	d7,.mult1

	; Decrunch color tunnel code
	; --------------------------
	lea	ct_write,a0
	lea	ct_write_stc,a1
	bsr	decrunch
	move.w	#$4e75,ct_write_end
	rts

colortunnel_go:
	move.w	#INTF_SETCLR|INTF_BLIT,intena+custom
	move.l  #ch_cl,cop1lch+custom
	move.l	#colortunnel_main,part_main
	move.l	#colortunnel_vbi,part_vbi
	rts

colortunnel_main:
	; If chunky to planar is in progress do nothing
	; ---------------------------------------------
	tst.b	ch_c2p_pass
	beq.s	.c2p
	rts

	; Initiate chunky to planar (rest of it is in the blitter interrupt)
	; ------------------------------------------------------------------
.c2p:	move.b	#1,ch_c2p_pass

	lea	custom,a6
	; Pass 1:
	; 000000009999999922222222bbbbbbbb44444444dddddddd66666666ffffffff
	; ----------------------------------------------------------------
	lea	ch_chunky,a0
	move.l	ch_add,d0
	; Store so that this value will be used even if blit finishes early
	; -----------------------------------------------------------------
	move.l	d0,ch_add_current
	add.l	d0,a0
	lea	ch_tempbuffer1,a1
	waitb
	move.l	#-1,bltafwm(a6)
	move.w	#8,bltamod(a6)
	move.w	#8,bltbmod(a6)
	move.w	#0,bltdmod(a6)
	move.l	a0,bltapth(a6)
	addq	#8,a0
	move.l	a0,bltbpth(a6)
	move.l	a1,bltdpth(a6)
	move.w	#%1111111100000000,bltcdat(a6)
	move.w	#SRCA|SRCB|DEST|ANBC|ABC|ABNC|NABNC,bltcon0(a6)
	move.w	#(8<<BSHIFTSHIFT),bltcon1(a6)
	move.w	#((CH_CHUNKY_SIZE*2/8/2)<<6)|4,bltsize(a6)

	; Render new data if necessary
	; ----------------------------
ct_r:	lea	sinus,a0
	move.w	ct_rendered,d0
	cmp.w	ct_offset,d0
	beq	ct_eff
	add.w	#CT_ANGLE_RANGE*2,ct_rendered
	cmp.w	#CT_MAX_OFFSET,ct_rendered
	bcs.s	.ctok
	sub.w	#CT_MAX_OFFSET,ct_rendered
.ctok:	; Update sinuses
	; --------------
	add.w	#44,ct_base_sin
	add.w	#26,ct_mult_sin
	add.w	#2,ct_add_sin
	add.w	#4,ct_first_sin
	and.w	#2046,ct_base_sin
	and.w	#2046,ct_mult_sin
	and.w	#2046,ct_add_sin
	and.w	#2046,ct_first_sin

	move.w	ct_base_sin,d0
	move.w	(a0,d0.w),d1
	add.w	#$8000,d1
	rol.w	#4,d1
	and.w	#15,d1
	move.w	ct_mult_sin,d0
	move.w	(a0,d0.w),d2
	add.w	#$8000,d2
	lsr.w	#8,d2
	lsr.w	d2
	add.w	#$80,d2
	and.w	#$f0,d2
	move.w	ct_add_sin,d0
	move.w	(a0,d0.w),d3
	add.w	#$8000,d3
	lsr.w	#8,d3
	and.w	#254,d3
	addq	#8,d3
	move.w	ct_first,d0
	move.w	ct_first_sin,d7
	move.w	(a0,d7.w),d7
	asr.w	#8,d7
	asr.w	#2,d7
	add.w	d7,d7
	add.w	d7,d0
	and.w	#2046,d0
	move.w	d0,ct_first
	lea	ch_conversion,a1
	lea	ct_buffer,a2
	add.w	ct_rendered,a2
	lea	CT_MAX_OFFSET-CT_ANGLE_RANGE*2(a2),a2
	lea	CT_MAX_OFFSET(a2),a3
	lea	ct_buffer+2*CT_MAX_OFFSET,a4
	lea	ct_mult_16,a5
	moveq	#CT_ANGLE_RANGE-1,d7
.rend:	cmp.l	a4,a3
	bcs	.a3ok
	sub.l	#2*CT_MAX_OFFSET,a3
.a3ok:	move.w	(a0,d0.w),d4
	add.w	#$8000,d4
	rol.w	#4,d4
	and.w	#15,d4
	add.w	d2,d4
	move.b	(a5,d4.w),d4
	add.w	d1,d4
	and.w	#$f,d4
	add.w	d4,d4
	move.w	(a1,d4.w),d4
	move.w	d4,(a2)+
	move.w	d4,(a3)+
	add.w	d3,d0
	and.w	#2046,d0
	dbra	d7,.rend
	bra	ct_r

ct_eff:	lea	ct_buffer,a0
	add.w	ct_offset,a0
	lea	ch_chunky,a1
	; Use the other buffer for rendering chunky
	; -----------------------------------------
	move.l	ch_add_current,d0
	eor.l	#CH_CHUNKY_SIZE*2,d0
	add.l	d0,a1
	jmp	ct_write

colortunnel_vbi:
	movem.l	a1-a2/d1-d2/d7,-(sp)

	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#3,d0
	bcs.s	.fade
	cmp.w	#118,d0
	bcs	.npal
.fade:	mulu	#6,d0
	addq	#6,d0
	sub.w	tp_wait,d0
	cmp.w	#16,d0
	bhi.s	.fdout
	lsl.w	#4,d0
	; Fade palette in
	; ---------------
	lea	ct_palette,a0
	lea	table_fade,a1
	add.w	d0,a1
	lea	ch_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl1:	move.w	#$fff,d0
	sub.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	#$fff,d1
	sub.w	d0,d1
	move.w	d1,(a2)
	addq	#4,a2
	dbra	d7,.fdpl1
	bra.s	.npal

.fdout:	move.w	#121*6-1,d1
	sub.w	d0,d1
	bmi.s	.npal
	cmp.w	#16,d1
	bhi.s	.npal
	lsl.w	#4,d1
	; Fade palette out
	; ----------------
	lea	ct_palette,a0
	lea	table_fade,a1
	add.w	d1,a1
	lea	ch_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl2:	move.w	#$fff,d0
	sub.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	#$fff,d1
	sub.w	d0,d1
	move.w	d1,(a2)
	addq	#4,a2
	dbra	d7,.fdpl2

.npal:	; Update parameters
	; -----------------
	add.w	#CT_ANGLE_RANGE*2,ct_offset
	cmp.w	#CT_MAX_OFFSET,ct_offset
	bcs.s	.ctok
	sub.w	#CT_MAX_OFFSET,ct_offset
.ctok:

	; C2P done?
	; ---------
	cmp.b	#8,ch_c2p_pass
	bne.s	.vbiok

	; Display the rendered buffer
	; ---------------------------
	move.l	#ch_planes,d0
	add.l	ch_planes_add,d0
	lea	ch_cl_bpl1pth,a0
	moveq	#CH_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#CH_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Switch buffers
	; --------------
	eor.l	#CH_PLANES*CH_PLANESIZE,ch_planes_add
	eor.l	#CH_CHUNKY_SIZE*2,ch_add
	clr.b	ch_c2p_pass
	move.w	#$fff,ne_cl_palette+2
.vbiok:	movem.l	(sp)+,a1-a2/d1-d2/d7
	rts

cityscape:
	; Clear memory
	; ------------
	lea	cs_cl,a0
	move.l	#cs_requirements_chipmem,d7
	bsr	clearmemory
	lea	cs_planes_add,a0
	move.l	#cs_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	cs_ct,a0
	lea	cs_cl,a1
	move.w	#(cs_ct_data-cs_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Screen setup
	; ------------
	move.l	#cs_planes,d0
	add.l	#5*CS_PLANESIZE,d0
	lea	cs_cl_bpl1pth,a0
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	cs_mulu_planewidth,a0
	move.l	#CS_PLANEHEIGHT-1,d7
.mulu:	move.w	d0,(a0)+
	add.w	#CS_PLANEWIDTH,d0
	dbra	d7,.mulu

	; Create octants table
	; --------------------
	move.b	#0|LINEMODE,cs_octants		;y1<y2, x1<x2, dx<dy = okt6
	move.b	#16|LINEMODE,cs_octants+1	;y1<y2, x1<x2, dx>dy = okt7
	move.b	#8|LINEMODE,cs_octants+2		;y1<y2, x1>x2, dx<dy = okt5
	move.b	#20|LINEMODE,cs_octants+3	;y1<y2, x1>x2, dx>dy = okt4

	; Create ordered table
	; --------------------
	lea	table_order,a0
	lea	cs_order,a1
	moveq	#0,d1
	moveq	#16-1,d7
.ord1:	moveq	#0,d3
	moveq	#16-1,d6
.ord2:	move.b	(a0)+,d1
	move.w	d7,d2
	addq	#1,d2
	lsl.w	#4,d2
	sub.w	d1,d2
	addx.w	d3,d3
	dbra	d6,.ord2
	move.w	d3,(a1)+
	dbra	d7,.ord1

	; Create gradient helper bitplane
	; -------------------------------
	lea	cs_planes,a1
	add.l	#5*CS_PLANESIZE,a1
	move.l	#CS_PLANEHEIGHT/16-1,d7
.grad1:	lea	cs_order,a0
	moveq	#16-1,d6
.grad2:	moveq	#CS_PLANEWIDTH/2-1,d5
.grad3:	move.w	(a0),(a1)+
	dbra	d5,.grad3
	addq	#2,a0
	dbra	d6,.grad2
	dbra	d7,.grad1

	; Create multiply table
	; ---------------------
rollo:	lea	cs_mulu_16,a0
	moveq	#1,d0
	moveq	#16-1,d7
.mulu1:	moveq	#0,d1
	moveq	#16-1,d6
.mulu2:	move.w	d1,d2
	mulu	d0,d2
	lsr.w	#4,d2
	move.b	d2,(a0)+
	addq	#1,d1
	dbra	d6,.mulu2
	addq	#1,d0
	dbra	d7,.mulu1

	; Create copperlist
	; -----------------
	lea	cs_mulu_16,a0
	lea	cs_gradient,a1
	lea	cs_cl_data,a2
	move.l	#$3001fffe,a3
	move.w	cs_citycolor,a4
	moveq	#(CS_PLANEHEIGHT-1)/16-1,d7
.coplp:	cmp.l	#$0001fffe,a3
	bne.s	.nskip
	move.l	#$ffd1fffe,a3
.nskip:	move.l	a3,(a2)+
	move.w	(a1)+,a5
	move.w	(a1),a6
	move.w	#$180,(a2)+
	move.w	a5,(a2)+
	move.w	#$182,(a2)+
	move.w	a6,(a2)+

	move.w	a4,d0
	moveq	#3,d3
	bsr	multiplycolor
	move.w	d0,d4
	move.w	d0,d5
	move.w	a5,d0
	moveq	#15-3,d3
	bsr	multiplycolor
	add.w	d0,d4
	move.w	a6,d0
	moveq	#15-3,d3
	bsr	multiplycolor
	add.w	d0,d5

	move.w	#$188,(a2)+
	move.w	d4,(a2)+
	move.w	#$18a,(a2)+
	move.w	d5,(a2)+
	move.w	#$190,(a2)+
	move.w	d4,(a2)+
	move.w	#$192,(a2)+
	move.w	d5,(a2)+
	move.w	#$1a0,(a2)+
	move.w	d4,(a2)+
	move.w	#$1a2,(a2)+
	move.w	d5,(a2)+

	move.w	a4,d0
	moveq	#6,d3
	bsr	multiplycolor
	move.w	d0,d4
	move.w	d0,d5
	move.w	a5,d0
	moveq	#15-6,d3
	bsr	multiplycolor
	add.w	d0,d4
	move.w	a6,d0
	moveq	#15-6,d3
	bsr	multiplycolor
	add.w	d0,d5

	move.w	#$198,(a2)+
	move.w	d4,(a2)+
	move.w	#$19a,(a2)+
	move.w	d5,(a2)+
	move.w	#$1a8,(a2)+
	move.w	d4,(a2)+
	move.w	#$1aa,(a2)+
	move.w	d5,(a2)+
	move.w	#$1b0,(a2)+
	move.w	d4,(a2)+
	move.w	#$1b2,(a2)+
	move.w	d5,(a2)+

	move.w	a4,d0
	moveq	#10,d3
	bsr	multiplycolor
	move.w	d0,d4
	move.w	d0,d5
	move.w	a5,d0
	moveq	#15-10,d3
	bsr	multiplycolor
	add.w	d0,d4
	move.w	a6,d0
	moveq	#15-10,d3
	bsr	multiplycolor
	add.w	d0,d5

	move.w	#$1b8,(a2)+
	move.w	d4,(a2)+
	move.w	#$1ba,(a2)+
	move.w	d5,(a2)+

	add.l	#$10000000,a3
	dbra	d7,.coplp
	sub.l	#$01000000,a3
	move.l	a3,(a2)+
	move.w	#$180,(a2)+
	move.w	a4,(a2)+
	move.w	#bplcon0,(a2)+
	move.w	#0,(a2)+
	move.l	#$fffffffe,(a2)+

	move.w	cs_citycolor,d0
	lea	cs_cl_palette+2,a0
	moveq	#16-1,d7
.ccoll:	move.w	d0,(a0)
	addq	#4,a0
	dbra	d7,.ccoll

	move.w	cs_gradient,cs_cl_palette+66
	move.w	#512,cs_cosinus
	move.w	#140,cs_z
	move.l	#-$58000,cs_sinus_add_add
	rts

cityscape_go:
	move.l	#cityscape_main,part_main
	move.l	#cityscape_vbi,part_vbi
	rts

cityscape_main:
	; Clear destination bitplane
	; --------------------------
	lea	custom,a6
	move.l	#cs_planes,d0
	add.l	cs_planes_add,d0
	moveq	#0,d1
	waitb
	; Notice that the following blits use these values as well
	; --------------------------------------------------------
	move.l	#-1,bltafwm(a6)
	move.w	d1,bltcon1(a6)
	move.w	#DEST,bltcon0(a6)
	move.w	d1,bltdmod(a6)
	move.l	d0,bltdpth(a6)
	move.w	#(CS_BLITTER_CLEAR<<6)|(CS_PLANEWIDTH/2),bltsize(a6)

	; Clear part of the screen using the CPU
	; --------------------------------------
	move.l	d0,a0
	add.w	#CS_PLANESIZE,a0
	moveq	#0,d0
	moveq	#0,d1
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	moveq	#0,d5
	moveq	#0,d6
	sub.l	a1,a1
	sub.l	a2,a2
	sub.l	a3,a3
	sub.l	a4,a4
	move.l	#((CS_PLANEHEIGHT-CS_BLITTER_CLEAR)/16)-1,d7
.clr:	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	dbra	d7,.clr

	; Rotate one building first
	; -------------------------
	lea	sinus,a0
	move.w	cs_sinus,d0
	add.w	#256,d0
	and.w	#511,d0
	add.w	#1024,d0
	move.w	d0,d1
	add.w	#512,d1
	moveq	#4-1,d7
.build:	and.w	#2046,d0
	and.w	#2046,d1
	; Convert to rectangular coordinates
	; ----------------------------------
	move.w	(a0,d0.w),d2
	move.w	(a0,d1.w),d3
	muls	#CS_BUILDING_SIZE,d2
	muls	#CS_BUILDING_SIZE,d3
	asr.l	#8,d2
	swap	d3
	move.w	d3,-(sp)
	move.w	d2,-(sp)
	add.w	#512,d0
	add.w	#512,d1
	dbra	d7,.build

	; Prepare blitter for line drawing
	; --------------------------------
	lea	custom,a6
	waitb
	move.w	#$8000,bltadat(a6)
	move.w	#$ffff,bltbdat(a6)
	move.w	#CS_PLANEWIDTH,bltcmod(a6)
	move.w	#CS_PLANEWIDTH,bltdmod(a6)

	; Rotate building center coordinates
	; ----------------------------------
	lea	cs_coords,a0
	lea	sinus,a1
	lea	cs_mulu_planewidth,a2
	lea	cs_planes,a3
	add.l	cs_planes_add,a3
	move.w	(a1,d0.w),d2
	move.w	(a1,d1.w),d3
	move.w	(a0)+,d7
	subq	#1,d7
.loop:	; Angle and distance (polar)
	; --------------------------
	move.w	(a0)+,d2
	move.w	(a0)+,d3
	; Rotate (add to angle)
	; ---------------------
	move.w	d2,d4
	add.w	CS_SINUS(a2),d2
	add.w	CS_COSINUS(a2),d4
	and.w	#2046,d2
	and.w	#2046,d4
	; Convert to rectangular coordinates
	; ----------------------------------
	move.w	(a1,d2.w),d2
	move.w	(a1,d4.w),d4
	muls	d3,d2
	muls	d3,d4
	asr.l	#8,d2
	swap	d4
	; Get height (y)
	; --------------
	move.w	(a0)+,d3
	lsl.w	#7,d3
	; Translation: x=x+cx, z=z+cz
	; ---------------------------
	add.w	CS_X(a2),d2
	sub.w	CS_Z(a2),d4
	cmp.w	#CS_BUILDING_SIZE,d4	;-CS_BUILDING_SIZE*2,d4
	bge	.skip
	swap	d3
	move.w	d2,d3
	move.l	d3,a4
	move.w	d4,a5
	move.w	#$8000,CS_OLDX(a2)
	move.w	#-1,CS_CLIP(a2)
	; Plot building around the center coordinate
	; ------------------------------------------
	moveq	#4-1,d6
.bldng:	move.l	a4,d2
	move.l	d2,d3
	swap	d3
	move.l	a5,d4
	add.w	(sp)+,d2
	add.w	(sp)+,d4
	bmi	.zok
	move.w	#$8000,CS_OLDX(a2)
	bra	.next
.zok:	ext.l	d2
	ext.l	d3
	ext.l	d4
	; Projection: x'=x/z, y'=y/z
	; --------------------------
	divs	d4,d2
	divs	d4,d3
	; Centering
	; ---------
.projd:	add.w	#CS_PLANEWIDTH*8/2,d2
	add.w	#CS_PLANEHEIGHT*3/4,d3
	
	; Get line coordinates
	; --------------------
	move.w	CS_OLDX(a2),d0
	move.w	CS_OLDY(a2),d1
	move.w	d2,CS_OLDX(a2)
	move.w	d3,CS_OLDY(a2)
	cmp.w	#$8000,d0
	beq	.next

	; Clipping test
	; -------------
	lea	cs_clipstorage+16,a6
	movem.l	d6-d7,-(a6)
	movem.l	a2-a3,-(a6)
	moveq	#0,d7
	sub.l	a2,a2
	sub.l	a3,a3
.cloop:	moveq	#0,d4		; code1
	moveq	#0,d5		; code2
	tst.w	d0
	bpl.s	.x1lok
	or.w	#CLIP_LEFT_EDGE,d4
.x1lok:	cmp.w	#CS_PLANEWIDTH*8,d0
	blt.s	.x1rok
	or.w	#CLIP_RIGHT_EDGE,d4
.x1rok:	tst.w	d1
	bpl.s	.y1lok
	or.w	#CLIP_TOP_EDGE,d4
.y1lok:	cmp.w	#CS_PLANEHEIGHT,d1
	blt.s	.y1rok
	or.w	#CLIP_BOTTOM_EDGE,d4
.y1rok:	tst.w	d2
	bpl.s	.x2lok
	or.w	#CLIP_LEFT_EDGE,d5
.x2lok:	cmp.w	#CS_PLANEWIDTH*8,d2
	blt.s	.x2rok
	or.w	#CLIP_RIGHT_EDGE,d5
.x2rok:	tst.w	d3
	bpl.s	.y2lok
	or.w	#CLIP_TOP_EDGE,d5
.y2lok:	cmp.w	#CS_PLANEHEIGHT,d3
	blt.s	.y2rok
	or.w	#CLIP_BOTTOM_EDGE,d5
.y2rok:	move.w	d4,d6
	or.w	d5,d6
	beq.w	.line
	move.w	d4,d6
	and.w	d5,d6
	beq.s	.ok
	btst	#0,d4
	beq.s	.nl1
	moveq	#0,d0
.nl1:	btst	#1,d4
	beq.s	.nr1
	move.l	#CS_PLANEWIDTH*8-1,d0
.nr1:	btst	#2,d4
	beq.s	.nt1
	moveq	#0,d1
.nt1:	btst	#3,d4
	beq.s	.nb1
	move.l	#CS_PLANEHEIGHT-1,d1
.nb1:	btst	#0,d5
	beq.s	.nl2
	moveq	#0,d2
.nl2:	btst	#1,d5
	beq.s	.nr2
	move.l	#CS_PLANEWIDTH*8-1,d2
.nr2:	btst	#2,d5
	beq.s	.nt2
	moveq	#0,d3
.nt2:	btst	#3,d5
	beq.s	.nb2
	move.l	#CS_PLANEHEIGHT-1,d3
.nb2:	bra	.line
.ok:	cmp.l	#0,a2
	bne.s	.m2
	move.w	d3,d6		; m1=(y2-y1)/(x2-x1)
	sub.w	d1,d6
	ext.l	d6
	asl.l	#5,d6
	move.w	d2,d7
	sub.w	d0,d7
	beq.s	.m1
	add.l	#$3f,d6
	divs	d7,d6
	ext.l	d6
	move.l	d6,a2
.m1:	move.w	d2,d6		; m2=(x2-x1)/(y2-y1)
	sub.w	d0,d6
	ext.l	d6
	asl.l	#5,d6
	move.w	d3,d7
	sub.w	d1,d7
	beq.s	.m2
	add.l	#$3f,d6
	divs	d7,d6
	ext.l	d6
	move.l	d6,a3
.m2:	tst.w	d4
	bne.s	.clip
	exg	d0,d2
	exg	d1,d3
	exg	d4,d5
.clip:	btst	#0,d4
	beq.s	.nleft
	move.l	a2,d6
	muls	d6,d0
	asr.l	#6,d0
	sub.l	d0,d1
	moveq	#0,d0
	bra.w	.cloop
.nleft:	btst	#1,d4
	beq.s	.nrite
	sub.w	#CS_PLANEWIDTH*8-1,d0
	move.l	a2,d6
	muls	d6,d0
	asr.l	#6,d0
	sub.l	d0,d1
	move.l	#CS_PLANEWIDTH*8-1,d0
	bra.w	.cloop
.nrite:	btst	#2,d4
	beq.s	.ntop
	cmp.w	d0,d2
	beq.s	.y1
	move.l	a3,d6
	muls	d6,d1
	asr.l	#6,d1
	sub.l	d1,d0
.y1:	moveq	#0,d1
	bra.w	.cloop
.ntop:	btst	#3,d4
	beq.w	.cloop
	cmp.w	d0,d2
	beq.s	.y2
	sub.w	#CS_PLANEHEIGHT-1,d1
	move.l	a3,d6
	muls	d6,d1
	asr.l	#6,d1
	sub.l	d1,d0
.y2:	move.l	#CS_PLANEHEIGHT-1,d1
	bra.w	.cloop

.line:	lea	custom,a6
.wait:	btst	#14,dmaconr(a6)
	bne.s	.wait
	lea	cs_clipstorage,a6
	movem.l	(a6)+,a2-a3

	; If the top y of the previous line was 0 check out if this one's is too
	; ----------------------------------------------------------------------
	cmp.w	#-1,CS_CLIP(a2)
	beq	.chtop
	tst.w	d1
	beq.s	.d1tp1
	tst.w	d3
	bne.s	.chtop
.d3tp1:	move.w	d2,d4
	bra.s	.width
.d1tp1:	move.w	d0,d4
.width:	move.w	CS_CLIP(a2),d5
	cmp.w	d5,d4
	bcs.s	.d4ok
	exg	d4,d5
.d4ok:	moveq	#-1,d7
	move.w	d5,d6
	not.w	d6
	and.w	#15,d6
	lsl.w	d6,d7
	swap	d7
	move.w	d4,d6
	and.w	#15,d6
	lsr.w	d6,d7
	lsr.w	#3,d4
	lsr.w	#3,d5
	and.w	#$fffe,d4
	and.w	#$fffe,d5
	sub.w	d4,d5
	beq.s	.nloop
	lsr.w	d5
	or.w	d7,(a3,d4.w)
	addq	#2,d4
	subq	#2,d5
	bmi	.sloop
.filll:	move.w	#-1,(a3,d4.w)
	addq	#2,d4
	dbra	d5,.filll
.sloop:	swap	d7
	or.w	d7,(a3,d4.w)
	bra.s	.chtop
.nloop:	move.w	d7,d6
	swap	d7
	and.w	d7,d6
	or.w	d6,(a3,d4.w)
	
	; Check if the top y of this line is at 0
	; ---------------------------------------
.chtop:	move.w	#-1,CS_CLIP(a2)
	tst.w	d1
	beq.s	.d1tp2
	tst.w	d3
	bne.s	.swap
.d3tp2:	move.w	d2,CS_CLIP(a2)
	bra.s	.swap
.d1tp2:	move.w	d0,CS_CLIP(a2)
.swap:	movem.l	(a6)+,d6-d7
	lea	custom,a6

	; Make sure the line is drawn from top to bottom
	; ----------------------------------------------
	cmp.w	d1,d3
	bhi.s	.yok
	bne.s	.exg
	cmp.w	d0,d2
	bne	.yok
	bra	.next
.exg:	exg	d0,d2
	exg	d1,d3
.yok:	moveq	#0,d5
	move.w	d3,d4
	sub.w	d1,d4
	add.w	d4,d4
	sub.w	d0,d2
	bge.s	.x2gx1
	neg.w	d2
	addq	#2,d5
.x2gx1:	cmp.w	d4,d2
	blo.s	.allok
	subq	#1,d3
.allok:	sub.w	d1,d3
	add.w	d1,d1
	move.w	(a2,d1.w),d1
	ext.l	d1
	move.w	d0,d4
	asr.w	#3,d4
	add.w	d4,d1
	add.l	a3,d1

	move.w	d3,d4
	sub.w	d2,d4
	bge.s	.dygdx
	exg	d2,d3
	addq	#1,d5
.dygdx:	move.b	CS_OCTANTS(a2,d5.w),d5
	and.w	#$00ff,d5
	add.w	d2,d2
	and.w	#$000f,d0
	ror.w	#4,d0
	or.w	#SRCA|SRCC|DEST|NANBC|NABC|ANBC|ABC|ABNC,d0

.waitb:	btst	#14,dmaconr(a6)
	bne.s	.waitb
	move.w	d2,bltbmod(a6)
	sub.w	d3,d2
	bge.s	.signl
	or.w	#SIGNFLAG,d5
.signl:	move.w	d2,bltaptl(a6)
	sub.w	d3,d2
	move.w	d2,bltamod(a6)
	move.w	d0,bltcon0(a6)
	move.w	d5,bltcon1(a6)
	move.l	d1,bltcpth(a6)
	move.l	d1,bltdpth(a6)
	lsl.w	#6,d3
	addq	#2,d3
	move.w	d3,bltsize(a6)
.next:	dbra	d6,.bldng
	sub.w	#16,sp
.skip:	dbra	d7,.loop
	add.w	#16,sp

	; Prepare blitter for vertical filling
	; ------------------------------------
	lea	custom,a6
	move.l	#cs_planes+4,d0
	add.l	cs_planes_add,d0
	move.l	d0,d1
	add.l	#CS_PLANEWIDTH,d1
	waitb
	move.w	#SRCA|SRCB|DEST|ABC|ABNC|ANBC|ANBNC|NABC|NABNC,bltcon0(a6)
	move.l	#$00040004,bltamod(a6)
	move.l	#$00040004,bltcmod(a6)
	move.l	#-1,bltafwm(a6)
	move.w	#0,bltcon1(a6)
	move.l	d1,bltapth(a6)
	move.l	d0,bltbpth(a6)
	move.l	d1,bltdpth(a6)
	move.w	#((CS_PLANEHEIGHT-1)<<6)|((CS_PLANEWIDTH-4)/2),bltsize(a6)

	; Fill the first 4 bytes of each row using the CPU
	; ------------------------------------------------
	lea	cs_planes,a0
	add.l	cs_planes_add,a0
	moveq	#0,d0
	move.l	#CS_PLANEWIDTH,d6
	move.l	#CS_PLANEHEIGHT/8-1,d7
.vfill:	or.l	d0,(a0)
	move.l	(a0),d0
	add.w	d6,a0
	or.l	d0,(a0)
	move.l	(a0),d0
	add.w	d6,a0
	or.l	d0,(a0)
	move.l	(a0),d0
	add.w	d6,a0
	or.l	d0,(a0)
	move.l	(a0),d0
	add.w	d6,a0
	or.l	d0,(a0)
	move.l	(a0),d0
	add.w	d6,a0
	or.l	d0,(a0)
	move.l	(a0),d0
	add.w	d6,a0
	or.l	d0,(a0)
	move.l	(a0),d0
	add.w	d6,a0
	or.l	d0,(a0)
	move.l	(a0),d0
	add.w	d6,a0
	dbra	d7,.vfill
	
	waitb
	move.b	#1,render
	rts

cityscape_vbi:
	movem.l	d1/d7,-(sp)

	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#103,d0
	bhi.s	.noadd
	add.l	#$200,cs_sinus_add_add
	move.l	cs_sinus_add_add,d1
	add.l	d1,cs_sinus_add
	move.w	cs_sinus_add,d1
	beq.s	.noadd
	clr.w	cs_sinus_add
	add.w	d1,d1
	add.w	d1,cs_sinus
	add.w	d1,cs_cosinus
	and.w	#2046,cs_sinus
	and.w	#2046,cs_cosinus
.noadd:	cmp.w	#64,d0
	bcs.s	.moved
	cmp.w	#96,d0
	bcs.s	.out
.in:	sub.w	#2,cs_z
	bra.s	.moved
.out:	add.w	#1,cs_z
.moved:	tst.b	render
	beq.s	.vbiok

	move.l  #cs_cl,cop1lch+custom
	move.l	#cs_planes,d0
	move.l	d0,d1
	add.l	cs_planes_add,d0
	lea	cs_cl_bpl2pth,a0
	moveq	#4-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	sub.l	#CS_PLANESIZE,d0
	cmp.l	d1,d0
	bge	.plnok
	add.l	#5*CS_PLANESIZE,d0
.plnok:	dbra	d7,.setplanesloop

	add.l	#CS_PLANESIZE,cs_planes_add
	cmp.l	#5*CS_PLANESIZE,cs_planes_add
	bcs	.pladd
	clr.l	cs_planes_add
.pladd:	clr.b	render
	move.w	cs_citycolor,ne_cl_palette+2
.vbiok:	movem.l	(sp)+,d1/d7
	rts

multiplycolor:
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	lsl.w	#4,d3
	add.w	d3,a0
	move.b	(a0,d0.w),d0
	move.b	(a0,d1.w),d1
	move.b	(a0,d2.w),d2
	sub.w	d3,a0
	lsl.w	#8,d0
	lsl.b	#4,d1
	or.b	d1,d0
	or.b	d2,d0
	rts

discopallo:
	; Clear memory
	; ------------
	lea	dp_cl,a0
	move.l	#dp_requirements_chipmem,d7
	bsr	clearmemory
	lea	dp_planes_add,a0
	move.l	#dp_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	dp_ct,a0
	lea	dp_cl,a1
	move.w	#(dp_ct_data-dp_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst
	move.l	#$fffffffe,(a1)+
	
	; Screen setup
	; ------------
	move.l	#dp_planes,d0
	lea	dp_cl_bpl1pth,a0
	moveq	#DP_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#DP_PLANEWIDTH,d0
	dbra	d7,.setplanesloop

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	dp_mulu_planewidth,a0
	move.l	#DP_PLANEHEIGHT-1,d7
.mulu:	move.w	d0,-(a0)
	add.w	#DP_PLANEWIDTH,d0
	dbra	d7,.mulu

	moveq	#0,d0
	lea	dp_mulu_256,a0
.mulu2:	moveq	#1,d1
.mulu3:	move.w	d0,d2
	mulu	d1,d2
	lsr.w	#8,d2
	move.b	d2,(a0)+
	addq	#1,d1
	cmp.w	#256,d1
	ble.s	.mulu3
	addq	#1,d0
	cmp.w	#128,d0
	bcs.s	.mulu2

	lea	dp_mulu_256-128*256,a0
.mulu4:	moveq	#1,d1
.mulu5:	move.w	d0,d2
	mulu	d1,d2
	lsr.w	#8,d2
	move.b	d2,(a0)+
	addq	#1,d1
	cmp.w	#256,d1
	ble.s	.mulu5
	addq	#1,d0
	cmp.w	#256,d0
	bcs.s	.mulu4

	; Create discopallo ball width table (x=sqrt(r^2-y^2))
	; ----------------------------------------------------
	lea	dp_table,a0
	move.l	#-256,d7
.dpbw:	move.l	d7,d0
	bpl.s	.dpbp
	neg.l	d0
.dpbp:	mulu	d0,d0
	move.l	#256*256-1,d1
	sub.w	d0,d1
	; Calculate square root
	; ---------------------	
	moveq	#-1,d2
	clr.w	d2
	cmp.l	d2,d1
	bls.s	.sqrt0
	move.l	#$00010000,d2
	bra.s	.sqrt3
.sqrt0:	moveq	#31,d0
.sqrt1:	bclr	d0,d2
	lsr.l	d2
	cmp.l	d2,d1
	bls.s	.sqrt2
	sub.l	d2,d1
	bset	d0,d2
.sqrt2:	subq	#2,d0
	bcc.s	.sqrt1
	lsr.l	d2
.sqrt3:	cmp.w	#$100,d2
	bcs.s	.dpbok
	subq	#1,d2
.dpbok:	move.b	d2,(a0)+
	addq	#1,d7
	cmp.w	#256,d7
	bne.s	.dpbw

	; Copy the ordered table to the discopallo table
	; ----------------------------------------------
	lea	table_order,a0
	lea	dp_xoffsets,a1
	move.l	#16-1,d7
.dptf:	move.l	(a0)+,(a1)+
	move.l	(a0)+,60(a1)
	move.l	(a0)+,124(a1)
	move.l	(a0)+,188(a1)
	dbra	d7,.dptf

	; Remove pixels from the discopallo table
	; ---------------------------------------
	lea	dp_xoffsets,a0
	move.l	#255-1,d7
.dpt:	move.b	(a0)+,d0
	move.l	a0,a1
	move.l	d7,d6
	cmp.b	#128,d0
	bcs.s	.dptl
.dptr:
.dptrl:	move.b	(a1)+,d1
	cmp.b	d0,d1
	bcs.s	.dptrn
	subq	#1,d1
	move.b	d1,-1(a1)
.dptrn:	dbra	d6,.dptrl
	bra.s	.dptnx
.dptl:
.dptll:	move.b	(a1)+,d1
	cmp.b	d0,d1
	bhi.s	.dptln
	addq	#1,d1
	move.b	d1,-1(a1)
.dptln:	dbra	d6,.dptll
.dptnx:	dbra	d7,.dpt

	; Create discopallo Y offsets
	; ---------------------------
	moveq	#-2,d0
	moveq	#-1,d1
	lea	sinus,a0
	lea	dp_yoffsets,a1
	moveq	#32-1,d7
.dpyol:	addq	#2,d0
	cmp.w	#512,d0
	bne.s	.dpyon
	move.b	#128,(a1)+
	bra.s	.dpyol
.dpyon:	move.w	(a0,d0.w),d2
	lsr.w	#8,d2
	lsr.w	#3,d2
	cmp.w	d1,d2
	beq	.dpyol
	move.w	d2,d1
	move.w	d0,d3
	lsr.w	#2,d3
	addq	#1,d3
	move.b	d3,(a1)+
	dbra	d7,.dpyol
	move.b	#$ff,(a1)+
	clr.b	(a1)+
	
	; Create jelly table
	; ------------------
	lea	dp_jelly,a0
	move.w	#64-16,d6
.jell1:	moveq	#0,d7
.jell2:	move.w	d7,d0
	mulu	d6,d0
	lsr.w	#6,d0
	cmp.w	#256,d0
	bcs.s	.jelok
	move.w	#255,d0
.jelok:	move.b	d0,(a0)+
	addq	#1,d7
	cmp.w	#256,d7
	bcs.s	.jell2
	addq	#1,d6
	cmp.w	#64+16,d6
	bcs.s	.jell1

	; Decrunch data
	; -------------
	lea	dp_texture,a0
	lea	dp_texture_stc,a1
	bsr	decrunch

	; Add some of the texture below the texture (bubble gum fix...)
	; -------------------------------------------------------------
	lea	dp_texture,a0
	lea	dp_texture_hotfix,a1
	move.w	#128*2/4-1,d7
.hotfx:	move.l	(a0)+,(a1)+
	dbra	d7,.hotfx

	; Create discopallo
	; -----------------
	lea	sinus,a0
	lea	dp_planes+DP_PLANES*DP_PLANESIZE-DP_PLANES*DP_PLANEWIDTH,a1
	lea	DP_PLANEWIDTH(a1),a2
	lea	DP_PLANEWIDTH(a2),a3
	lea	DP_PLANEWIDTH(a3),a4
	lea	DP_PLANEWIDTH+16(a4),a5
	move.l	#$80,d0
	moveq	#128-1,d7
.dp1:	move.w	(a0)+,d1
	addq	#2,a0
	lsr.w	#8,d1
	lsr.w	#4,d1
	bcc	.dp1n1
	or.b	d0,(a1)
.dp1n1:	lsr.w	d1
	bcc	.dp1n2
	or.b	d0,(a2)
.dp1n2:	lsr.w	d1
	bcc	.dp1n3
	or.b	d0,(a3)
.dp1n3:	lsr.w	d1
	bcc	.dp1n4
	or.b	d0,(a4)
.dp1n4:	ror.b	d0
	bpl.s	.dp1ok
	addq	#1,a1
	addq	#1,a2
	addq	#1,a3
	addq	#1,a4
.dp1ok:	dbra	d7,.dp1

	moveq	#128-1,d7
.dp2:	move.w	#$7fff,d1
	sub.w	(a0)+,d1
	addq	#2,a0
	lsr.w	#8,d1
	lsr.w	#4,d1
	bcc	.dp2n1
	or.b	d0,(a1)
.dp2n1:	lsr.w	d1
	bcc	.dp2n2
	or.b	d0,(a2)
.dp2n2:	lsr.w	d1
	bcc	.dp2n3
	or.b	d0,(a3)
.dp2n3:	lsr.w	d1
	bcc	.dp2n4
	or.b	d0,(a4)
.dp2n4:	ror.b	d0
	bpl.s	.dp2ok
	addq	#1,a1
	addq	#1,a2
	addq	#1,a3
	addq	#1,a4
	move.b	#-1,(a5)+
.dp2ok:	dbra	d7,.dp2
	
	lea	dp_xoffsets,a1
	lea	dp_planes+DP_PLANES*DP_PLANESIZE-2*DP_PLANES*DP_PLANEWIDTH,a3
	lea	DP_PLANES*DP_PLANEWIDTH(a3),a2
	lea	custom,a6
	moveq	#0,d7
dp_lp:	; Copy row below as is
	; --------------------
	moveq	#0,d0
	waitb
	move.w	#SRCA|DEST|ABC|ABNC|ANBC|ANBNC,bltcon0(a6)
	move.w	d0,bltcon1(a6)
	move.l	#$fffffffe,bltafwm(a6)
	move.l	d0,bltamod(a6)
	move.l	a2,bltapth(a6)
	move.l	a3,bltdpth(a6)
	move.w	#(DP_PLANES<<6)|(32/2),bltsize(a6)

	; Get destination pixel to remove
	; -------------------------------
	move.b	(a1,d7.w),d0

	; Check whether the pixel is on the left or on the right half
	; -----------------------------------------------------------
	cmp.b	#128,d0
	bcs.s	dp_ol
	; Blit width in words
	; -------------------
	move.w	#255,d1
	sub.b	d0,d1
	lsr.w	#4,d1
	addq	#1,d1
	; Modulo in bytes
	; ---------------
	move.w	#DP_PLANEWIDTH,d2
	sub.w	d1,d2
	sub.w	d1,d2

	; How many pixels of the original are preserved
	; ---------------------------------------------
	and.w	#15,d0
	
	; Calculate blitter mask
	; --------------------
	move.l	#$fffeffff,d3
	lsr.w	d0,d3

	lea	DP_PLANES*DP_PLANEWIDTH-2(a3),a4
	or.w	#(DP_PLANES<<6),d1
	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	#(1<<BSHIFTSHIFT)|BLITREVERSE,bltcon1(a6)
	move.w	#-1,bltadat(a6)
	move.l	d3,bltafwm(a6)
	move.w	d2,bltbmod(a6)
	move.w	d2,bltcmod(a6)
	move.w	d2,bltdmod(a6)
	move.l	a4,bltbpth(a6)
	move.l	a4,bltcpth(a6)
	move.l	a4,bltdpth(a6)
	move.w	d1,bltsize(a6)
	bra.s	dp_nx

dp_ol:	; Blit width in words
	; -------------------
	move.w	d0,d1
	lsr.w	#4,d1
	addq	#1,d1
	; Modulo in bytes
	; ---------------
	move.w	#DP_PLANEWIDTH,d2
	sub.w	d1,d2
	sub.w	d1,d2

	; How many pixels of the original are preserved
	; ---------------------------------------------
	and.w	#15,d0
	sub.w	#15,d0
	neg.w	d0

	; Calculate blitter mask
	; ----------------------
	move.l	#$7fffffff,d3
	lsl.w	d0,d3

	or.w	#(DP_PLANES<<6),d1
	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	#(1<<BSHIFTSHIFT),bltcon1(a6)
	move.w	#-1,bltadat(a6)
	move.l	d3,bltafwm(a6)
	move.w	d2,bltbmod(a6)
	move.w	d2,bltcmod(a6)
	move.w	d2,bltdmod(a6)
	move.l	a3,bltbpth(a6)
	move.l	a3,bltcpth(a6)
	move.l	a3,bltdpth(a6)
	move.w	d1,bltsize(a6)

dp_nx:	lea	-DP_PLANES*DP_PLANEWIDTH(a2),a2
	lea	-DP_PLANES*DP_PLANEWIDTH(a3),a3
	addq	#1,d7
	cmp.w	#255,d7
	bne	dp_lp

	move.w	#60*2+64,dp_sizepointer
	move.w	#(DP_PLANES-1)*DP_PLANEWIDTH,dp_modulo
	move.l	#$fffffffe,dp_cl_data
	move.w	#$58,dp_ddfstrt
	move.w	#$d0,dp_ddfstop
	waitb
	rts

discopallo_go:
	move.l  #dp_cl,cop1lch+custom
	move.l	#discopallo_main,part_main
	move.l	#discopallo_vbi,part_vbi
	rts

discopallo_main:
	; Update copperlist
	; -----------------
	lea	dp_table,a0
	lea	dp_cl_data,a1
	add.l	dp_copper_add,a1
	lea	dp_jelly,a2
	lea	dp_mulu_256,a3
	lea	dp_texture,a4
	lea	dp_yoffsets,a5
	move.w	dp_texturey,d0
	lsl.w	#7,d0
	add.w	dp_texturex,d0
	add.w	d0,d0
	add.w	d0,a4
	move.w	dp_jellyptr,d6
	add.w	d6,a2
	sub.w	#256*32,d6
	neg.w	d6
	lsr.w	#8,d6
	moveq	#0,d7
	move.w	dp_ysize,d7
	add.w	d6,d7
	; Copper Y wait
	; -------------
	move.l	d7,d0
	lsr.w	d0
	neg.w	d0
	add.w	#$a8,d0
	lsl.w	#8,d0
	or.w	#1,d0
	; Y table pointer
	; ---------------
	moveq	#0,d1
	; Y table pointer delta
	; ---------------------
	move.l	#$20000,d2
	divu	d7,d2
	ext.l	d2

	; Previous width
	; --------------	
	moveq	#0,d3

	; Multiplier table pointer
	; ------------------------
	move.w	d7,d6
	lsl.w	#8,d6

	; Loop counter (in stack!)
	; ------------------------
	move.w	d7,-(sp)

	; Y offset to wait and first Y position
	; -------------------------------------
	move.l	d0,a6
	move.l	d0,d7
	
	; Wait for the first Y position, switch bitplanes on
	; --------------------------------------------------
	move.w	d0,(a1)+
	move.w	#$fffe,(a1)+
	move.w	#bplcon0,(a1)+
	move.w	dp_cl_bplcon0+2,(a1)+
.yloop:	add.l	d2,d1

	; Get the width of the next row and set modulos accordingly
	; ---------------------------------------------------------
	move.l	d1,d4
	lsr.l	#8,d4
	and.w	#$fffe,d4
	move.w	(a0,d4.w),d4
	lsr.w	#8,d4
	add.w	d6,d4
	moveq	#0,d5
	move.b	(a3,d4.w),d5
	move.b	(a2,d5.w),d5
	move.w	d5,d4
	sub.w	d3,d5
	move.w	d4,d3
	subq	#1,d5
	bmi.s	.neg
	addq	#1,d5
	add.w	d5,d5
	neg.w	d5
	move.w	(a0,d5.w),d5
	bra.s	.done
.neg:	subq	#1,d5
	add.w	d5,d5
	move.w	(a0,d5.w),d5
	neg.w	d5	
.done:	move.w	d5,d4
	; Multiply by 5 (number of bitplanes)
	; -----------------------------------
	add.w	d5,d5
	add.w	d5,d5
	add.w	d4,d5
	add.w	-DP_PLANEHEIGHT*2-2(a0),d5
	move.w	#bpl1mod,(a1)+
	move.w	d5,(a1)+
	move.w	#bpl2mod,(a1)+
	move.w	d5,(a1)+

	; Check whether some texture data should be written in the colour regs
	; --------------------------------------------------------------------
	cmp.l	a6,d0
	bcs	.nopal
	; Get next Y wait position and scale it
	; -------------------------------------
	moveq	#0,d4
	moveq	#0,d5
	move.b	(a5)+,d4
	bne.s	.ywtok
	move.l	#$400001,a6
	bra.s	.wrtex
.ywtok:	add.w	d6,d4
	move.b	(a3,d4.w),d5
	lsl.w	#8,d5
	add.l	d7,d5
	move.l	d5,a6

	; Write new texture data
	; ----------------------
.wrtex:	move.w	#$182,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$184,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$186,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$188,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$18a,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$18c,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$18e,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$190,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$192,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$194,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$196,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$198,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$19a,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$19c,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$19e,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1a0,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1a2,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1a4,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1a6,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1a8,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1aa,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1ac,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1ae,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1b0,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1b2,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1b4,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1b6,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1b8,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1ba,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1bc,(a1)+
	move.w	(a4)+,(a1)+
	move.w	#$1be,(a1)+
	move.w	(a4)+,(a1)+
	lea	256-62(a4),a4

.nopal:	; Move to next Y position, check for position $100
	; ------------------------------------------------
	add.l	#$100,d0
	cmp.w	#1,d0
	bne.s	.next
	move.l	#$ffc1fffe,(a1)+
.next:	move.w	d0,(a1)+
	move.w	#$fffe,(a1)+
	sub.w	#1,(sp)
	bne.w	.yloop
	move.w	#bplcon0,(a1)+
	clr.w	(a1)+
	move.w	#$ffff,(a1)+
	move.w	#$fffe,(a1)+

	; Restore stack
	; -------------
	addq	#2,sp

	move.b	#1,render
	rts

discopallo_vbi:
	movem.l	d1-d4/d7,-(sp)

	move.w	dp_ddfstrt,dp_cl_ddfstrt+2
	move.w	dp_ddfstop,dp_cl_ddfstop+2
	move.w	dp_bplcon1,dp_cl_bplcon1+2

	; Screen setup
	; ------------
	move.l	#dp_planes,d0
	add.l	dp_planes_add,d0
	lea	dp_cl_bpl1pth,a0
	moveq	#DP_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#DP_PLANEWIDTH,d0
	dbra	d7,.setplanesloop

	; Copperlist setup
	; ----------------
	move.l	#dp_cl_data,d0
	add.l	dp_copper_add,d0
	move.w	d0,dp_cl_cop2lcl
	swap	d0
	move.w	d0,dp_cl_cop2lch

	; Update ball X position
	; ----------------------
	lea	sinus,a0
	move.l	#(DP_PLANES-1)*DP_PLANEWIDTH,d3
	moveq	#0,d4
	move.w	dp_xsinus,d0
	move.w	(a0,d0.w),d0
	add.w	#$8000,d0
	lsr.w	#8,d0
	move.w	d0,d1
	lsr.w	d1
	and.w	#$fff8,d1
	move.w	d1,d2
	add.w	#$58-2*DP_PLANEWIDTH,d1
	add.w	#$50+2*DP_PLANEWIDTH,d2
	; Does the ball go outside the screen from the left?
	; --------------------------------------------------
	cmp.w	#$18,d1
	bcc.s	.strok
	sub.w	#$18,d1
	neg.w	d1
	lsr.w	#2,d1
	add.w	d1,d3
	move.w	d1,d4
	move.w	#$18,d1
.strok:	move.w	d1,dp_ddfstrt
	; Does the ball go outside the screen from the right?
	; ---------------------------------------------------
	cmp.w	#$d8,d2
	bls.s	.stpok
	sub.w	#$d8,d2
	lsr.w	#2,d2
	add.w	d2,d3
	move.w	#$d8,d2
.stpok:	move.w	d2,dp_ddfstop
	and.w	#15,d0
	move.w	d0,d1
	lsl.w	#4,d1
	or.w	d1,d0
	move.w	d0,dp_bplcon1
	move.w	d3,dp_modulo
	move.l	d4,dp_planes_add

	; Update ball size, texture location, jelly
	; -----------------------------------------
	lea	sinus,a0
	move.w	dp_sizepointer,d0
	move.w	(a0,d0.w),d0
	lsr.w	#7,d0
	sub.w	#50,d0
	move.w	d0,dp_ysize
	move.w	dp_texxptr,d0
	move.w	(a0,d0.w),d0
	add.w	#$8000,d0
	lsr.w	#8,d0
	lsr.w	d0
	move.w	d0,d1
	add.w	d0,d0
	add.w	d1,d0
	lsr.w	#2,d0
	move.w	d0,dp_texturex
	move.w	dp_texyptr,d0
	move.w	(a0,d0.w),d0
	add.w	#$8000,d0
	lsr.w	#8,d0
	lsr.w	d0
	move.w	d0,d1
	add.w	d0,d0
	add.w	d1,d0
	lsr.w	#2,d0
	move.w	d0,dp_texturey
	move.w	dp_jellysinus,d0
	move.w	(a0,d0.w),d0
	add.w	#$8000,d0
	rol.w	#5,d0
	and.w	#31,d0
	lsl.w	#8,d0
	move.w	d0,dp_jellyptr

	; Synchronize ball size to the beat
	; ---------------------------------
	add.w	#32,dp_sizepointer
	move.l	sc_position,d0
	addq	#3,d0
	and.w	#3,d0
	bne.s	.nsync
	tst.b	dp_synced
	bne.s	.nores
	move.b	#1,dp_synced
	move.w	#60*2+64,dp_sizepointer
	bra.s	.nores
.nsync:	clr.b	dp_synced
.nores:	add.w	#10,dp_texxptr
	add.w	#8,dp_texyptr
	move.l	sc_position,d0
	and.w	#127,d0
	cmp.w	#65,d0
	bcs.s	.nxsin
	add.w	#42,dp_xsinus
.nxsin:	add.w	#132,dp_jellysinus
	cmp.w	#1024-60*2,dp_sizepointer
	bcs.s	.sizo
	sub.w	#1024-60*2*2,dp_sizepointer
.sizo:	and.w	#2046,dp_texxptr
	and.w	#2046,dp_texyptr
	and.w	#2046,dp_xsinus
	and.w	#2046,dp_jellysinus

	clr.b	render
	eor.l	#(4+256*6+34*62+2+2+2)*2,dp_copper_add
	movem.l	(sp)+,d1-d4/d7
	rts

	; Fancy writer
	; ------------
fancywriter:
	; Clear memory
	; ------------
	lea	fw_cl,a0
	move.l	#fw_requirements_chipmem,d7
	bsr	clearmemory
	lea	fw_planes_add,a0
	move.l	#fw_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	fw_ct,a0
	lea	fw_cl,a1
	move.w	#(fw_ct_data-fw_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Screen setup
	; ------------
	move.l	#fw_planes,d0
	move.w	d0,fw_cl_bpl1ptl
	move.w	d0,fw_cl_bpl2ptl
	swap	d0
	move.w	d0,fw_cl_bpl1pth
	move.w	d0,fw_cl_bpl2pth
	swap	d0
	add.l	#2*FW_PLANESIZE,d0
	move.w	d0,fw_cl_bpl3ptl
	swap	d0
	move.w	d0,fw_cl_bpl3pth

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	fw_mulu_planewidth,a0
	move.l	#FW_PLANEHEIGHT-1,d7
.mulu1:	move.w	d0,(a0)+
	add.w	#FW_PLANEWIDTH,d0
	dbra	d7,.mulu1

	; Create scaling table
	; --------------------
	moveq	#0,d0
	lea	fw_mulu_256,a0
.mulu2:	moveq	#0,d1
.mulu3:	move.w	d0,d2
	move.w	d1,d3
	ext.w	d3
	muls	d3,d2
	asr.w	#8,d2
	move.b	d2,(a0)+
	addq	#1,d1
	cmp.w	#256,d1
	bcs.s	.mulu3
	addq	#1,d0
	cmp.w	#128,d0
	bcs.s	.mulu2

	move.w	#128,d0
	lea	fw_mulu_256-128*256,a0
.mulu4:	moveq	#0,d1
.mulu5:	move.w	d0,d2
	move.w	d1,d3
	ext.w	d3
	muls	d3,d2
	asr.w	#8,d2
	move.b	d2,(a0)+
	addq	#1,d1
	cmp.w	#256,d1
	bcs.s	.mulu5
	addq	#1,d0
	cmp.w	#256,d0
	bcs.s	.mulu4

	; Width of the space character
	; ----------------------------
	move.b	#3,fw_font_widths

	; Decrunch bitmap
	; ---------------
	lea	fw_symbol,a0
	lea	fw_symbol_stc,a1
	bsr	decrunch

	; Decrunch font
	; -------------
	lea	fw_font,a0
	lea	fw_font_stc,a1
	bsr	decrunch

	; Copy Jorma
	; ----------
	lea	fw_symbol,a0
	lea	fw_planes+2*FW_PLANESIZE+16*FW_PLANEWIDTH+(FW_PLANEWIDTH-32)/2,a1
	lea	FW_PLANESIZE(a1),a2
	move.w	#224-1,d7
.jorma:	move.l	(a0),(a1)+
	move.l	(a0)+,(a2)+
	move.l	(a0),(a1)+
	move.l	(a0)+,(a2)+
	move.l	(a0),(a1)+
	move.l	(a0)+,(a2)+
	move.l	(a0),(a1)+
	move.l	(a0)+,(a2)+
	move.l	(a0),(a1)+
	move.l	(a0)+,(a2)+
	move.l	(a0),(a1)+
	move.l	(a0)+,(a2)+
	move.l	(a0),(a1)+
	move.l	(a0)+,(a2)+
	move.l	(a0),(a1)+
	move.l	(a0)+,(a2)+
	lea	FW_PLANEWIDTH-32(a1),a1
	lea	FW_PLANEWIDTH-32(a2),a2
	dbra	d7,.jorma

	; Set initial particle speeds
	; ---------------------------
	move.l	#(FW_PLANEWIDTH*8/2)<<16,d0
	move.l	#(FW_PLANEHEIGHT-FW_NUMBER_OF_PARTICLES)<<16,d1
	moveq	#0,d2
	move.l	#$10000,d3
	lea	fw_part_speeds,a0
	lea	fw_part_coords,a1
	move.w	#FW_NUMBER_OF_PARTICLES/2-1,d7
.set:	move.l	d2,(a0)+
	move.l	d3,(a0)+
	move.l	d0,(a1)+
	move.l	d1,(a1)+
	move.l	d2,(a0)+
	move.l	d3,(a0)+
	move.l	d0,(a1)+
	move.l	d1,(a1)+
	add.l	#2<<16,d1
	dbra	d7,.set

	move.w	#2,fw_asl
	move.w	#254*256,fw_mult
	rts

fancywriter_go:
	move.l  #fw_cl,cop1lch+custom
	move.l	#fancywriter_main,part_main
	move.l	#fancywriter_vbi,part_vbi
	rts

fancywriter_main:
	tst.b	fw_written
	bne	fw_blt
	move.b	#1,fw_written

	; Clear writer bitplane
	; ---------------------
	lea	custom,a6
	move.l	#fw_plane,d0
	moveq	#0,d1
	waitb
	move.l	#-1,bltafwm(a6)
	move.w	d1,bltcon1(a6)
	move.w	#DEST,bltcon0(a6)
	move.w	d1,bltdmod(a6)
	move.l	d0,bltdpth(a6)
	move.w	#(FW_BLITTER_CLEAR<<6)|(FW_PLANEWIDTH/2),bltsize(a6)

	; Clear part of the bitplane using the CPU
	; ----------------------------------------
	move.l	d0,a0
	add.w	#FW_PLANESIZE,a0
	moveq	#0,d0
	moveq	#0,d1
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	moveq	#0,d5
	moveq	#0,d6
	sub.l	a1,a1
	sub.l	a2,a2
	sub.l	a3,a3
	sub.l	a4,a4
	move.l	#((FW_PLANEHEIGHT-FW_BLITTER_CLEAR)/16)-1,d7
.clr:	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	dbra	d7,.clr

	moveq	#0,d0
	moveq	#0,d2
	lea	fw_text,a0
	lea	fw_font,a1
	lea	fw_font_widths,a2
	lea	fw_font_left,a3
	lea	fw_row_in_use,a4
	clr.b	(a4)
	lea	fw_plane+FW_STARTING_ROW*FW_PLANEWIDTH,a5
	waitb
.loop:	; 0? Text rendered
	; ----------------
	move.b	(a0)+,d2
	beq	fw_blt
	; 10? Line feed
	; -------------
	cmp.b	#10,d2
	bne.s	.noret
	; Reset X position, move on to the next line
	; ------------------------------------------
	moveq	#0,d0
	lea	16*FW_PLANEWIDTH(a5),a5
	; Check if anything was written on this row
	; -----------------------------------------
	tst.b	(a4)
	beq.s	.nouse
	; Mark the following 16 rows as used
	; ----------------------------------
	move.l	#$01010101,d3
	move.l	d3,(a4)+
	move.l	d3,(a4)+
	move.l	d3,(a4)+
	move.l	d3,(a4)+
	clr.b	(a4)
	bra.s	.loop
	; Mark the following 16 rows as unused
	; ------------------------------------
.nouse:	clr.l	(a4)+
	clr.l	(a4)+
	clr.l	(a4)+
	clr.l	(a4)+
	clr.b	(a4)
	bra.s	.loop
.noret:	; This row is used
	; ----------------
	move.b	#1,(a4)
	; Substract space (the first character); don't render spaces
	; ----------------------------------------------------------
	sub.b	#32,d2
	beq.s	.next
	; Substract left substraction
	; ---------------------------
	moveq	#0,d3
	move.b	(a3,d2.w),d3
	sub.w	d3,d0
	; Get font
	; --------
	move.w	d2,d3
	lsl.w	#6,d3
	; Calculate offset, shift and mask
	; --------------------------------
	move.w	d0,d1
	move.w	d0,d4
	lsr.w	#3,d1
	and.w	#$fffe,d1
	and.w	#15,d4
	move.l	#-1,d6
	lsr.l	d4,d6
	not.l	d6
	sub.l	a6,a6
.font:	move.l	(a1,d3.w),d5
	lsr.l	d4,d5
	or.l	d5,(a5,d1.w)
	move.l	(a1,d3.w),d5
	ror.l	d4,d5
	and.l	d6,d5
	or.l	d5,4(a5,d1.w)
	addq	#4,d3
	add.w	#FW_PLANEWIDTH,d1
	; Next row
	; --------
	addq	#1,a6
	cmp.w	#16,a6
	bcs.s	.font
.next:	; Add font width minus right substraction
	; ---------------------------------------
	moveq	#1,d1
	add.b	(a2,d2.w),d1
	sub.b	FW_NUMBER_OF_FONTS(a3,d2.w),d1
	add.w	d1,d0
	bra	.loop

fw_blt:	; Clear destination bitplane
	; --------------------------
	lea	custom,a6
	move.l	#fw_planes,d0
	add.l	fw_planes_add,d0
	moveq	#0,d1
	waitb
	move.w	d1,bltcon1(a6)
	move.w	#DEST,bltcon0(a6)
	move.l	#-1,bltafwm(a6)
	move.w	d1,bltdmod(a6)
	move.l	d0,bltdpth(a6)
	move.w	#(FW_BLITTER_CLEAR<<6)|(FW_PLANEWIDTH/2),bltsize(a6)

	; Clear part of the bitplane using the CPU
	; ----------------------------------------
	move.l	d0,a0
	add.w	#FW_PLANESIZE,a0
	moveq	#0,d0
	moveq	#0,d1
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	moveq	#0,d5
	moveq	#0,d6
	sub.l	a1,a1
	sub.l	a2,a2
	sub.l	a3,a3
	sub.l	a4,a4
	move.l	#((FW_PLANEHEIGHT-FW_BLITTER_CLEAR)/16)-1,d7
.clr:	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	movem.l	d0-d6/a1-a4,-(a0)
	dbra	d7,.clr

	lea	fw_plane,a0
	lea	fw_planes,a1
	add.l	fw_planes_add,a1
	lea	sinus,a2
	lea	fw_mulu_planewidth,a3
	lea	fw_mulu_256,a4
	lea	fw_row_in_use,a5
	lea	FW_STARTING_ROW*FW_PLANEWIDTH(a0),a0
	add.w	fw_mult,a4
	move.w	fw_sinus,d0
	swap	d0
	move.w	fw_sinus,d0
	add.w	#512,d0
	moveq	#0,d1
	moveq	#0,d2
	move.w	fw_asl,d6
	moveq	#FW_STARTING_ROW,d7
fw_blp:	and.l	#$07ff07ff,d0
	tst.b	(a5)+
	beq	fw_nxt
	; Y add
	; -----
	moveq	#0,d1
	move.b	(a2,d0.w),d1
	move.b	(a4,d1.w),d1
	ext.w	d1
	asl.w	d6,d1
	add.w	d7,d1
	; Don't draw if the line goes outside the screen
	; ----------------------------------------------
	bmi	fw_nxt
	cmp.w	#FW_PLANEHEIGHT,d1
	bge	fw_nxt
	add.w	d1,d1
	move.w	(a3,d1.w),d1
	move.l	a0,d4
	move.l	a1,d5
	add.l	d1,d5
	; X add
	; -----
	moveq	#0,d1
	swap	d0
	move.b	(a2,d0.w),d1
	swap	d0
	move.b	(a4,d1.w),d1
	ext.w	d1
	asl.w	d6,d1
	bmi.s	fw_xng
	; X positive: Width = PLANEWIDTH/2 - X/16, Modulo = X/8
	; -----------------------------------------------------
	move.w	d1,d3
	lsr.w	#4,d3
	move.w	d3,d2
	neg.w	d3
	add.w	#FW_PLANEWIDTH/2,d3
	; Don't draw if the line goes outside the screen
	; ----------------------------------------------
	bmi	fw_nxt
	beq	fw_nxt
	or.w	#(1<<6),d3
	add.w	d2,d2
	and.w	#15,d1
	ror.w	#4,d1
	or.w	#SRCA|DEST|ABC|ABNC|ANBC|ANBNC,d1
	add.l	d2,d5
	waitb
	move.w	#0,bltcon1(a6)
	bra.s	fw_dbl
	; X negative: Width = PLANEWIDTH/2 + X/16, Modulo = X/8
	; -----------------------------------------------------
fw_xng:	neg.w	d1
	move.w	d1,d3
	lsr.w	#4,d3
	move.w	d3,d2
	sub.w	#FW_PLANEWIDTH/2,d3
	; Don't draw if the line goes outside the screen
	; ----------------------------------------------
	bpl	fw_nxt
	neg.w	d3
	or.w	#(1<<6),d3
	add.w	d2,d2
	and.w	#15,d1
	ror.w	#4,d1
	or.w	#SRCA|DEST|ABC|ABNC|ANBC|ANBNC,d1
	add.l	#FW_PLANEWIDTH-2,d4
	add.l	#FW_PLANEWIDTH-2,d5
	sub.l	d2,d5
	waitb
	move.w	#BLITREVERSE,bltcon1(a6)
fw_dbl:	move.w	d1,bltcon0(a6)
	move.l	d4,bltapth(a6)
	move.l	d5,bltdpth(a6)
	move.w	d3,bltsize(a6)
fw_nxt:	add.l	#$00100010,d0
	lea	FW_PLANEWIDTH(a0),a0
	addq	#1,d7
	cmp.w	#FW_ENDING_ROW,d7
	bcs.w	fw_blp

	lea	fw_part_speeds,a0
	lea	fw_part_coords,a1
	lea	fw_part_coords+FW_NUMBER_OF_PARTICLES*2*2*4,a2
	lea	fw_mulu_planewidth,a3
	lea	fw_planes+2*FW_PLANESIZE,a4
	add.l	fw_planes_add,a4
	lea	sinus,a5
	move.w	#324,d4
	move.w	#2046,d5
	move.w	fw_random,d6
	move.w	#FW_NUMBER_OF_PARTICLES-1,d7
.part1:	; Plot old coordinates
	; --------------------
	move.w	(a2),d0
	move.w	4(a2),d1
	add.w	d1,d1
	move.w	(a3,d1.w),d1
	move.w	d0,d2
	lsr.w	#3,d0
	add.w	d0,d1
	not.w	d2
	bchg.b	d2,(a4,d1.w)
	bchg.b	d2,FW_PLANEWIDTH(a4,d1.w)
	addq	#8,a2

	; Add speed to coordinates
	; ------------------------
	move.l	(a1),d0
	move.l	4(a1),d1
	move.l	(a0),d2
	move.l	4(a0),d3
	add.l	d2,d0
	bmi.s	.reset
	cmp.l	#FW_PLANEWIDTH<<19,d0
	bge.s	.reset
	add.l	d3,d1
	bmi.s	.reset
	cmp.l	#(FW_PLANEHEIGHT-1)<<16,d1
	blt.s	.crdok
.reset:	; Reset particle location and speed
	; ---------------------------------
	move.l	#FW_PLANEWIDTH<<18,d0
	move.l	#14<<16,d1
	move.w	(a5,d6.w),d2
	add.w	d4,d6
	and.w	d5,d6
	move.w	(a5,d6.w),d3
	add.w	d4,d6
	and.w	d5,d6
	ext.l	d2
	ext.l	d3
	sub.l	#$8000,d3
	add.l	d2,d2
	add.l	d2,d2
.crdok:	move.l	d0,(a1)+
	move.l	d1,(a1)+
	; Update speed
	; ------------
	add.l	#$1000,d3
	move.l	d2,(a0)+
	move.l	d3,(a0)+
	
	; Plot new coordinates
	; --------------------
	swap	d0
	swap	d1
	add.w	d1,d1
	move.w	(a3,d1.w),d1
	move.w	d0,d2
	lsr.w	#3,d0
	add.w	d0,d1
	not.w	d2
	bchg.b	d2,(a4,d1.w)
	bchg.b	d2,FW_PLANEWIDTH(a4,d1.w)
	dbra	d7,.part1

	; Move old coordinates in the buffer
	; ----------------------------------
	lea	fw_part_coords+FW_NUMBER_OF_PARTICLES*2*2*4,a0
	lea	fw_part_coords+FW_NUMBER_OF_PARTICLES*2*3*4,a1
	move.w	#2*FW_NUMBER_OF_PARTICLES-1,d7
.parto:	move.l	-(a0),-(a1)
	move.l	-(a0),-(a1)
	dbra	d7,.parto

	waitb

	move.b	#1,render
	rts	

fancywriter_vbi:
	movem.l	a1-a2/d1-d2/d7,-(sp)

	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#3,d0
	bcs.s	.fade
	cmp.w	#120,d0
	bcs.w	.npal
.fade:	mulu	#6,d0
	addq	#6,d0
	sub.w	tp_wait,d0
	cmp.w	#16,d0
	bhi.s	.fdout
	lsl.w	#4,d0
	; Fade palette in
	; ---------------
	lea	fw_palette,a0
	lea	table_fade,a1
	add.w	d0,a1
	lea	fw_cl_palette+2,a2
	moveq	#8-1,d7
.fdpl1:	move.w	#$fff,d0
	sub.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	#$fff,d1
	sub.w	d0,d1
	move.w	d1,(a2)
	addq	#4,a2
	dbra	d7,.fdpl1
	bra.s	.npal

.fdout:	move.w	#123*6-1,d1
.doit:	sub.w	d0,d1
	bmi.s	.npal
	cmp.w	#16,d1
	bhi.s	.npal
	lsl.w	#4,d1
	; Fade palette out
	; ----------------
	lea	fw_palette,a0
	lea	table_fade,a1
	add.w	d1,a1
	lea	fw_cl_palette+2,a2
	moveq	#8-1,d7
.fdpl2:	move.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,(a2)
	addq	#4,a2
	dbra	d7,.fdpl2

.npal:	tst.b	fw_direction
	bne.s	.out
	tst.w	fw_mult
	bne.s	.in
	add.w	#1,fw_wait
	cmp.w	#260,fw_wait
	bcs.s	.mulok
	clr.w	fw_wait
	move.b	#1,fw_direction
	bra.s	.out
.in:	sub.w	#2*256,fw_mult
	cmp.w	#128*256,fw_mult
	bne.s	.mulok
	tst.w	fw_asl
	beq.s	.mulok
	sub.w	#1,fw_asl
	move.w	#254*256,fw_mult
	bra.s	.mulok
.out:	add.w	#2*256,fw_mult
	bne.s	.mulok
	move.w	#128*256,fw_mult
	add.w	#1,fw_asl
	cmp.w	#3,fw_asl
	bcs.s	.mulok
	clr.w	fw_mult
	clr.w	fw_asl
.mulok:	add.w	#16,fw_sinus
	add.w	#134,fw_random
	and.w	#2046,fw_sinus
	and.w	#2046,fw_random
	
	tst.b	render
	beq.s	.vbiok

	; Set the bitplanes
	; -----------------
	move.l	#fw_planes,d0
	add.l	fw_planes_add,d0
	move.l	d0,d1
	add.l	#FW_PLANEWIDTH,d0
	move.w	d0,fw_cl_bpl1ptl
	move.w	d1,fw_cl_bpl2ptl
	swap	d0
	swap	d1
	move.w	d0,fw_cl_bpl1pth
	move.w	d1,fw_cl_bpl2pth

	move.l	#fw_planes+FW_PLANES*FW_PLANESIZE,d0
	add.l	fw_planes_add,d0
	move.w	d0,fw_cl_bpl3ptl
	swap	d0
	move.w	d0,fw_cl_bpl3pth

	; Double buffering
	; ----------------
	eor.l	#FW_PLANESIZE,fw_planes_add
	clr.b	render
.vbiok:	movem.l	(sp)+,a1-a2/d1-d2/d7
	rts

fullscreenscrollersinus:
	; Clear memory
	; ------------
	lea	fs_cl,a0
	move.l	#fs_requirements_chipmem,d7
	bsr	clearmemory
	lea	fs_planes_add,a0
	move.l	#fs_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	fs_ct,a0
	lea	fs_cl,a1
	move.w	#(fs_ct_data-fs_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst
	or.w	#1,fs_cl_bplcon0+2

	; Decrunch bitmap
	; ---------------
	lea	fs_planes,a0
	lea	fs_background_1_stc,a1
	bsr	decrunch

	; Screen setup
	; ------------
	move.l	#fs_planes,d0
	lea	fs_cl_bpl1pth,a0
	moveq	#FS_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#FS_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	fs_mulu_planewidth,a0
	move.l	#FS_PLANEHEIGHT-1,d7
.mulu1:	move.w	d0,(a0)+
	add.w	#FS_PLANEWIDTH,d0
	dbra	d7,.mulu1

	; Create scaling table
	; --------------------
	moveq	#0,d0
	lea	fs_mulu_256,a0
.mulu2:	moveq	#1,d1
.mulu3:	move.w	d0,d2
	mulu	d1,d2
	lsr.w	#8,d2
	move.b	d2,(a0)+
	addq	#1,d1
	cmp.w	#256,d1
	ble.s	.mulu3
	addq	#1,d0
	cmp.w	#128,d0
	bcs.s	.mulu2

	lea	fs_mulu_256-128*256,a0
.mulu4:	moveq	#1,d1
.mulu5:	move.w	d0,d2
	mulu	d1,d2
	lsr.w	#8,d2
	move.b	d2,(a0)+
	addq	#1,d1
	cmp.w	#256,d1
	ble.s	.mulu5
	addq	#1,d0
	cmp.w	#256,d0
	bcs.s	.mulu4

	; Create sinus table
	; ------------------
	lea	sinus,a0
	lea	fs_sinus,a1
	move.l	#1024/4-1,d7
.fssin:	move.w	(a0),d0
	asr.w	#8,d0
	asr.w	d0
	move.w	d0,1536(a1)
	move.w	d0,1024(a1)
	move.w	d0,512(a1)
	move.w	d0,(a1)+
	addq	#8,a0
	dbra	d7,.fssin

	; Decrunch data
	; -------------
;	lea	fs_data_1,a0
;	lea	fs_data_1_stc,a1
;	bsr	decrunch
	lea	fs_data_2,a0
	lea	fs_data_2_stc,a1
	bsr	decrunch

	; Set object
	; ----------
	move.l	#fs_pointers_2,fs_pointers
	move.l	#fs_data_2,fs_data
	move.w	#1536,fs_xsinus
	move.w	#768+42+42,fs_scalesinus
	move.w	#128,fs_scalefactor
	rts

fullscreenscrollersinus_go:
	move.l  #fs_cl,cop1lch+custom
	move.l	#fullscreenscrollersinus_main,part_main
	move.l	#fullscreenscrollersinus_vbi,part_vbi
	rts

fullscreenscrollersinus_main:
	lea	fs_planes+3*FS_PLANESIZE,a4
	add.l	fs_planes_add,a4

	; Clear the first 144 rows of the bitplane
	; ----------------------------------------
	lea	custom,a6
	moveq	#0,d0
	waitb
	move.w	#DEST,bltcon0(a6)
	move.l	#-1,bltafwm(a6)
	move.w	d0,bltdmod(a6)
	move.w	d0,bltcon1(a6)
	move.l	a4,bltdpth(a6)
	move.w	#(144<<6)|(FS_PLANEWIDTH/2),bltsize(a6)

	; Simultaneously clear the rest of the bitplane using the CPU
	; -----------------------------------------------------------
	moveq	#0,d1
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	moveq	#0,d5
	moveq	#0,d6
	sub.l	a0,a0
	move.l	a4,a1
	lea	FS_PLANESIZE(a1),a1
	moveq	#7-1,d7
.clr:	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	dbra	d7,.clr
	waitb

	; Draw the pixel pairs
	; --------------------
	lea	fs_sinus,a1
	add.w	fs_sinusadd,a1
	lea	fs_mulu_256,a2
	lea	fs_mulu_planewidth,a3
	move.w	fs_scalefactor,d4

	; Y origin ((PLANEHEIGHT - zoomed_text_size) / 2)
	; -----------------------------------------------
	move.w	#256,d0
	sub.w	d4,d0
	move.w	#FS_PLANEHEIGHT,d1
	mulu	d0,d1
	lsr.l	#8,d1
	lsr.w	d1
	move.w	d1,fs_yorigin

	; X coordinate delta to be added to source X for every screen X coord
	; -------------------------------------------------------------------
	move.l	#$10000,d3
	divu	d4,d3
	move.w	d3,d0
	ext.l	d3
	lsl.l	#8,d3

	; X coordinate in source data (upper word is the real part)
	; ---------------------------------------------------------
	moveq	#0,d2
	move.w	fs_xposition,d2
	swap	d2
	mulu	#256*FS_PLANEWIDTH*4-1,d0
	sub.l	d0,d2

	; Multiply table offset for zooming
	; ---------------------------------
	subq	#1,d4
	lsl.w	#8,d4
	add.w	d4,a2

	; Current planar bit to set (7 -> 0, next byte, 7 -> 0 ...)
	; ---------------------------------------------------------
	moveq	#7,d5
	move.l	fs_data,a5
	move.l	fs_pointers,a6
	; Skip the width (in the first word)
	; ----------------------------------
	addq	#2,a6

	; Uppermost Y position
	; --------------------
	move.w	fs_yorigin,d1

	; Draw the pixel pairs from X = 0 to X = PLANEWIDTH * 8 - 1
	; ---------------------------------------------------------
	move.l	#FS_PLANEWIDTH*8-1,d7
.xloop:	; Get wobble sinus and advance in it
	; ----------------------------------
	move.w	(a1)+,d4

	; If the source X pointer is outside the source data area do nothing
	; ------------------------------------------------------------------
	move.l	d2,d0
	bmi	.next
	; If the source X pointer is outside the source data area do nothing
	; ------------------------------------------------------------------
	swap	d0
	cmp.w	-2(a6),d0
	bge	fs_fillsinus

	; Add Y origin to sinus wobble
	; ----------------------------
	add.w	d1,d4

	; Get pixel pair data
	; -------------------
	add.w	d0,d0
	move.w	(a6,d0.w),d0
	lea	(a5,d0.w),a0

	; Get number of coordinate pairs - 1 in this column (-1 if none)
	; --------------------------------------------------------------
	move.b	(a0)+,d6
	bmi.s	.next
	ext.w	d6
.yloop:	; Y coordinate of the first pixel in the pair
	; -------------------------------------------
	moveq	#0,d0
	move.b	(a0)+,d0
	; Multiply by zoom
	; ----------------
	move.b	(a2,d0.w),d0
	; Add Y origin and sinus wobble
	; -----------------------------
	add.w	d4,d0
	; Get PLANEWIDTH multiplied offset to plane data
	; ----------------------------------------------
	add.w	d0,d0
	move.w	(a3,d0.w),d0
	bchg.b	d5,(a4,d0.w)

	; Second pixel of pair as above
	; -----------------------------
	moveq	#0,d0
	move.b	(a0)+,d0
	move.b	(a2,d0.w),d0
	add.w	d4,d0
	add.w	d0,d0
	move.w	(a3,d0.w),d0
	bchg.b	d5,(a4,d0.w)
	dbra	d6,.yloop

	; Move on to the next pixel on screen
	; -----------------------------------
.next:	; Advance in source data
	; ----------------------
	add.l	d3,d2
	; Next bit
	; --------
	subq	#1,d5
	bpl.s	.nbyte
	addq	#1,a4
	moveq	#7,d5
.nbyte:	dbra	d7,.xloop

fs_fillsinus:
	; Prepare blitter for vertical filling
	; ------------------------------------
	move.l	#fs_planes+3*FS_PLANESIZE+4,d1
	add.l	fs_planes_add,d1
	move.l	d1,d2
	add.l	#FS_PLANEWIDTH,d2
	lea	custom,a6
	waitb
	move.w	#SRCA|SRCB|DEST|ANBC|ANBNC|NABC|NABNC,bltcon0(a6)
	move.l	d2,bltapth(a6)
	move.l	d1,bltbpth(a6)
	move.l	d2,bltdpth(a6)
	move.l	#$00040004,bltamod(a6)
	move.w	#4,bltbmod(a6)
	move.w	#((FS_PLANEHEIGHT-1)<<6)|((FS_PLANEWIDTH-4)/2),bltsize(a6)

	; Fill the first 4 bytes of each row using the CPU
	; ------------------------------------------------
	lea	fs_planes+3*FS_PLANESIZE,a0
	add.l	fs_planes_add,a0
	moveq	#0,d0
	move.l	#FS_PLANEWIDTH-4,d6
	move.l	#FS_PLANEHEIGHT/8-1,d7
.vfill:	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	dbra	d7,.vfill

fsoks:	move.b	#1,render
	rts

fullscreenscrollersinus_vbi:
	movem.l	d1-d4/d7/a1-a2,-(sp)

	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#3,d0
	bcs.s	.fade
	cmp.w	#110,d0
	bcs	.npal
.fade:	mulu	#6,d0
	addq	#6,d0
	sub.w	tp_wait,d0
	cmp.w	#16,d0
	bhi.s	.fdout
	lsl.w	#4,d0
	; Fade palette in
	; ---------------
	lea	fs_palette_1,a0
	lea	table_fade,a1
	add.w	d0,a1
	lea	fs_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl1:	move.w	#$fff,d0
	sub.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	#$fff,d1
	sub.w	d0,d1
	move.w	d1,(a2)
	addq	#4,a2
	dbra	d7,.fdpl1
	bra.s	.npal

.fdout:	move.w	#113*6-1,d1
	sub.w	d0,d1
	bmi.s	.npal
	cmp.w	#16,d1
	bhi.s	.npal
	lsl.w	#4,d1
	; Fade palette out
	; ----------------
	lea	fs_palette_1,a0
	lea	table_fade,a1
	add.w	d1,a1
	lea	fs_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl2:	move.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,(a2)
	addq	#4,a2
	dbra	d7,.fdpl2

.npal:	; Synchronize scale the beat
	; --------------------------
	add.w	#42,fs_scalesinus
	move.l	sc_position,d0
	and.w	#7,d0
	bne.s	.nsync
	tst.b	fs_synced
	bne.s	.nores
	move.b	#1,fs_synced
	move.w	#768,fs_scalesinus
	bra.s	.nores
.nsync:	clr.b	fs_synced
.nores:	add.w	#2,fs_xsinus
	add.w	#12,fs_sinusadd
	and.w	#2046,fs_scalesinus
	and.w	#2046,fs_xsinus
	and.w	#511,fs_sinusadd

	lea	sinus,a0
	move.w	fs_scalesinus,d0
	move.w	(a0,d0.w),d2
	add.w	#$8000,d2
	lsr.w	#8,d2
	lsr.w	#2,d2
	move.w	d2,d3
	lsr.w	d3
	add.w	d3,d2
	add.w	#32,d2
	cmp.w	#1,d2
	bhi.s	.fsok
	moveq	#2,d2
.fsok:	move.w	d2,fs_scalefactor

	move.w	fs_xsinus,d1
	move.w	(a0,d1.w),d2
	ext.l	d2
	move.l	fs_pointers,a1
	moveq	#0,d3
	move.w	(a1),d3
	move.l	#$8000,d4
	divu	d3,d4
	divs	d4,d2
	add.w	d3,d2
	lsr.w	d2
	move.w	d2,fs_xposition

	tst.b	render
	beq.s	.vbiok

	; Set the bitplanes
	; -----------------
	move.l	#fs_planes+3*FS_PLANESIZE,d0
	add.l	fs_planes_add,d0
	move.w	d0,fs_cl_bpl4ptl
	swap	d0
	move.w	d0,fs_cl_bpl4pth

	; Double buffering
	; ----------------
	eor.l	#FS_PLANES*FS_PLANESIZE,fs_planes_add
	clr.b	render
.vbiok:	movem.l	(sp)+,d1-d4/d7/a1-a2
	rts

fullscreenscrollerrotate:
	; Clear memory
	; ------------
	lea	fs_cl,a0
	move.l	#fs_requirements_chipmem,d7
	bsr	clearmemory
	lea	fs_planes_add,a0
	move.l	#fs_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	fs_ct,a0
	lea	fs_cl,a1
	move.w	#(fs_ct_data-fs_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Decrunch bitmap
	; ---------------
	lea	fs_planes,a0
	lea	fs_background_2_stc,a1
	bsr	decrunch

	; Screen setup
	; ------------
	move.l	#fs_planes,d0
	lea	fs_cl_bpl1pth,a0
	moveq	#FS_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#FS_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	fs_mulu_planewidth,a0
	move.l	#FS_PLANEHEIGHT-1,d7
.mulu1:	move.w	d0,(a0)+
	add.w	#FS_PLANEWIDTH,d0
	dbra	d7,.mulu1

	; Create scaling table
	; --------------------
	moveq	#0,d0
	lea	fs_mulu_256,a0
.mulu2:	move.w	#-255,d1
.mulu3:	move.w	d0,d2
	muls	d1,d2
	asr.w	#7,d2
	add.w	#128,d2
	move.b	d2,(a0)+
	addq	#2,d1
	cmp.w	#256,d1
	blt.s	.mulu3
	addq	#1,d0
	cmp.w	#128,d0
	bcs.s	.mulu2

	moveq	#-128,d0
	lea	fs_mulu_256-128*256,a0
.mulu4:	move.w	#-255,d1
.mulu5:	move.w	d0,d2
	muls	d1,d2
	asr.w	#7,d2
	add.w	#128,d2
	move.b	d2,(a0)+
	addq	#2,d1
	cmp.w	#256,d1
	blt.s	.mulu5
	addq	#1,d0
	bmi.s	.mulu4

	; Create sinus table
	; ------------------
	lea	sinus,a0
	lea	fs_sinus,a1
	move.l	#1024/4-1,d7
.fssin:	move.w	(a0),d0
	asr.w	#8,d0
	asr.w	d0
	move.w	d0,1536(a1)
	move.w	d0,1024(a1)
	move.w	d0,512(a1)
	move.w	d0,(a1)+
	addq	#8,a0
	dbra	d7,.fssin

	; Decrunch data
	; -------------
;	lea	fs_data_1,a0
;	lea	fs_data_1_stc,a1
;	bsr	decrunch
	lea	fs_data_2,a0
	lea	fs_data_2_stc,a1
	bsr	decrunch

	; Set object
	; ----------
	move.l	#fs_pointers_2,fs_pointers
	move.l	#fs_data_2,fs_data
	move.w	#512,fs_xsinus
	rts

fullscreenscrollerrotate_go:
	move.l  #fs_cl,cop1lch+custom
	move.l	#fullscreenscrollerrotate_main,part_main
	move.l	#fullscreenscrollerrotate_vbi,part_vbi
	rts

fullscreenscrollerrotate_main:
	lea	fs_planes+3*FS_PLANESIZE,a4
	add.l	fs_planes_add,a4

	; Clear the first 144 rows of the bitplane
	; ----------------------------------------
	lea	custom,a6
	moveq	#0,d0
	waitb
	move.w	#DEST,bltcon0(a6)
	move.l	#-1,bltafwm(a6)
	move.w	d0,bltdmod(a6)
	move.w	d0,bltcon1(a6)
	move.l	a4,bltdpth(a6)
	move.w	#(144<<6)|(FS_PLANEWIDTH/2),bltsize(a6)

	; Simultaneously clear the rest of the bitplane using the CPU
	; -----------------------------------------------------------
	moveq	#0,d1
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	moveq	#0,d5
	moveq	#0,d6
	sub.l	a0,a0
	move.l	a4,a1
	lea	FS_PLANESIZE(a1),a1
	moveq	#7-1,d7
.clr:	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	movem.l	d0-d6/a0,-(a1)
	dbra	d7,.clr
	waitb

	; Draw the pixel pairs
	; --------------------
	lea	sinus,a1
	lea	fs_mulu_256,a2
	lea	fs_mulu_planewidth,a3

	; Current planar bit to set (7 -> 0, next byte, 7 -> 0 ...)
	; ---------------------------------------------------------
	moveq	#7,d5
	move.l	fs_data,a5
	move.l	fs_pointers,a6

	; Draw the pixel pairs from X = 0 to X = PLANEWIDTH * 8 - 1
	; ---------------------------------------------------------
	move.l	#FS_PLANEWIDTH*8,d7
	move.w	(a6)+,d2
	sub.w	d7,d2
	move.w	fs_xposition,d0
	; Check bounds
	; ------------
	bpl.s	.xpok1
	add.w	d0,d7
	bra.s	.xpok2
.xpok1:	move.w	d0,d3
	sub.w	d2,d3
	bmi.s	.xpok2
	sub.w	d3,d7
.xpok2:	add.w	d0,d0
	add.w	d0,a6
	move.w	fs_rotatesinus,d2
	move.w	#$ff,d3
	subq	#1,d7
	bmi	fs_fillrotate
.xloop:	; Get sinus and advance in it
	; ---------------------------
	move.w	(a1,d2.w),d4
	asr.w	d4
	
	; Get pixel pair data
	; -------------------
	move.w	(a6)+,d0
	lea	(a5,d0.w),a0

	; Get number of coordinate pairs - 1 in this column (-1 if none)
	; --------------------------------------------------------------
	move.b	(a0)+,d6
	bmi.s	.next
	ext.w	d6
.yloop:	; Y coordinate of the first pixel in the pair
	; -------------------------------------------
	move.w	d4,d0
	move.b	(a0)+,d0
	; Multiply by zoom
	; ----------------
	move.b	(a2,d0.w),d0
	and.w	d3,d0
	; Get PLANEWIDTH multiplied offset to plane data
	; ----------------------------------------------
	add.w	d0,d0
	move.w	(a3,d0.w),d0
	bchg.b	d5,(a4,d0.w)

	; Second pixel of pair as above
	; -----------------------------
	move.w	d4,d0
	move.b	(a0)+,d0
	move.b	(a2,d0.w),d0
	and.w	d3,d0
	add.w	d0,d0
	move.w	(a3,d0.w),d0
	bchg.b	d5,(a4,d0.w)
	dbra	d6,.yloop

	; Move on to the next pixel on screen
	; -----------------------------------
.next:	; Next bit
	; --------
	subq	#1,d5
	bpl.s	.nbyte
	addq	#1,a4
	moveq	#7,d5
.nbyte:	addq	#2,d2
	and.w	#2046,d2
	dbra	d7,.xloop

fs_fillrotate:
	; Prepare blitter for vertical filling
	; ------------------------------------
	move.l	#fs_planes+3*FS_PLANESIZE+4,d1
	add.l	fs_planes_add,d1
	move.l	d1,d2
	add.l	#FS_PLANEWIDTH,d2
	lea	custom,a6
	waitb
	move.w	#SRCA|SRCB|DEST|ANBC|ANBNC|NABC|NABNC,bltcon0(a6)
	move.l	d2,bltapth(a6)
	move.l	d1,bltbpth(a6)
	move.l	d2,bltdpth(a6)
	move.l	#$00040004,bltamod(a6)
	move.w	#4,bltbmod(a6)
	move.w	#((FS_PLANEHEIGHT-1)<<6)|((FS_PLANEWIDTH-4)/2),bltsize(a6)

	; Fill the first 4 bytes of each row using the CPU
	; ------------------------------------------------
	lea	fs_planes+3*FS_PLANESIZE,a0
	add.l	fs_planes_add,a0
	moveq	#0,d0
	move.l	#FS_PLANEWIDTH-4,d6
	move.l	#FS_PLANEHEIGHT/8-1,d7
.vfill:	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	eor.l	d0,(a0)
	move.l	(a0)+,d0
	add.w	d6,a0
	dbra	d7,.vfill

fsokr:	move.b	#1,render
	rts

fullscreenscrollerrotate_vbi:
	movem.l	d1-d4/d7/a1-a2,-(sp)

	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#3,d0
	bcs.s	.fade
	cmp.w	#123,d0
	bcs	.npal
.fade:	mulu	#6,d0
	addq	#6,d0
	sub.w	tp_wait,d0
	cmp.w	#16,d0
	bhi.s	.fdout
	lsl.w	#4,d0
	; Fade palette in
	; ---------------
	lea	fs_palette_2,a0
	lea	table_fade,a1
	add.w	d0,a1
	lea	fs_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl1:	move.w	#$fff,d0
	sub.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	#$fff,d1
	sub.w	d0,d1
	move.w	d1,(a2)
	addq	#4,a2
	dbra	d7,.fdpl1
	bra.s	.npal

.fdout:	move.w	#126*6-1,d1
	sub.w	d0,d1
	bmi.s	.npal
	cmp.w	#16,d1
	bhi.s	.npal
	lsl.w	#4,d1
	; Fade palette out
	; ----------------
	lea	fs_palette_2,a0
	lea	table_fade,a1
	add.w	d1,a1
	lea	fs_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl2:	move.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,(a2)
	addq	#4,a2
	dbra	d7,.fdpl2

.npal:	add.w	#26,fs_rotatesinus
	add.w	#2,fs_xsinus
	add.w	#12,fs_sinusadd
	and.w	#2046,fs_rotatesinus
	and.w	#2046,fs_xsinus
	and.w	#511,fs_sinusadd

	lea	sinus,a0
	move.w	fs_xsinus,d1
	move.w	(a0,d1.w),d2
	ext.l	d2
	move.l	fs_pointers,a1
	moveq	#0,d3
	move.w	(a1),d3
	sub.w	#FS_PLANEWIDTH*16,d3
	move.l	#$8000,d4
	divu	d3,d4
	divs	d4,d2
	add.w	d3,d2
	add.w	#FS_PLANEWIDTH*16,d2
	lsr.w	d2
	move.w	d2,fs_xposition

	move.w	fs_rotatesinus,d0
	move.w	(a0,d0.w),d2
	add.w	#$8000,d2
	lsr.w	#8,d2
	move.w	d2,fs_rotate

	tst.b	render
	beq.s	.vbiok

	; Set the bitplanes
	; -----------------
	move.l	#fs_planes+3*FS_PLANESIZE,d0
	add.l	fs_planes_add,d0
	move.w	d0,fs_cl_bpl4ptl
	swap	d0
	move.w	d0,fs_cl_bpl4pth

	; Double buffering
	; ----------------
	eor.l	#FS_PLANES*FS_PLANESIZE,fs_planes_add
	clr.b	render
.vbiok:	movem.l	(sp)+,d1-d4/d7/a1-a2
	rts

	; Horizon
	; -------
horizon:
	; Clear memory
	; ------------
	lea	ho_cl,a0
	move.l	#ho_requirements_chipmem,d7
	bsr	clearmemory
	lea	ho_planes_add,a0
	move.l	#ho_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	ho_ct,a0
	lea	ho_cl,a1
	move.w	#(ho_ct_data2-ho_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst
	move.w	#(64+56)/2-1,d7
.cp1:	clr.l	(a1)+
	dbra	d7,.cp1
	move.w	#(ho_ct_data-ho_ct_data2)/4-1,d7
.cp2:	move.l	(a0)+,(a1)+
	dbra	d7,.cp2
	move.w	#(64+56)/2-1,d7
.cp3:	clr.l	(a1)+
	dbra	d7,.cp3

	; Screen setup
	; ------------
	move.l	#ho_plane_empty,d0
	lea	ho_cl_bpl1pth,a0
	moveq	#HO_HORIZON_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	dbra	d7,.setplanesloop
	move.l	#ho_planes+(HO_PLANES-1)*HO_PLANESIZE,d0
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	ho_mulu_planewidth,a0
	move.l	#HO_PLANES*HO_PLANEHEIGHT-1,d7
.mulu:	move.w	d0,(a0)+
	add.w	#HO_PLANEWIDTH,d0
	dbra	d7,.mulu

	; Create ordered table
	; --------------------
	lea	table_order,a0
	lea	ho_order,a1
	moveq	#0,d1
	moveq	#16-1,d7
.ord1:	moveq	#0,d3
	moveq	#16-1,d6
.ord2:	move.b	(a0)+,d1
	move.w	d7,d2
	addq	#1,d2
	lsl.w	#4,d2
	sub.w	d1,d2
	addx.w	d3,d3
	dbra	d6,.ord2
	move.w	d3,(a1)+
	dbra	d7,.ord1

	; Initialize horizon Z positions
	; ------------------------------
	lea	horizon_table,a0
	move.w	#256,6(a0)
	move.w	#200,18(a0)
	move.w	#144,30(a0)
	move.w	#88,42(a0)

	; Find maximum Y value of each horizon
	; ------------------------------------
	lea	horizon_table,a0
.ho_find_maxy_loop:
	move.l	(a0)+,a2
	moveq	#0,d0
.ho_find_maxy:
	cmp.w	2(a2),d0
	bhi.s	.ho_not_max
	move.w	2(a2),d0
.ho_not_max:
	addq	#4,a2
	cmp.l	#-1,(a2)
	bne.s	.ho_find_maxy
	; Write to horizon table (as the height value)
	; --------------------------------------------
	move.w	d0,(a0)+
	addq	#6,a0
	cmp.l	#horizon_end,a0
	bcs.s	.ho_find_maxy_loop

	; Set up copperlist jump addresses
	; --------------------------------
	move.l	#ho_cl_data1,d0
	move.w	d0,ho_cl_cop2lcl
	swap	d0
	move.w	d0,ho_cl_cop2lch

	; Create fully filled bitplane
	; ----------------------------
	lea	ho_plane_full,a0
	move.l	#HO_PLANEHEIGHT-1,d7
.full:	move.l	#-1,(a0)+
	move.l	#-1,(a0)+
	move.l	#-1,(a0)+
	move.l	#-1,(a0)+
	move.l	#-1,(a0)+
	move.l	#-1,(a0)+
	move.l	#-1,(a0)+
	move.l	#-1,(a0)+
	move.l	#-1,(a0)+
	move.l	#-1,(a0)+
	dbra	d7,.full

	; Create gradient helper bitplane
	; -------------------------------
	lea	ho_planes+(HO_PLANES-1)*HO_PLANESIZE,a0
	move.l	#HO_PLANEHEIGHT/16-1,d7
.grad1:	lea	ho_order,a1
	moveq	#16-1,d6
.grad2:	moveq	#HO_PLANEWIDTH/2-1,d5
.grad3:	move.w	(a1),(a0)+
	dbra	d5,.grad3
	addq	#2,a1
	dbra	d6,.grad2
	dbra	d7,.grad1

	move.l	#$6000,ho_speed

	move.w	ho_gradient,ho_cl_palette+2
	move.l	#horizon_table,ho_table
	rts

horizon_go:
	move.l	#horizon_main,part_main
	move.l	#horizon_vbi,part_vbi
	rts

horizon_main:
	; Clear bitplanes
	; ---------------
	lea	custom,a6
	move.l	#ho_planes,d0
	add.l	ho_planes_add,d0
	; Clear (ho_clear/2) & $fff0 rows using the CPU and the rest using blt
	; --------------------------------------------------------------------
	move.w	ho_clear+2,d1
	move.w	d1,d6
	move.w	d1,d7
	lsr.w	d7
	and.w	#$fff0,d7
	sub.w	d7,d1
	lsl.w	#6,d1
	or.w	#HO_PLANEWIDTH/2,d1
	moveq	#0,d2
	waitb
	move.w	#DEST,bltcon0(a6)
	move.l	#-1,bltafwm(a6)
	move.w	d2,bltdmod(a6)
	move.w	d2,bltcon1(a6)
	move.l	d0,bltdpth(a6)
	move.w	d1,bltsize(a6)

	; Clear rest of the bitplanes using the CPU
	; -----------------------------------------
	move.l	d0,a0
	mulu	#HO_PLANEWIDTH,d6
	add.l	d6,a0
	moveq	#0,d0
	moveq	#0,d1
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	moveq	#0,d5
	moveq	#0,d6
	sub.l	a1,a1
	sub.l	a2,a2
	sub.l	a3,a3
	lsr.w	#4,d7
	subq	#1,d7
	bmi	.noclr
.clr:	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	movem.l	d0-d6/a1-a3,-(a0)
	dbra	d7,.clr

.noclr:	; Calculate zoom values
	; ---------------------
	move.w	ho_frames,d1
	clr.w	ho_frames
	lea	horizon_table,a0
.zoom_loop:
	sub.w	d1,HO_TABLE_Z(a0)
	cmp.w	#31,HO_TABLE_Z(a0)
	bhi.s	.zoom_ok
	move.l	a0,ho_table
	move.w	#256,HO_TABLE_Z(a0)
.zoom_ok:
	move.l	#256*HO_PLANEWIDTH*8,d0
	divu	HO_TABLE_Z(a0),d0
	move.w	d0,HO_TABLE_ZOOM(a0)
	add.l	#HO_TABLE_SIZE,a0
	cmp.l	#horizon_end,a0
	bcs.s	.zoom_loop
	
	; Fade horizon colors
	; -------------------
	move.l	ho_table,a0
	lea	ho_colors,a1
	lea	ho_cl_data1+2,a2
	add.l	ho_cl_data_add,a2
	cmp.w	#228,HO_TABLE_Z(a0)
	bcc.s	.setc
	addq	#2,a1
.setc:	move.w	(a1),d0
	move.w	4(a1),d1
	move.w	8(a1),d2
	move.w	12(a1),d3
	move.w	d0,(a2)
	move.w	d0,60(a2)
	move.w	d1,4(a2)
	move.w	d1,8(a2)
	move.w	d1,64(a2)
	move.w	d1,68(a2)
	move.w	d2,12(a2)
	move.w	d2,16(a2)
	move.w	d2,20(a2)
	move.w	d2,24(a2)
	move.w	d2,72(a2)
	move.w	d2,76(a2)
	move.w	d2,80(a2)
	move.w	d2,84(a2)
	move.w	d3,28(a2)
	move.w	d3,32(a2)
	move.w	d3,36(a2)
	move.w	d3,40(a2)
	move.w	d3,44(a2)
	move.w	d3,48(a2)
	move.w	d3,52(a2)
	move.w	d3,56(a2)
	move.w	d3,88(a2)
	move.w	d3,92(a2)
	move.w	d3,96(a2)
	move.w	d3,100(a2)
	move.w	d3,104(a2)
	move.w	d3,108(a2)
	move.w	d3,112(a2)
	move.w	d3,116(a2)

	; Prepare blitter for vertical filling
	; ------------------------------------
	lea	custom,a6
	moveq	#0,d0
	waitb
	move.w	#SRCA|SRCB|DEST|ABC|ABNC|ANBC|ANBNC|NABC|NABNC,bltcon0(a6)
	move.l	d0,bltamod(a6)
	move.l	d0,bltcmod(a6)
	move.w	d0,bltcon1(a6)

	; Render each horizon
	; -------------------
	clr.w	ho_pass
	lea	ho_mulu_planewidth,a1
	move.l	ho_table,a4
	lea	ho_height,a5
	clr.l	8(a5)
	clr.l	12(a5)
.horiz:	clr.w	(a5)
	move.l	(a4)+,a6
	; Calculate Y coordinate substract (maxy-PLANEHEIGHT)/2
	; -----------------------------------------------------
	move.w	(a4),d2
	mulu	4(a4),d2
	lsr.l	#8,d2
	sub.w	#HO_PLANEHEIGHT,d2
	bpl.s	.subd2
	moveq	#0,d2
	bra.s	.subok
.subd2:	lsr.w	d2
.subok:	move.w	d2,HO_SUBSTRACT(a1)
	; Calculate first coordinate pair into the stack
	; ----------------------------------------------
	move.w	(a6)+,d0
	move.w	(a6)+,d1
	move.w	4(a4),d4
	muls	d4,d0
	muls	d4,d1
	asr.l	#8,d0
	asr.l	#8,d1
	add.w	#HO_PLANEWIDTH*8/2,d0
	sub.w	d2,d1
	; Reset minx and maxx values for this horizon
	; -------------------------------------------
	move.w	#HO_PLANEWIDTH*8-1,HO_MINXX(a1)
	clr.w	HO_MAXXX(a1)
	move.w	d1,-(sp)
	move.w	d0,-(sp)
.loop:	lea	ho_planes,a0
	add.l	ho_planes_add,a0
	moveq	#0,d0
	move.w	8(a5),d0
	add.l	d0,a0
	; Use previous coordinate pair values from the stack
	; --------------------------------------------------
	move.w	(sp)+,d0
	move.w	(sp)+,d1
	move.w	(a6)+,d2
	move.w	(a6)+,d3
	move.w	4(a4),d4
	muls	d4,d2
	muls	d4,d3
	asr.l	#8,d2
	asr.l	#8,d3
	add.w	#HO_PLANEWIDTH*8/2,d2
	sub.w	HO_SUBSTRACT(a1),d3
	move.w	d3,-(sp)
	move.w	d2,-(sp)
	bsr	VerticalFillLine
	; Check if current height (after clipping) has changed
	; ----------------------------------------------------
	cmp.w	(a5),a3
	blt.s	.nmaxy
	move.w	a3,(a5)
.nmaxy:	cmp.l	#-1,(a6)
	bne.s	.loop

	; If the leftmost X coordinate was not 0 draw line from it to 0
	; -------------------------------------------------------------
	move.w	HO_MINXX(a1),d2
	beq.s	.nminl
	; If no lines were drawn don't draw any lines now either
	; ------------------------------------------------------
	cmp.w	#HO_PLANEWIDTH*8-1,d2
	beq.s	.nminl
	move.w	HO_MINXY(a1),d3
	; Only draw the line if it's missing from the top of the screen
	; -------------------------------------------------------------
	bne.s	.nminl
	moveq	#0,d0
	move.w	d3,d1
	bsr	VerticalFillLineNoClip
.nminl:	; If the rightmost X coordinate was not 351 draw line from it to 351
	; ------------------------------------------------------------------
	move.w	HO_MAXXX(a1),d0
	; If no lines were drawn don't draw any lines now either
	; ------------------------------------------------------
	beq.s	.nmaxl
	cmp.w	#HO_PLANEWIDTH*8-1,d0
	beq.s	.nmaxl
	move.w	HO_MAXXY(a1),d1
	; Only draw the line if it's missing from the top of the screen
	; -------------------------------------------------------------
	bne.s	.nmaxl
	move.w	#HO_PLANEWIDTH*8-1,d2
	move.w	d1,d3
	bsr	VerticalFillLineNoClip
.nmaxl:
	; Restore stack
	; -------------	
	addq	#4,sp
	; Calculate plane offsets
	; -----------------------
	add.w	#1,(a5)
	moveq	#0,d0
	move.w	(a5)+,d0
	add.w	d0,d0
	move.w	(a1,d0.w),d0
	add.w	6(a5),d0
	move.w	d0,8(a5)
	move.w	6(a5),d0
	; Fill the current horizon
	; ------------------------
	add.l	#ho_planes,d0
	add.l	ho_planes_add,d0
	move.l	d0,d1
	add.l	#HO_PLANEWIDTH,d1
.waitb:	btst	#14,dmaconr+custom
	bne.s	.waitb
	move.l	#-1,bltafwm+custom
	move.l	d1,bltapth+custom
	move.l	d0,bltbpth+custom
	move.l	d1,bltdpth+custom
	move.w	-2(a5),d0
	subq	#1,d0
	beq.s	.nblit
	lsl.w	#6,d0
	or.w	#HO_PLANEWIDTH/2,d0
	move.w	d0,bltsize+custom
.nblit:	; Render all horizons
	; -------------------
	add.w	#1,ho_pass
	cmp.w	#HO_HORIZON_PLANES,ho_pass
	beq.s	.passd
	addq	#8,a4
	cmp.l	#horizon_end,a4
	bcs.w	.horiz
	lea	horizon_table,a4
	bra.w	.horiz

.passd:	; Calculate total height to be cleared
	; ------------------------------------
	move.w	ho_clear,ho_clear+2
	clr.w	ho_clear
	lea	ho_height,a0
	moveq	#HO_HORIZON_PLANES-1,d7
.cumul:	move.w	(a0)+,d0
	add.w	d0,ho_clear
	dbra	d7,.cumul

	; Calculate bitplane y positions
	; ------------------------------
	move.l	ho_table,a0
	lea	ho_height,a1
	lea	ho_copper,a2
	moveq	#0,d2
	moveq	#4,d3
	moveq	#HO_HORIZON_PLANES-1,d7
.calcy:	move.w	4(a0),d0
	mulu	8(a0),d0
	lsr.l	#8,d0
	lsr.w	d0
	move.w	#HO_PLANEHEIGHT/2,d1
	sub.w	d0,d1
	bpl.s	.pyok
	moveq	#0,d1
.pyok:	; If the height of the horizon is 0 only sky is to be drawn
	; ---------------------------------------------------------
	move.w	(a1)+,d0
	subq	#1,d0
	bne.s	.heiok
	move.w	#HO_PLANEHEIGHT-1,d1
.heiok:	move.w	d1,(a2)+
	move.w	d2,(a2)+
	add.w	d0,d1
	move.w	d1,(a2)+
	move.w	d3,(a2)+
	addq	#1,d2
	addq	#1,d3
	add.l	#12,a0
	cmp.l	#horizon_end,a0
	bcs.s	.hotok
	lea	horizon_table,a0
.hotok:	dbra	d7,.calcy

	; Sort Y positions
	; ----------------
	lea	ho_copper,a0
	moveq	#8,d0
	move.l	#HO_PLANEHEIGHT,d1
	bsr	StraightRadixSort

	; Check for duplicates
	; --------------------
	lea	ho_copper,a1
	moveq	#7-1,d7
.dupe1:	move.l	a1,a0
	move.w	(a0),d0
.dupe2:	addq	#4,a0
	cmp.l	#ho_copper+32,a0
	beq.s	.dupe3
	cmp.w	(a0),d0
	bne.s	.dupe2
	add.w	#1,(a0)
	bra.s	.dupe2
.dupe3:	addq	#4,a1
	dbra	d7,.dupe1

	; Create copperlist
	; -----------------
	lea	ho_cl_data1+120,a0
	add.l	ho_cl_data_add,a0
	lea	ho_mulu_planewidth,a1
	lea	ho_copper,a2
	lea	ho_height+8,a3
	move.l	#ho_planes,a4
	add.l	ho_planes_add,a4
	lea	ho_gradient,a5
	moveq	#0,d3
	move.w	(a5)+,d4
	moveq	#0,d6
	sub.l	a6,a6
	moveq	#HO_HORIZON_PLANES*2-1,d7
.cop:	move.w	(a2)+,d1
	move.w	(a2)+,d2
	; Draw gradient if it has not been drawn yet
	; ------------------------------------------
.bg:	cmp.w	#9*HO_GRADIENT_HEIGHT,d3
	bhi.s	.nobg
	; Set bitplane values if they should be set
	; -----------------------------------------
	cmp.w	d3,d1
	ble.s	.nobg
	move.w	d3,d5
	; Add first Y position (this should match cl_diwstrt)
	; ---------------------------------------------------
	add.w	#$28,d5
	lsl.w	#8,d5
	or.w	#1,d5
	; If the line has already been waited for don't wait again
	; --------------------------------------------------------
	cmp.l	d5,a6
	beq.s	.nwait
	move.w	d5,(a0)+
	move.w	#$fffe,(a0)+
.nwait:	move.w	#$180,(a0)+
	move.w	d4,(a0)+
	add.w	#HO_GRADIENT_HEIGHT,d3
	move.w	(a5)+,d4
	move.w	#$1a0,(a0)+
	move.w	d4,(a0)+
	bra.s	.bg

.nobg:	; Add first Y position (this should match cl_diwstrt)
	; ---------------------------------------------------
	add.w	#$28,d1
	; End copperlist if bottom reached
	; --------------------------------
	cmp.w	#$12f,d1
	bhi.s	.copdn
	cmp.w	#$100,d1
	bcs.s	.copyo
	sub.w	#$100,d1
	tst.w	d6
	bne.s	.copyo
	move.l	#$ffe1fffe,(a0)+
	moveq	#1,d6
.copyo:	lsl.w	#8,d1
	or.w	#1,d1
	move.w	d1,(a0)+
	move.w	#$fffe,(a0)+
	move.l	d1,a6

	cmp.w	#3,d2
	bhi.s	.full
	moveq	#0,d0
	add.w	d2,d2
	move.w	(a3,d2.w),d0
	add.l	a4,d0
	add.w	d2,d2
	add.w	#bpl1ptl,d2
	move.w	d2,(a0)+
	move.w	d0,(a0)+
	swap	d0
	subq	#2,d2
	move.w	d2,(a0)+
	move.w	d0,(a0)+
	dbra	d7,.cop
	bra.s	.copdn

.full:	sub.w	#4,d2
	add.w	d2,d2
	add.w	d2,d2
	add.w	#bpl1ptl,d2
	move.l	#ho_plane_full,d0
	move.w	d2,(a0)+
	move.w	d0,(a0)+
	swap	d0
	subq	#2,d2
	move.w	d2,(a0)+
	move.w	d0,(a0)+
	dbra	d7,.cop

.copdn:	move.l	#$fffffffe,(a0)+
	move.b	#1,render
	rts

; a0: array to sort
; d0: array size in long words
; d1: maximum value in array
StraightRadixSort:
	move.l	a0,a4
	move.l	d0,d6
	move.l	d1,d5
	move.l	d0,d4
	add.l	d4,d4
	add.l	d4,d4
	subq	#1,d5
	subq	#1,d6
	lea	ho_rs_tempbuffer,a5
	lea	ho_rs_distcount,a6

	; Clear distribution count
	; ------------------------
	move.l	a6,a0
	move.w	d5,d7
.clear:	clr.b	(a0)+
	dbra	d7,.clear

	; Calculate distribution
	; ----------------------
	moveq	#0,d0
	move.l	a6,a0
	move.l	a4,a1
	move.w	d6,d7
.dist:	move.w	(a1),d0
	add.b	#1,(a0,d0.w)
	addq	#4,a1
	dbra	d7,.dist

	; Calculate cumulative distribution
	; ---------------------------------
	move.l	a6,a0
	move.w	d5,d7
	subq	#1,d7
.cumul:	move.b	(a0)+,d0
	add.b	d0,(a0)
	dbra	d7,.cumul

	moveq	#0,d0
	move.l	a6,a0
	move.l	a4,a1
	add.l	d4,a1
	move.l	a5,a2
	move.l	a1,a3
	moveq	#0,d1
	move.w	d6,d7
.spred:	subq	#4,a3
	move.w	(a3),d0
	move.b	(a0,d0.w),d1
	subq	#1,d1
	move.b	d1,(a0,d0.w)
	add.w	d1,d1
	add.w	d1,d1
	move.l	-(a1),(a2,d1.w)
	dbra	d7,.spred

	move.l	a5,a0
	move.l	a4,a1
	move.w	d6,d7
.copy:	move.l	(a0)+,(a1)+
	dbra	d7,.copy
	rts

; Draws a line, one pixel per x position
; --------------------------------------
; a0: bitplanes
; d0: x1
; d1: y1
; d2: x2
; d3: y2
; uses d0-d7/a0-a3
VerticalFillLine:
	; Clipping test
	; -------------
	sub.l	a2,a2
	sub.l	a3,a3
.loop:	moveq	#0,d4		; code1
	moveq	#0,d5		; code2
	tst.w	d0
	bpl.s	.x1lok
	or.w	#CLIP_LEFT_EDGE,d4
.x1lok:	cmp.w	#HO_PLANEWIDTH*8,d0
	blt.s	.x1rok
	or.w	#CLIP_RIGHT_EDGE,d4
.x1rok:	tst.w	d1
	bpl.s	.y1lok
	or.w	#CLIP_TOP_EDGE,d4
.y1lok:	cmp.w	#HO_PLANEHEIGHT,d1
	blt.s	.y1rok
	or.w	#CLIP_BOTTOM_EDGE,d4
.y1rok:	tst.w	d2
	bpl.s	.x2lok
	or.w	#CLIP_LEFT_EDGE,d5
.x2lok:	cmp.w	#HO_PLANEWIDTH*8,d2
	blt.s	.x2rok
	or.w	#CLIP_RIGHT_EDGE,d5
.x2rok:	tst.w	d3
	bpl.s	.y2lok
	or.w	#CLIP_TOP_EDGE,d5
.y2lok:	cmp.w	#HO_PLANEHEIGHT,d3
	blt.s	.y2rok
	or.w	#CLIP_BOTTOM_EDGE,d5
.y2rok:	move.w	d4,d6
	or.w	d5,d6
	beq.w	.line
	move.w	d4,d6
	and.w	d5,d6
	beq.s	.ok
	sub.l	a3,a3
	rts
.ok:	cmp.l	#0,a2
	bne.s	.m2
	move.w	d3,d6		; m1=(y2-y1)/(x2-x1)
	sub.w	d1,d6
	ext.l	d6
	asl.l	#5,d6
	move.w	d2,d7
	sub.w	d0,d7
	beq.s	.m1
	add.l	#$3f,d6
	divs	d7,d6
	ext.l	d6
	move.l	d6,a2
.m1:	move.w	d2,d6		; m2=(x2-x1)/(y2-y1)
	sub.w	d0,d6
	ext.l	d6
	asl.l	#5,d6
	move.w	d3,d7
	sub.w	d1,d7
	beq.s	.m2
	add.l	#$3f,d6
	divs	d7,d6
	ext.l	d6
	move.l	d6,a3
.m2:	tst.w	d4
	bne.s	.clip
	exg	d0,d2
	exg	d1,d3
	exg	d4,d5
.clip:	btst	#0,d4
	beq.s	.nleft
	move.l	a2,d6
	muls	d6,d0
	asr.l	#6,d0
	sub.l	d0,d1
	moveq	#0,d0
	bra.w	.loop
.nleft:	btst	#1,d4
	beq.s	.nrite
	sub.l	#HO_PLANEWIDTH*8-1,d0
	move.l	a2,d6
	muls	d6,d0
	asr.l	#6,d0
	sub.l	d0,d1
	move.l	#HO_PLANEWIDTH*8-1,d0
	bra.w	.loop
.nrite:	btst	#2,d4
	beq.s	.ntop
	cmp.w	d0,d2
	beq.s	.y1
	move.l	a3,d6
	muls	d6,d1
	asr.l	#6,d1
	sub.l	d1,d0
.y1:	moveq	#0,d1
	bra.w	.loop
.ntop:	btst	#3,d4
	beq.w	.loop
	cmp.w	d0,d2
	beq.s	.y2
	sub.l	#HO_PLANEHEIGHT-1,d1
	move.l	a3,d6
	muls	d6,d1
	asr.l	#6,d1
	sub.l	d1,d0
.y2:	move.l	#HO_PLANEHEIGHT-1,d1
	bra.w	.loop

.line:	; Check if the coordinates are the leftmost or rightmost
	; ------------------------------------------------------
	cmp.w	HO_MINXX(a1),d0
	bcc.s	.nmix1
	move.w	d0,HO_MINXX(a1)
	move.w	d1,HO_MINXY(a1)
.nmix1:	cmp.w	HO_MINXX(a1),d2
	bcc.s	.nmix2
	move.w	d2,HO_MINXX(a1)
	move.w	d3,HO_MINXY(a1)
.nmix2:	cmp.w	HO_MAXXX(a1),d0
	bls.s	.nmax1
	move.w	d0,HO_MAXXX(a1)
	move.w	d1,HO_MAXXY(a1)
.nmax1:	cmp.w	HO_MAXXX(a1),d2
	bls.s	.nmax2
	move.w	d2,HO_MAXXX(a1)
	move.w	d3,HO_MAXXY(a1)
.nmax2:	; Return clipped maximum y in a3
	; ------------------------------
	move.l	d1,a3
	cmp.w	d1,d3
	blt.s	.draw
	move.l	d3,a3
.draw:
VerticalFillLineNoClip:
	; Draw the line
	; -------------
	move.l	#1,a2
	cmp.w	d0,d2
	bge.s	.noexg
	exg	d0,d2
	exg	d1,d3
.noexg:	move.w	d2,d4		; dx
	sub.w	d0,d4
	move.w	d3,d5		; dy
	sub.w	d1,d5
	bpl.s	.dyok
	neg.w	d5
	move.l	#-1,a2
.dyok:	cmp.w	d4,d5
	bgt.s	.yline

	; dx>=dy
	; ------
	add.w	d5,d5		; 2dy
	move.w	d5,d6		; p
	sub.w	d4,d6
	add.w	d4,d4		; 2dx
	neg.w	d4		; 2dy-2dx
	add.w	d5,d4

	move.w	d0,d3
	move.w	d0,d7
	not.w	d7
	and.w	#7,d7
	lsr.w	#3,d3
	add.w	d3,a0
	move.w	d1,d3
	add.w	d3,d3
	move.w	(a1,d3.w),d3
	bset.b	d7,(a0,d3.w)

	; If x1==x2 and y1==y2 don't go to loop
	; -------------------------------------
	cmp.w	d0,d2
	bne.s	.xloop
	tst.w	d5
	beq.s	.done
	
.xloop:	addq	#1,d0
	subq	#1,d7
	bpl.s	.nxadd
	and.l	#7,d7
	addq	#1,a0
.nxadd:	tst.w	d6
	bpl.s	.xpos
	add.w	d5,d6
	bra.s	.xplot
.xpos:	add.w	a2,d1
	add.w	d4,d6
.xplot:	move.w	d1,d3
	add.w	d3,d3
	move.w	(a1,d3.w),d3
	bset.b	d7,(a0,d3.w)
	cmp.w	d2,d0
	bne.s	.xloop
.done:	rts

.yline:	; dy>dx
	; -----
	exg	d4,d5
	add.w	d5,d5		; 2dx
	move.w	d5,d6		; p
	sub.w	d4,d6
	add.w	d4,d4		; 2dy
	neg.w	d4		; 2dx-2dy
	add.w	d5,d4

	move.w	d0,d2
	move.w	d0,d7
	not.w	d7
	and.w	#7,d7
	lsr.w	#3,d2
	add.w	d2,a0

.yloop:	tst.w	d6
	bpl.s	.ypos
	add.w	a2,d1
	add.w	d5,d6
	cmp.w	d3,d1
	bne.s	.yloop
	rts
.ypos:	move.w	d1,d2
	add.w	d2,d2
	move.w	(a1,d2.w),d2
	bset.b	d7,(a0,d2.w)
	add.w	a2,d1
	addq	#1,d0
	subq	#1,d7
	bpl.s	.nyadd
	and.l	#7,d7
	addq	#1,a0
.nyadd:	add.w	d4,d6
	cmp.w	d3,d1
	bne.s	.yloop
	rts

horizon_vbi:
	sub.l	a0,a0
	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#32,d0
	bcs.s	.up
	cmp.w	#56,d0
	bcs.s	.spdok
	cmp.w	#88,d0
	bcs.s	.down
	move.l	#$880,a0
	bra.s	.spdok
.up:	move.l	#$660,a0
	bra.s	.spdok
.down:	move.l	#-$330,a0
.spdok:	move.l	ho_speed,d0
	add.l	d0,ho_frames
	add.l	a0,d0
	move.l	d0,ho_speed
	
	tst.b	render
	beq.s	.vbiok
	
	; Use the correct copperlist
	; --------------------------
	move.l  #ho_cl,cop1lch+custom
	move.w	#%0000000000000001+$1000*HO_PLANES,ho_cl_bplcon0+2
	move.l	#ho_cl_data1,d0
	add.l	ho_cl_data_add,d0
	move.w	d0,ho_cl_cop2lcl
	swap	d0
	move.w	d0,ho_cl_cop2lch

	; Double buffering
	; ----------------
	eor.l	#HO_PLANES*HO_PLANESIZE,ho_planes_add
	eor.l	#ho_cl_data2-ho_cl_data1,ho_cl_data_add
	clr.b	render
	move.w	#$ff0,ne_cl_palette+2
.vbiok:	rts

imageroll:
	; Clear memory
	; ------------
	lea	ir_cl,a0
	move.l	#ir_requirements_chipmem,d7
	bsr	clearmemory
	lea	ir_copperlist_add,a0
	move.l	#ir_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	ir_ct,a0
	lea	ir_cl,a1
	move.w	#(ir_ct_data-ir_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Screen setup
	; ------------
	move.l	#ir_planes,d0
	lea	ir_cl_bpl1pth,a0
	moveq	#IR_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#IR_PLANEWIDTH,d0
	dbra	d7,.setplanesloop

	move.l	#ir_cl_data,d0
	move.w	d0,ir_cl_cop2lcl
	swap	d0
	move.w	d0,ir_cl_cop2lch

	; Decrunch bitmap
	; ---------------
	lea	ir_planes+((IR_PLANEHEIGHT-32-IR_SOURCE_HEIGHT)/2+32)*IR_PLANES*IR_PLANEWIDTH,a0
	lea	ir_picture_stc,a1
	bsr	decrunch
	
	lea	ir_planes+((IR_PLANEHEIGHT-32-IR_SOURCE_HEIGHT)/2+32)*IR_PLANES*IR_PLANEWIDTH+IR_SOURCE_HEIGHT*IR_PLANES*IR_PLANEWIDTH,a0
	lea	ir_cl_palette+2,a1
	moveq	#16-1,d7
.pallp:	move.w	(a0),(a1)
	clr.w	(a0)+
	addq	#4,a1
	dbra	d7,.pallp

	move.l	#$fffffffe,ir_cl_data
	move.l	#$fffffffe,ir_cl_data+(IR_RADIUS*2*6+2+4+2)*2

	; Use $1a as the starting position because the first 25 lines are for VBI
	; -----------------------------------------------------------------------
	move.w	#$1a+1,ir_y
	rts

imageroll_go:
	move.l  #ir_cl,cop1lch+custom
	move.l	#imageroll_main,part_main
	move.l	#imageroll_vbi,part_vbi
	rts

imageroll_main:
	lea	ir_low,a0
	lea	ir_high,a1
	lea	ir_cl_data,a2
	add.l	ir_copperlist_add,a2
	move.w	ir_y,d0
	move.w	d0,d2
	; Current copper wait
	; -------------------
	lsl.w	#8,d0
	add.w	#$0001,d0
	; Current y position relative to the beginning of the roll
	; --------------------------------------------------------
	moveq	#-1,d1
	; How many pixels are rolled
	; --------------------------
	move.w	#IR_PLANEHEIGHT-IR_MAX+2*IR_RADIUS,d7
	sub.w	d2,d7
	bmi	ir_dn
	; Only 2*IR_RADIUS pixels can be rolled
	; ----------------------------------
	cmp.w	#2*IR_RADIUS,d7
	ble.s	.hiok
	move.w	#2*IR_RADIUS,d7
.hiok:	; How many pixels are shown from the "bottom" layer
	; -------------------------------------------------
	move.w	#2*IR_RADIUS,d6
	sub.w	d7,d6
	beq	.high
	add.w	d6,a1

	subq	#1,d6
	bmi	.high
.lowl:	moveq	#0,d2
	move.b	(a0)+,d2
	move.w	d2,d3
	; Delta between current and previous
	; ----------------------------------
	sub.w	d1,d3
	; Store previous
	; --------------
	move.w	d2,d1
	; Calculate modulo
	; ----------------
	muls	#IR_PLANES*IR_PLANEWIDTH,d3
	sub.w	#IR_PLANEWIDTH,d3
	cmp.w	#$0001,d0
	bne.s	.nolw
	move.l	#$ffd1fffe,(a2)+
.nolw:	move.w	d0,(a2)+
	move.w	#$fffe,(a2)+
	move.w	#bpl1mod,(a2)+
	move.w	d3,(a2)+
	move.w	#bpl2mod,(a2)+
	move.w	d3,(a2)+
	add.w	#$100,d0
	dbra	d6,.lowl

.high:	subq	#1,d7
	bmi	.hdone
.highl:	moveq	#0,d2
	move.b	(a1)+,d2
	move.w	d2,d3
	; Delta between current and previous
	; ----------------------------------
	sub.w	d1,d3
	; Store previous
	; --------------
	move.w	d2,d1
	; Calculate modulo
	; ----------------
	muls	#IR_PLANES*IR_PLANEWIDTH,d3
	sub.w	#IR_PLANEWIDTH,d3
	cmp.w	#$0001,d0
	bne.s	.nohw
	move.l	#$ffd1fffe,(a2)+
.nohw:	move.w	d0,(a2)+
	move.w	#$fffe,(a2)+
	move.w	#bpl1mod,(a2)+
	move.w	d3,(a2)+
	move.w	#bpl2mod,(a2)+
	move.w	d3,(a2)+
	add.w	#$100,d0
	dbra	d7,.highl

.hdone:	cmp.w	#$0001,d0
	bne.s	.nolw2
	move.l	#$ffd1fffe,(a2)+
.nolw2:	move.w	d0,(a2)+
	move.w	#$fffe,(a2)+
	move.w	#bplcon0,(a2)+
	clr.w	(a2)+
	move.l	#$fffffffe,(a2)+

	tst.b	ir_direction
	beq	.down
	cmp.w	#$1b,ir_y
	beq.s	ir_dn
	sub.w	#2,ir_y
	bra.s	ir_dn
.down:	cmp.w	#IR_PLANEHEIGHT-IR_MAX+2*IR_RADIUS-1,ir_y
	bhs.s	.wait
	add.w	#2,ir_y	
	bra.s	ir_dn
.wait:	tst.w	ir_wait
	bne.s	ir_dn
	move.w	#1,ir_wait
ir_dn:	move.b	#1,render
	rts

imageroll_vbi:
	tst.w	ir_wait
	beq.s	.nwait
	add.w	#1,ir_wait
	cmp.w	#560,ir_wait
	bcs.s	.nwait
	move.b	#1,ir_direction
.nwait:	tst.b	render
	beq.s	.vbiok
	move.l	#ir_cl_data,d0
	add.l	ir_copperlist_add,d0
	move.w	d0,ir_cl_cop2lcl
	swap	d0
	move.w	d0,ir_cl_cop2lch
	
	eor.l	#(IR_RADIUS*2*6+2+4+2)*2,ir_copperlist_add
	clr.b	render
	move.w	#$fff,ne_cl_palette+2
.vbiok:	rts

insaneplasma:
	; Clear memory
	; ------------
	lea	ip_cl,a0
	move.l	#ip_requirements_chipmem,d7
	bsr	clearmemory
	lea	ip_copperadd,a0
	move.l	#ip_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	ip_ct,a0
	lea	ip_cl,a1
	move.w	#(ip_ct_data1-ip_ct)/4-1,d7
.cpl1:	move.l	(a0)+,(a1)+
	dbra	d7,.cpl1
	move.w	#(ip_cl_2-ip_cl_data1)/4-1,d7
.cpl2:	clr.l	(a1)+
	dbra	d7,.cpl2
	move.w	#(ip_ct_data2-ip_ct_2)/4-1,d7
.cpl3:	move.l	(a0)+,(a1)+
	dbra	d7,.cpl3
	move.w	#(ip_planes-ip_cl_data2)/4-1,d7
.cpl4:	clr.l	(a1)+
	dbra	d7,.cpl4

	; Screen setup
	; ------------
	move.l	#ip_planedata,d0
	move.l	d0,d1
	add.l	#4*IP_PLANEWIDTH,d1
	lea	ip_cl_bpl1pth1,a0
	lea	ip_cl_bpl1pth2,a1
	moveq	#4-1,d7
.setplanesloop1:
	move.w	d0,4(a0)
	move.w	d1,4(a1)
	swap	d0
	swap	d1
	move.w	d0,(a0)
	move.w	d1,(a1)
	swap	d0
	swap	d1
	addq	#8,a0
	addq	#8,a1
	add.l	#IP_PLANEWIDTH,d0
	add.l	#IP_PLANEWIDTH,d1
	dbra	d7,.setplanesloop1

	move.l	#ip_planes,d0
	lea	ip_cl_bpl2pth,a0
	moveq	#2-1,d7
.setplanesloop2:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#IP_PLANESIZE,d0
	dbra	d7,.setplanesloop2

	; Create copperlist
	; -----------------
	lea	ip_cl_data1,a0
	lea	ip_cl_data2,a1
	move.l	#$3401,d0
	move.l	#ip_planedata+3*IP_PLANEWIDTH,d1
	move.l	d1,d2
	add.l	#4*IP_PLANEWIDTH,d2
	move.l	#ip_copperdata,d3
	move.l	#ip_cl,d4
	move.l	#IP_PLANEHEIGHT-1,d7
.loop:	; Extra copper wait at $ffc1
	; --------------------------
	cmp.w	#$0001,d0
	bne.s	.d0ok
	move.l	#$ffd1fffe,(a0)+
	move.l	#$ffd1fffe,(a1)+
.d0ok:	; Copper wait
	; -----------
	move.w	d0,(a0)+
	move.w	d0,(a1)+
	move.w	#$fffe,(a0)+
	move.w	#$fffe,(a1)+
	; Reset bitplane 6 address
	; ------------------------
	move.w	#bpl6ptl,(a0)+
	move.w	#bpl6ptl,(a1)+
	move.w	d1,(a0)+
	move.w	d2,(a1)+
	move.w	#bpl6pth,(a0)+
	move.w	#bpl6pth,(a1)+
	swap	d1
	swap	d2
	move.w	d1,(a0)+
	move.w	d2,(a1)+
	swap	d1
	swap	d2
	; Set copper jump address
	; -----------------------
	move.w	#cop2lcl,(a0)+
	move.w	#cop2lcl,(a1)+
	move.w	d3,(a0)+
	move.w	d3,(a1)+
	move.w	#cop2lch,(a0)+
	move.w	#cop2lch,(a1)+
	swap	d3
	move.w	d3,(a0)+
	move.w	d3,(a1)+
	swap	d3
	; Set copper return address
	; -------------------------
	move.l	a0,d5
	move.l	a1,d6
	add.l	#12,d5
	add.l	#12,d6
	move.w	#cop1lcl,(a0)+
	move.w	#cop1lcl,(a1)+
	move.w	d5,(a0)+
	move.w	d6,(a1)+
	move.w	#cop1lch,(a0)+
	move.w	#cop1lch,(a1)+
	swap	d5
	swap	d6
	move.w	d5,(a0)+
	move.w	d6,(a1)+
	move.w	#copjmp2,(a0)+
	move.w	#copjmp2,(a1)+
	clr.w	(a0)+
	clr.w	(a1)+
	add.w	#$100,d0
	dbra	d7,.loop
	move.w	#bplcon0,(a0)+
	move.w	#bplcon0,(a1)+
	move.w	#1,(a0)+
	move.w	#1,(a1)+
	move.w	#cop1lcl,(a0)+
	move.w	#cop1lcl,(a1)+
	move.w	d4,(a0)+
	move.w	d4,(a1)+
	move.w	#cop1lch,(a0)+
	move.w	#cop1lch,(a1)+
	swap	d4
	move.w	d4,(a0)+
	move.w	d4,(a1)+
	swap	d4
	move.l	#$fffffffe,(a0)+
	move.l	#$fffffffe,(a1)+

	lea	table_fade+16,a0
	lea	ip_copperdata,a3
	moveq	#16-1,d6
.cpdt2:	sub.l	a4,a4
	moveq	#16-1,d7
.cpdt1:	lea	ip_palette1,a1
	lea	ip_palette2,a2
	move.w	a4,d4
	mulu	d6,d4
	lsr.w	#4,d4
	move.w	d4,a5

	move.w	#15,d5
	sub.w	d6,d5
	move.w	a4,d4
	mulu	d5,d4
	lsr.w	#4,d4
	move.w	d4,a6
		
	; Colors for bitplanes 1,3,5 while 2==1, 4==0
	; -------------------------------------------
	move.w	#$184,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$186,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$18c,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$18e,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1a4,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1a6,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1ac,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1ae,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	; Colors for bitplanes 1,3,5 while 2==0, 4==1
	; -------------------------------------------
	move.w	#$190,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$192,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$198,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$19a,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1b0,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1b2,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1b8,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1ba,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	; Colors for bitplanes 1,3,5 while 2==1, 4==1
	; -------------------------------------------
	move.w	#$194,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$196,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$19c,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$19e,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1b4,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1b6,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1bc,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	move.w	#$1be,(a3)+
	move.w	a5,d3
	move.w	(a1)+,d0
	bsr	multiplycolor
	move.w	d0,d4
	move.w	a6,d3
	move.w	(a2)+,d0
	bsr	multiplycolor
	add.w	d4,d0
	move.w	d0,(a3)+

	; Jump back to the original copperlist
	; ------------------------------------
	move.w	#copjmp1,(a3)+
	clr.w	(a3)+
	addq	#1,a4
	dbra	d7,.cpdt1
	dbra	d6,.cpdt2

	; Create copperlist pointers
	; --------------------------
	lea	ip_copperdata,a0
	lea	ip_copperptr,a1
	move.l	#16*16-1,d7
.cpptr:	move.l	a0,(a1)+
	lea	25*2*2(a0),a0
	dbra	d7,.cpptr

	; Decrunch bitmap
	; ---------------
	lea	ip_planes,a0
	lea	ip_image_stc,a1
	bsr	decrunch

	; Set copperlist
	; --------------
	move.l	#ip_cl_1,d0
	move.w	d0,ip_cl_cop1lcl
	swap	d0
	move.w	d0,ip_cl_cop1lch

	lea	sinus,a0
	lea	ip_sinus,a1
	move.w	#1024-1,d7
.sinus:	move.w	(a0)+,d0
	add.w	#$8000,d0
	lsr.w	#8,d0
	lsr.w	#3,d0
	move.w	d0,(a1)+
	dbra	d7,.sinus

	move.w	#$0544,ip_xsinus11
	move.w	#$018c,ip_xsinus12
	move.w	#$04dc,ip_xsinus21
	move.w	#$06e2,ip_xsinus22
	move.w	#$0624,ip_ysinus11
	move.w	#$0676,ip_ysinus12
	move.w	#$0170,ip_ysinus21
	move.w	#$039e,ip_ysinus22
	move.b	#1,ip_set
	rts

insaneplasma_go:
	move.l  #ip_cl,cop1lch+custom
	move.l	#insaneplasma_main,part_main
	move.l	#insaneplasma_vbi,part_vbi
	rts

insaneplasma_main:
	; X loop: create a row of funky chunky
	; ------------------------------------
	lea	ip_sinus,a0
	lea	ip_chunky,a1
	moveq	#2,d0
	add.w	ip_zoom,d0
	move.w	d0,a2
	mulu	#IP_PLANEWIDTH*8/2,d0
	move.w	d0,a3
	move.w	ip_xsinus11,d0
	move.w	ip_xsinus21,d1
	move.w	(a0,d0.w),d0
	move.w	(a0,d1.w),d1
	lsl.w	#4,d0
	lsl.w	#4,d1
	add.w	ip_xsinus12,d0
	add.w	ip_xsinus22,d1
	sub.w	a3,d0
	sub.w	a3,d1
	move.w	#2046,d2
	move.w	#IP_PLANEWIDTH-1,d7
.xloop:	rept	8
	and.w	d2,d0
	and.w	d2,d1
	move.w	(a0,d0.w),d6
	add.w	(a0,d1.w),d6
	lsr.w	#2,d6
	move.b	d6,(a1)+
	add.w	a2,d0
	add.w	a2,d1
	endr
	dbra	d7,.xloop

	; Y loop: set copper jump addresses
	; ---------------------------------
	moveq	#2,d0
	add.w	ip_zoom,d0
	move.w	d0,a3
	mulu	#IP_PLANEHEIGHT/2,d0
	move.w	d0,a4
	lea	ip_cl_data1,a1
	add.l	ip_copperadd,a1
	lea	ip_copperptr,a2
	move.w	ip_ysinus11,d0
	move.w	ip_ysinus21,d1
	move.w	(a0,d0.w),d0
	move.w	(a0,d1.w),d1
	lsl.w	#4,d0
	lsl.w	#4,d1
	add.w	ip_ysinus12,d0
	add.w	ip_ysinus22,d1
	sub.w	a4,d0
	sub.w	a4,d1
	move.w	#2046,d2
	move.w	#$3c,d3
	move.l	#IP_PLANEHEIGHT/16-1,d7
.yloop:	moveq	#16-1,d6
.iloop:	and.w	d2,d0
	and.w	d2,d1
	cmp.w	#$ffd1,(a1)
	bne.w	.nskip
	addq	#4,a1
.nskip:	move.w	(a0,d0.w),d5
	add.w	(a0,d1.w),d5
	and.w	d3,d5
	move.l	(a2,d5.w),d5
	move.w	d5,14(a1)
	swap	d5
	move.w	d5,18(a1)
	add.w	a3,d0
	add.w	a3,d1
	lea	32(a1),a1
	dbra	d6,.iloop
	lea	64(a2),a2
	dbra	d7,.yloop
	moveq	#8-1,d6
.rloop:	and.w	d2,d0
	and.w	d2,d1
	move.w	(a0,d0.w),d5
	add.w	(a0,d1.w),d5
	and.w	d3,d5
	move.l	(a2,d5.w),d5
	move.w	d5,14(a1)
	swap	d5
	move.w	d5,18(a1)
	add.w	a3,d0
	add.w	a3,d1
	lea	32(a1),a1
	dbra	d6,.rloop

	; Chunky to planar
	; ----------------
	lea	ip_chunky,a0
	lea	ip_planedata,a1
	add.l	ip_planeadd,a1
	move.l	#$33333333,d5
	move.l	#$55555555,a5
	move.l	#$00ff00ff,a6

	add.w	#IP_PLANEWIDTH,a1
	lea	IP_PLANEWIDTH*8(a0),a2

	move.l	(a0)+,d0		; Merge 4x1
	lsl.l	#4,d0
	or.l	(a0)+,d0
	move.l	(a0)+,d1
	lsl.l	#4,d1
	or.l	(a0)+,d1

	move.l	(a0)+,d2
	lsl.l	#4,d2
	or.l	(a0)+,d2
	move.l	(a0)+,d3
	lsl.l	#4,d3
	or.l	(a0)+,d3

	move.w	d2,d6			; Swap 16x2
	move.w	d3,d4
	move.w	d0,d2
	move.w	d1,d3
	swap	d2
	swap	d3
	move.w	d2,d0
	move.w	d3,d1
	move.w	d6,d2
	move.w	d4,d3

	move.l	d2,d6			; Swap 2x2
	move.l	d3,d7
	lsr.l	#2,d6
	lsr.l	#2,d7
	eor.l	d0,d6
	eor.l	d1,d7
	and.l	d5,d6
	and.l	d5,d7
	eor.l	d6,d0
	eor.l	d7,d1
	lsl.l	#2,d6
	lsl.l	#2,d7
	eor.l	d6,d2
	eor.l	d7,d3

	move.l	a6,d4			; Swap 8x1
	move.l	d1,d6
	move.l	d3,d7
	lsr.l	#8,d6
	lsr.l	#8,d7
	eor.l	d0,d6
	eor.l	d2,d7
	and.l	d4,d6
	and.l	d4,d7
	eor.l	d6,d0
	eor.l	d7,d2
	lsl.l	#8,d6
	lsl.l	#8,d7
	eor.l	d6,d1
	eor.l	d7,d3
	bra.s	.start

.x:	move.l	(a0)+,d0		; Merge 4x1
	lsl.l	#4,d0
	or.l	(a0)+,d0
	move.l	(a0)+,d1
	lsl.l	#4,d1
	or.l	(a0)+,d1

	move.l	(a0)+,d2
	lsl.l	#4,d2
	or.l	(a0)+,d2
	move.l	(a0)+,d3
	lsl.l	#4,d3
	or.l	(a0)+,d3

	move.l	d6,IP_PLANEWIDTH(a1)

	move.w	d2,d6			; Swap 16x2
	move.w	d3,d4
	move.w	d0,d2
	move.w	d1,d3
	swap	d2
	swap	d3
	move.w	d2,d0
	move.w	d3,d1
	move.w	d6,d2
	move.w	d4,d3

	move.l	d7,-IP_PLANEWIDTH(a1)

	move.l	d2,d6			; Swap 2x2
	move.l	d3,d7
	lsr.l	#2,d6
	lsr.l	#2,d7
	eor.l	d0,d6
	eor.l	d1,d7
	and.l	d5,d6
	and.l	d5,d7
	eor.l	d6,d0
	eor.l	d7,d1
	lsl.l	#2,d6
	lsl.l	#2,d7
	eor.l	d6,d2
	eor.l	d7,d3

	move.l	a3,IP_PLANEWIDTH*2(a1)

	move.l	a6,d4			; Swap 8x1
	move.l	d1,d6
	move.l	d3,d7
	lsr.l	#8,d6
	lsr.l	#8,d7
	eor.l	d0,d6
	eor.l	d2,d7
	and.l	d4,d6
	and.l	d4,d7
	eor.l	d6,d0
	eor.l	d7,d2
	lsl.l	#8,d6
	lsl.l	#8,d7
	eor.l	d6,d1
	eor.l	d7,d3

	move.l	a4,(a1)+
.start:	move.l	a5,d4			; Swap 1x1
	move.l	d1,d6
	move.l	d3,d7
	lsr.l	#1,d6
	lsr.l	#1,d7
	eor.l	d0,d6
	eor.l	d2,d7
	and.l	d4,d6
	and.l	d4,d7
	eor.l	d6,d0
	eor.l	d7,d2
	add.l	d6,d6
	add.l	d7,d7
	eor.l	d1,d6
	eor.l	d3,d7

	not.l	d0
	move.l	d0,a3
	move.l	d2,a4

	cmpa.l	a0,a2
	bne	.x

	move.l	d6,IP_PLANEWIDTH(a1)
	move.l	d7,-IP_PLANEWIDTH(a1)
	move.l	a3,IP_PLANEWIDTH*2(a1)
	move.l	a4,(a1)+

	move.b	#1,render
	rts

insaneplasma_vbi:
	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#120,d0
	bcs.s	.norml
	move.b	#7,ip_direction
	bra.s	.set
.norml:	and.w	#3,d0
	bne.w	.nset
	tst.b	ip_set
	bne.w	.set
	move.b	#1,ip_set
	add.b	#1,ip_direction
	and.b	#7,ip_direction
	bra.s	.set
.nset:	clr.b	ip_set
.set:	add.w	#42,ip_xsinus11
	sub.w	#58,ip_xsinus12
	sub.w	#32,ip_xsinus21
	add.w	#42,ip_xsinus22
	sub.w	#50,ip_ysinus11
	add.w	#28,ip_ysinus12
	add.w	#36,ip_ysinus21
	sub.w	#44,ip_ysinus22
	and.w	#2046,ip_xsinus11
	and.w	#2046,ip_xsinus12
	and.w	#2046,ip_xsinus21
	and.w	#2046,ip_xsinus22
	and.w	#2046,ip_ysinus11
	and.w	#2046,ip_ysinus12
	and.w	#2046,ip_ysinus21
	and.w	#2046,ip_ysinus22
	cmp.b	#3,ip_direction
	beq.s	.out
	cmp.b	#7,ip_direction
	beq.s	.in
	bra.s	.zoomd
.in:	tst.w	ip_zoom
	beq.s	.zoomd
	sub.w	#2,ip_zoom
	bra.s	.zoomd
.out:	add.w	#2,ip_zoom
.zoomd:

	tst.b	render
	beq.s	.vbiok

	move.l	#ip_cl_1,d0
	add.l	ip_copperadd,d0
	move.w	d0,ip_cl_cop1lcl
	swap	d0
	move.w	d0,ip_cl_cop1lch

	eor.l	#4*IP_PLANEWIDTH,ip_planeadd
	eor.l	#ip_cl_2-ip_cl_1,ip_copperadd
	clr.b	render
.vbiok:	rts

rotate:	; Clear memory
	; ------------
	lea	ro_cl,a0
	move.l	#ro_requirements_chipmem,d7
	bsr	clearmemory
	lea	ro_mulu_planewidth,a0
	move.l	#ro_requirements_fastmem,d7
	bsr	clearmemory

	; Start pre/post effect immediately
	; ---------------------------------
	move.b	#16,ro_frame
	move.l	#rotate_pre_vbi,part_vbi

	; Copy copperlist
	; ---------------
	lea	ro_ct,a0
	lea	ro_cl,a1
	move.w	#(ro_ct_data-ro_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Screen setup
	; ------------
	move.l	#ro_planes,d0
	lea	ro_cl_bpl1pth,a0
	moveq	#RO_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#RO_PLANEWIDTH,d0
	dbra	d7,.setplanesloop

	; Create delta table
	; ------------------
	lea	ro_waitdelta,a0
	moveq	#RO_SIZE/2,d0
	move.l	#(RO_SIZE/2)<<8,d1
	moveq	#RO_SIZE/2-1,d7
.delta:	move.l	d1,d2
	divu	d0,d2
	move.w	d2,(a0)+
	subq	#1,d0
	dbra	d7,.delta

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	ro_mulu_planewidth,a0
	move.l	#RO_PLANEHEIGHT-1,d7
.mulu1:	move.w	d0,(a0)+
	add.w	#RO_PLANES*RO_PLANEWIDTH,d0
	dbra	d7,.mulu1

	; Create scaling table
	; --------------------
	moveq	#0,d0
	lea	ro_mulu_256,a0
.mulu2:	moveq	#0,d1
.mulu3:	move.w	d0,d2
	move.w	d1,d3
	ext.w	d3
	muls	d3,d2
	asr.w	#7,d2
	cmp.b	#128,d2
	bne.s	.d2ok1
	move.b	#127,d2
.d2ok1:	add.b	#128,d2
	move.b	d2,(a0)+
	addq	#1,d1
	cmp.w	#256,d1
	bcs.s	.mulu3
	addq	#1,d0
	cmp.w	#128,d0
	bcs.s	.mulu2

	moveq	#-128,d0
	lea	ro_mulu_256-128*256,a0
.mulu4:	moveq	#0,d1
.mulu5:	move.w	d0,d2
	move.w	d1,d3
	ext.w	d3
	muls	d3,d2
	asr.w	#7,d2
	cmp.b	#128,d2
	bne.s	.d2ok2
	move.b	#127,d2
.d2ok2:	add.b	#128,d2
	move.b	d2,(a0)+
	addq	#1,d1
	cmp.w	#256,d1
	bcs.s	.mulu5
	addq	#1,d0
	bmi.s	.mulu4
	move.b	#8,ro_multiplier
	rts

rotate_go:
	clr.b	ro_frame
	move.l  #ro_cl,cop1lch+custom
	move.l	#rotate_main,part_main
	move.l	#rotate_vbi,part_vbi
	rts

rotate_main:
	lea	ro_planes,a0
	lea	RO_PLANES*RO_PLANEWIDTH*RO_SIZE*RO_RESOLUTION-(RO_PLANEWIDTH-RO_SIZE*RO_RESOLUTION/8)-(RO_RESOLUTION/8+2)(a0),a3
	lea	RO_PLANES*RO_PLANEWIDTH(a0),a0
	lea	RO_PLANES*RO_PLANEWIDTH*RO_SIZE*RO_RESOLUTION-(RO_PLANEWIDTH-RO_SIZE*RO_RESOLUTION/8)-2(a0),a1
	lea	RO_PLANES*RO_PLANEWIDTH+2(a0),a2
	lea	ro_waitdelta,a4
	lea	ro_wait,a5
	lea	custom,a6
	moveq	#0,d0
	move.b	ro_frame,d0
	move.l	#RO_SIZE/2-1,d7
ro_lp:	move.w	(a5)+,d1
	move.w	(a4)+,d2
	move.w	d1,d3
	lsr.w	#8,d3
	; Check if current frame is higher or equal than the frame to wait
	; ----------------------------------------------------------------
	cmp.w	d3,d0
	bcs.w	ro_nbl
	; Calculate new frame to wait
	; ---------------------------
	add.w	d2,d1
	move.w	d1,-2(a5)

	; Blit top half to up right
	; -------------------------
	waitb
	move.w	#(1<<ASHIFTSHIFT)|SRCA|DEST|ABC|ABNC|ANBC|ANBNC,bltcon0(a6)
	move.w	#0,bltcon1(a6)
	move.l	#$7ffffffe,bltafwm(a6)
	move.w	#RO_PLANEWIDTH-RO_SIZE*RO_RESOLUTION/8,bltamod(a6)
	move.w	#RO_PLANEWIDTH-RO_SIZE*RO_RESOLUTION/8,bltdmod(a6)
	move.l	a0,bltapth(a6)
	sub.w	#RO_PLANES*RO_PLANEWIDTH,a0
	move.l	a0,bltdpth(a6)
	add.w	#RO_PLANES*RO_PLANEWIDTH,a0
	move.w	#((RO_PLANES*RO_RESOLUTION)<<6)|(RO_SIZE*RO_RESOLUTION/16),bltsize(a6)

	; Blit bottom half to down left
	; -----------------------------
	waitb
	move.w	#(1<<ASHIFTSHIFT)|SRCA|DEST|ABC|ABNC|ANBC|ANBNC,bltcon0(a6)
	move.w	#BLITREVERSE,bltcon1(a6)
	move.l	#$fffe7fff,bltafwm(a6)
	move.w	#RO_PLANEWIDTH-RO_SIZE*RO_RESOLUTION/8,bltamod(a6)
	move.w	#RO_PLANEWIDTH-RO_SIZE*RO_RESOLUTION/8,bltdmod(a6)
	move.l	a1,bltapth(a6)
	add.w	#RO_PLANES*RO_PLANEWIDTH,a1
	move.l	a1,bltdpth(a6)
	sub.w	#RO_PLANES*RO_PLANEWIDTH,a1
	move.w	#((RO_PLANES*RO_RESOLUTION)<<6)|(RO_SIZE*RO_RESOLUTION/16),bltsize(a6)

	; Blit left half up left
	; ----------------------
	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	#(1<<BSHIFTSHIFT)|BLITREVERSE,bltcon1(a6)
	move.l	#$0000ffff,bltafwm(a6)
	move.w	#-1,bltadat(a6)
	move.w	#-RO_PLANEWIDTH-(RO_RESOLUTION/8+2),bltbmod(a6)
	move.w	#-RO_PLANEWIDTH-(RO_RESOLUTION/8+2),bltcmod(a6)
	move.w	#-RO_PLANEWIDTH-(RO_RESOLUTION/8+2),bltdmod(a6)
	move.l	a2,bltbpth(a6)
	sub.w	#RO_PLANES*RO_PLANEWIDTH,a2
	move.l	a2,bltcpth(a6)
	move.l	a2,bltdpth(a6)
	add.w	#RO_PLANES*RO_PLANEWIDTH,a2
	move.w	#((RO_PLANES*RO_SIZE*RO_RESOLUTION)<<6)|((RO_RESOLUTION/8+2)/2),bltsize(a6)

	; Blit right half down right
	; --------------------------
	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	#(1<<BSHIFTSHIFT),bltcon1(a6)
	move.l	#$0000ffff,bltafwm(a6)
	move.w	#-1,bltadat(a6)
	move.w	#-RO_PLANEWIDTH-(RO_RESOLUTION/8+2),bltbmod(a6)
	move.w	#-RO_PLANEWIDTH-(RO_RESOLUTION/8+2),bltcmod(a6)
	move.w	#-RO_PLANEWIDTH-(RO_RESOLUTION/8+2),bltdmod(a6)
	move.l	a3,bltbpth(a6)
	add.w	#RO_PLANES*RO_PLANEWIDTH,a3
	move.l	a3,bltcpth(a6)
	move.l	a3,bltdpth(a6)
	sub.w	#RO_PLANES*RO_PLANEWIDTH,a3
	move.w	#((RO_PLANES*RO_SIZE*RO_RESOLUTION)<<6)|((RO_RESOLUTION/8+2)/2),bltsize(a6)

ro_nbl:	lea	RO_PLANES*RO_RESOLUTION*RO_PLANEWIDTH(a0),a0
	lea	-RO_PLANES*RO_RESOLUTION*RO_PLANEWIDTH(a1),a1
	addq	#(RO_RESOLUTION/8),a2
	subq	#(RO_RESOLUTION/8),a3
	dbra	d7,ro_lp

	waitb
	; Draw some shit
	; --------------
	lea	sinus,a1
	lea	ro_mulu_planewidth,a2
	lea	ro_mulu_256,a3
	lea	ro_planes,a4
	add.w	ro_planes_add,a4
	move.w	ro_sinuspointer,d0
	move.w	d0,d1
	add.w	#512,d1
	move.b	ro_multiplier,d4
	lsl.w	#8,d4
	move.w	#2046,d6
	move.w	#RO_NUMPOINTS-1,d7
.scope:	moveq	#0,d2
	moveq	#0,d3
	and.w	d6,d0
	and.w	d6,d1
	move.b	(a1,d0.w),d4
	move.b	(a3,d4.w),d2
	move.b	(a1,d1.w),d4
	move.b	(a3,d4.w),d3
	add.w	d3,d3
	move.w	(a2,d3.w),d3
	move.w	d2,d5
	lsr.w	#3,d2
	add.w	d3,d2
	not.w	d5
	and.w	#7,d5
	bchg.b	d5,(a4,d2.w)
	add.w	#2048/RO_NUMPOINTS,d0
	add.w	#2048/RO_NUMPOINTS,d1
	add.w	#(256/RO_NUMPOINTS)<<8,d4
	dbra	d7,.scope

	eor.w	#RO_PLANEWIDTH,ro_planes_add
	add.b	#1,ro_frame
	and.b	#RO_SIZE/2-1,ro_frame
	bne.s	.frmok
	; Fix overflowing counters
	; ------------------------
	lea	ro_wait,a0
	move.l	#RO_SIZE/2-1,d7
.fixfr:	move.w	(a0)+,d0
	cmp.w	#(RO_SIZE/2)<<8,d0
	bcs	.nofix
	sub.w	#(RO_SIZE/2)<<8,d0
	move.w	d0,-2(a0)
.nofix:	dbra	d7,.fixfr
.frmok:	move.b	#1,render
	rts

rotate_pre_vbi:
	movem.l	d1-d2,-(sp)

	moveq	#0,d0
	move.b	ro_frame,d0
	bmi.s	.done
	lsl.w	#4,d0
	; Fade palette out
	; ----------------
	lea	table_fade,a0
	add.w	d0,a0
	move.w	cs_citycolor,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a0,d0.w),d0
	move.b	(a0,d1.w),d1
	move.b	(a0,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,ne_cl_palette+2
	sub.b	#1,ro_frame

.done:	movem.l	(sp)+,d1-d2
	rts

rotate_vbi:
	movem.l	d1-d2/d7/a1-a2,-(sp)

	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#3,d0
	bcs.s	.fade
	cmp.w	#116,d0
	bcs	.npal
.fade:	mulu	#6,d0
	addq	#6,d0
	sub.w	tp_wait,d0
	cmp.w	#16,d0
	bhi.s	.fdout
	lsl.w	#4,d0
	; Fade palette in
	; ---------------
	lea	ro_palette,a0
	lea	table_fade,a1
	add.w	d0,a1
	lea	ro_cl_palette+2,a2
	moveq	#4-1,d7
.fdpl1:	move.w	#$fff,d0
	sub.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	#$fff,d1
	sub.w	d0,d1
	move.w	d1,(a2)
	addq	#4,a2
	dbra	d7,.fdpl1
	bra.s	.npal

.fdout:	move.w	#119*6-1,d1
	sub.w	d0,d1
	bmi.s	.npal
	cmp.w	#16,d1
	bhi.s	.npal
	lsl.w	#4,d1
	; Fade palette out
	; ----------------
	lea	ro_palette,a0
	lea	table_fade,a1
	add.w	d1,a1
	lea	ro_cl_palette+2,a2
	moveq	#4-1,d7
.fdpl2:	move.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,(a2)
	addq	#4,a2
	dbra	d7,.fdpl2

.npal:	add.w	#2,ro_sinuspointer
	and.w	#2046,ro_sinuspointer
	add.b	#2,ro_multiplier
	cmp.b	#2,ro_multiplier
	bge.s	.multo
	cmp.b	#-2,ro_multiplier
	bls.s	.multo
	move.b	#2,ro_multiplier
.multo:	tst.b	render
	beq.s	.vbiok
	clr.b	render
	clr.w	ne_cl_palette+2
.vbiok:	movem.l	(sp)+,d1-d2/d7/a1-a2
	rts

starwarsscroller:
	; Clear memory
	; ------------
	lea	sw_cl,a0
	move.l	#sw_requirements_chipmem,d7
	bsr	clearmemory
	lea	sw_mulu_planewidth,a0
	move.l	#sw_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	sw_ct,a0
	lea	sw_cl,a1
	move.w	#(sw_ct_data-sw_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Decrunch bitmap
	; ---------------
	lea	sw_bitmap,a0
	lea	sw_bitmap_stc,a1
	bsr	decrunch

	; Screen setup
	; ------------
	move.l	#sw_planes,d0
	lea	sw_cl_bpl1pth,a0
	moveq	#SW_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#SW_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Copy the ordered table to the star wars scroller table
	; ------------------------------------------------------
	lea	table_order,a0
	lea	sw_offsets,a1
	move.l	#16-1,d7
.swtf:	move.l	(a0)+,(a1)+
	move.l	(a0)+,60(a1)
	move.l	(a0)+,124(a1)
	move.l	(a0)+,188(a1)
	dbra	d7,.swtf

	; Remove pixels from the star wars scroller table
	; -----------------------------------------------
	lea	sw_offsets,a0
	move.l	#255-1,d7
.swt:	move.b	(a0)+,d0
	move.l	a0,a1
	move.l	d7,d6
	cmp.b	#128,d0
	bcs.s	.swtl
.swtr:
.swtrl:	move.b	(a1)+,d1
	cmp.b	d0,d1
	bcs.s	.swtrn
	subq	#1,d1
	move.b	d1,-1(a1)
.swtrn:	dbra	d6,.swtrl
	bra.s	.swtnx
.swtl:
.swtll:	move.b	(a1)+,d1
	cmp.b	d0,d1
	bhi.s	.swtln
	addq	#1,d1
	move.b	d1,-1(a1)
.swtln:	dbra	d6,.swtll
.swtnx:	dbra	d7,.swt

	; Create a Y height table for the Star Wars scroller
	; --------------------------------------------------
	lea	table_order,a0
	lea	sw_heights,a1
	move.l	#$100,d0
	moveq	#0,d1
	moveq	#0,d2
.swhlp:	move.w	d0,d3
	move.b	(a0,d1.w),d4
	cmp.b	d4,d3
	bls	.swlow
	add.w	#$100,d3
.swlow:	lsr.w	#8,d3
	move.b	d3,(a1)+
	add.w	#SW_ANGLE,d0
	addq	#1,d1
	and.w	#255,d1
	add.w	d3,d2
	cmp.w	#SW_HEIGHT,d2
	bcs	.swhlp
	sub.l	#sw_heights,a1
	move.w	a1,sw_rows

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	sw_mulu_planewidth,a0
	move.l	#SW_HEIGHT-1,d7
.mulu:	move.w	d0,(a0)+
	add.w	#SW_PLANEWIDTH,d0
	dbra	d7,.mulu

	; Create copperlist
	; -----------------
	lea	sw_cl_data,a0
	lea	sw_heights,a1
	lea	sw_mulu_planewidth,a2
	move.w	#$a8,d0
	move.w	sw_rows,d7
	add.w	d7,a1
	lsr.w	d7
	move.w	d7,d1
	lsr.w	d1
	sub.w	d1,d0
	lsl.w	#8,d0
	or.w	#1,d0
	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	move.w	#bplcon0,(a0)+
	move.w	sw_cl_bplcon0+2,(a0)+
	move.w	#$180,(a0)+
	move.w	#$111,(a0)+
	move.w	#$e00,d2
	divu	d7,d2
	move.w	#$200,d1
	moveq	#0,d3
	subq	#1,d7
.swcop:	move.b	-(a1),d3
	add.b	-(a1),d3
	add.w	d3,d3
	move.w	(a2,d3.w),d4
	sub.w	#SW_PLANEWIDTH,d4
	move.w	#bpl1mod,(a0)+
	move.w	d4,(a0)+
	add.w	d2,d1
	move.w	d1,d4
	and.w	#$f00,d4
	move.w	d4,d5
	lsr.w	#4,d5
	or.w	d5,d4
	or.w	#1,d4
	move.w	#$182,(a0)+
	move.w	d4,(a0)+
	add.w	#$100,d0
	cmp.w	#1,d0
	bne.s	.swcnx
	move.l	#$ffd1fffe,(a0)+
.swcnx:	move.w	d0,(a0)+
	move.w	#$fffe,(a0)+
	dbra	d7,.swcop
	move.w	#bplcon0,(a0)+
	clr.w	(a0)+
	move.w	#$180,(a0)+
	move.w	#$000,(a0)+
	move.l	#$fffffffe,(a0)+
	rts

starwarsscroller_go:
	move.l  #sw_cl,cop1lch+custom
	move.l	#starwarsscroller_main,part_main
	move.l	#starwarsscroller_vbi,part_vbi
	rts

starwarsscroller_main:
	lea	sw_heights,a0
	add.w	sw_rows,a0
	lea	sw_offsets,a1
	lea	sw_planes,a2
	lea	SW_PLANEWIDTH(a2),a3
	lea	sw_mulu_planewidth,a4
	lea	custom,a6

	; Blit the rows upwards as is (half of it using the blitter)
	; ----------------------------------------------------------
	waitb
	move.w	#SRCA|DEST|ABC|ABNC|ANBC|ANBNC,bltcon0(a6)
	move.w	#0,bltcon1(a6)
	move.l	#-1,bltafwm(a6)
	move.w	#SW_PLANEWIDTH-SW_WIDTH,bltamod(a6)
	move.w	#SW_PLANEWIDTH-SW_WIDTH,bltdmod(a6)
	move.l	a3,bltapth(a6)
	move.l	a2,bltdpth(a6)
	move.w	#((SW_HEIGHT-1)<<6)|(SW_WIDTH/2),bltsize(a6)

	moveq	#0,d6
	move.w	sw_rows,d7
	waitb
	move.w	#-1,bltadat(a6)
sw_lp:	; Current height
	; --------------
	move.b	-(a0),d6
	move.w	d6,d5
	lsl.w	#6,d5

	; Get destination pixel to remove
	; -------------------------------
	moveq	#0,d0
	move.b	(a1,d7.w),d0

	; Check whether the pixel is on the left or on the right half
	; -----------------------------------------------------------
	cmp.b	#128,d0
	bcs.w	sw_l

	; Shift the remaining part of the row: width in words
	; ---------------------------------------------------
	move.w	#255,d1
	sub.b	d0,d1
	lsr.w	#4,d1
	addq	#1,d1
	; Modulo in bytes
	; ---------------
	move.w	#SW_PLANEWIDTH,d2
	sub.w	d1,d2
	sub.w	d1,d2

	; How many pixels of the original are preserved
	; ---------------------------------------------
	and.w	#15,d0
	
	; Calculate blitter mask
	; --------------------
	move.l	#$fffeffff,d3
	lsr.w	d0,d3

	lea	(SW_PLANEWIDTH-2)(a2),a5
	or.w	#(1<<6),d1
	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	#(1<<BSHIFTSHIFT)|BLITREVERSE,bltcon1(a6)
	move.l	d3,bltafwm(a6)
	move.w	d2,bltbmod(a6)
	move.w	d2,bltcmod(a6)
	move.w	d2,bltdmod(a6)
	move.l	a5,bltbpth(a6)
	move.l	a5,bltcpth(a6)
	move.l	a5,bltdpth(a6)
	move.w	d1,bltsize(a6)
	bra.w	sw_nxt

sw_l:	; Shift the remaining part of the row: width in words
	; ---------------------------------------------------
	move.w	d0,d1
	lsr.w	#4,d1
	addq	#1,d1
	; Modulo in bytes
	; ---------------
	move.w	#SW_PLANEWIDTH,d2
	sub.w	d1,d2
	sub.w	d1,d2

	; How many pixels of the original are preserved
	; ---------------------------------------------
	and.w	#15,d0
	sub.w	#15,d0
	neg.w	d0

	; Calculate blitter mask
	; ----------------------
	move.l	#$ffffffff,d3
	lsl.w	d0,d3

	or.w	#(1<<6),d1
	waitb
	move.w	#SRCB|SRCC|DEST|ABC|ABNC|NABC|NANBC,bltcon0(a6)
	move.w	#(1<<BSHIFTSHIFT),bltcon1(a6)
	move.l	d3,bltafwm(a6)
	move.w	d2,bltbmod(a6)
	move.w	d2,bltcmod(a6)
	move.w	d2,bltdmod(a6)
	move.l	a2,bltbpth(a6)
	move.l	a2,bltcpth(a6)
	move.l	a2,bltdpth(a6)
	move.w	d1,bltsize(a6)
	waitb
sw_nxt:	subq	#1,d7
	move.w	d6,d0
	add.w	d6,d0
	move.w	(a4,d0.w),d0
	add.w	d0,a2
	add.w	d0,a3
	cmp.l	#sw_heights,a0
	bne	sw_lp

sw_dn:	; Write new material to the bottom end if needed
	; ----------------------------------------------
	cmp.l	#SW_BITMAP_HEIGHT*SW_WIDTH,sw_y
	beq	sw_wrd
	waitb
	lea	sw_bitmap,a0
	add.l	sw_y,a0
	lea	sw_planes+(SW_HEIGHT-1)*SW_PLANEWIDTH,a1
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	add.l	#SW_WIDTH,sw_y

sw_wrd:	move.b	#1,render
	rts

starwarsscroller_vbi:
	tst.b	render
	beq.s	.vbiok
	clr.b	render
.vbiok:	rts

stencilvector:
	; Clear memory
	; ------------
	lea	sv_cl,a0
	move.l	#sv_requirements_chipmem,d7
	bsr	clearmemory
	lea	sv_planes_add,a0
	move.l	#sv_requirements_fastmem,d7
	bsr	clearmemory

	; Start pre/post effect immediately
	; ---------------------------------
	move.b	#1,sv_pre_set
	move.b	#1,sv_pre_wait
	move.w	#17,sv_pre_fader
	move.l	#stencilvector_pre_vbi,part_vbi

	; Copy copperlist
	; ---------------
	lea	sv_ct,a0
	lea	sv_cl,a1
	move.w	#(sv_ct_data-sv_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Screen setup
	; ------------
	move.l	#sv_planes,d0
	lea	sv_cl_bpl1pth,a0
	moveq	#SV_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#SV_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Reset boundary values
	; ---------------------
	lea	sv_boundaries,a0
	move.w	#SV_PLANEWIDTH*8,(a0)
	clr.w	2(a0)
	move.w	#SV_PLANEHEIGHT,4(a0)
	clr.w	6(a0)

	; Calculate square root table
	; ---------------------------
	lea	sv_table_sqrt,a0
	moveq	#0,d3
	move.w	#257-1,d7
.sqrtl:	move.l	d3,d1
	; Calculate square root
	; ---------------------	
	moveq	#-1,d2
	clr.w	d2
	cmp.l	d2,d1
	bls.s	.sqrt0
	move.l	#$00010000,d2
	bra.s	.sqrt3
.sqrt0:	moveq	#31,d0
.sqrt1:	bclr	d0,d2
	lsr.l	d2
	cmp.l	d2,d1
	bls.s	.sqrt2
	sub.l	d2,d1
	bset	d0,d2
.sqrt2:	subq	#2,d0
	bcc.s	.sqrt1
	lsr.l	d2
.sqrt3:	move.b	d2,(a0)+
	add.l	#$80,d3
	dbra	d7,.sqrtl

	; Render ordered ball to be used as a filling pattern
	; ---------------------------------------------------
	lea	table_order,a0
	lea	sv_table_sqrt,a1
	lea	sv_stencil,a2
	lea	2*SV_STENCIL_SIZE(a2),a3
	moveq	#0,d4
	moveq	#0,d5
	moveq	#0,d6
	moveq	#0,d7
	move.w	#SV_STENCIL_HEIGHT,a5
.yloop:	move.w	#SV_STENCIL_WIDTH*8,a4
.xloop:	; Calculate distance^2 from origin: |x^2 + y^2|
	; ---------------------------------------------
	move.w	a5,d1
	sub.w	#SV_STENCIL_HEIGHT/2,d1
	bpl.s	.ypos
	neg.w	d1
.ypos:	mulu	d1,d1
	move.w	a4,d0
	sub.w	#SV_STENCIL_WIDTH*8/2,d0
	bpl.s	.xpos
	neg.w	d0
.xpos:	mulu	d0,d0
	add.l	d0,d1

	lsr.l	#7,d1
	moveq	#0,d2
	move.b	(a1,d1.w),d2

	; Inverse
	; -------
	move.w	#SV_STENCIL_HEIGHT/2,d0
	sub.w	d2,d0
	bpl.s	.zpos
	moveq	#0,d0
.zpos:	; Expand distance from 0-128 to 0-256
	; -----------------------------------
	add.w	d0,d0
	; Base color (0-16)
	; -----------------
	move.w	d0,d1
	lsr.w	#4,d1
	; Use the rest of the bits for ordered dithering comparison and scale
	; -------------------------------------------------------------------
	and.w	#15,d0
	lsl.w	#4,d0
	; Get the current ordered dithering table element
	; -----------------------------------------------
	move.w	a5,d2
	and.w	#15,d2
	lsl.w	#4,d2
	move.w	a4,d3
	and.w	#15,d3
	add.w	d3,d2
	moveq	#0,d3
	move.b	(a0,d2.w),d3
	; Ordered dithering
	; -----------------
	cmp.w	d3,d0
	ble.s	.nodit
	addq	#1,d1
.nodit:	; No overflows
	; ------------
	cmp.w	#16,d1
	bcs.s	.colok
	move.w	#15,d1
.colok:	; Chunky to planar... slowest ever but sufficient here
	; ----------------------------------------------------
	lsr.b	d1
	addx.l	d4,d4
	lsr.b	d1
	addx.l	d5,d5
	lsr.b	d1
	addx.l	d6,d6
	lsr.b	d1
	addx.l	d7,d7
	subq	#1,a4
	move.w	a4,d1
	; Write to planes every 32nd pixel
	; --------------------------------
	and.w	#31,d1
	bne.s	.nowr
	move.l	d4,(a2)+
	move.l	d5,SV_STENCIL_SIZE-4(a2)
	move.l	d6,(a3)+
	move.l	d7,SV_STENCIL_SIZE-4(a3)
.nowr:	cmp.w	#0,a4
	bne	.xloop
	subq	#1,a5
	cmp.w	#0,a5
	bne	.yloop

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	sv_mulu_planewidth,a0
	move.w	#SV_STENCIL_HEIGHT-1,d7
.mulu:	move.w	d0,(a0)+
	add.w	#SV_PLANEWIDTH,d0
	dbra	d7,.mulu

	; Create octants table
	; --------------------
	move.b	#0|ONEDOT|LINEMODE,sv_boundaries-1	;y1<y2, x1<x2, dx<dy = okt6
	move.b	#16|ONEDOT|LINEMODE,sv_boundaries-2	;y1<y2, x1<x2, dx>dy = okt7
	move.b	#8|ONEDOT|LINEMODE,sv_boundaries-3	;y1<y2, x1>x2, dx<dy = okt5
	move.b	#20|ONEDOT|LINEMODE,sv_boundaries-4	;y1<y2, x1>x2, dx>dy = okt4

	; Reset angles
	; ------------
	move.l	#$00000200,d0
	lea	sv_angles,a0
	move.l	d0,(a0)+
	move.l	d0,(a0)+
	move.l	d0,(a0)+

	; Calculate face normals
	; ----------------------
	lea	sv_faces_list,a0
	lea	sv_coordinates_list+2,a1
	move.w	(a0)+,d7
	subq	#1,d7
.nrml1:	move.l	(a0)+,a2
	move.l	(a1)+,a3
	addq	#2,a3
	move.w	(a2)+,d6
	move.w	(a2)+,d5
	subq	#1,d6
.nrml2:	; Get pointers for three successive coordinates from the face
	; -----------------------------------------------------------
	move.w	18(a2),d0
	move.w	20(a2),d1
	move.w	22(a2),d2
	lsl.w	#3,d0
	lsl.w	#3,d1
	lsl.w	#3,d2

	; A = y1(z2 - z3)
	; ---------------
	move.w	4(a3,d1.w),d3
	sub.w	4(a3,d2.w),d3
	muls	2(a3,d0.w),d3
	; + y2(z3 - z1)
	; -------------
	move.w	4(a3,d2.w),d4
	sub.w	4(a3,d0.w),d4
	muls	2(a3,d1.w),d4
	add.w	d4,d3
	; + y3(z1 - z2)
	; -------------
	move.w	4(a3,d0.w),d4
	sub.w	4(a3,d1.w),d4
	muls	2(a3,d2.w),d4
	add.w	d4,d3
	asr.w	#4,d3
	move.w	d3,(a2)

	; B = z1(x2 - x3)
	; ---------------
	move.w	(a3,d1.w),d3
	sub.w	(a3,d2.w),d3
	muls	4(a3,d0.w),d3
	; + z2(x3 - x1)
	; -------------
	move.w	(a3,d2.w),d4
	sub.w	(a3,d0.w),d4
	muls	4(a3,d1.w),d4
	add.w	d4,d3
	; + z3(x1 - x2)
	; -------------
	move.w	(a3,d0.w),d4
	sub.w	(a3,d1.w),d4
	muls	4(a3,d2.w),d4
	add.w	d4,d3
	asr.w	#4,d3
	move.w	d3,2(a2)

	; C = x1(y2 - y3)
	; ---------------
	move.w	2(a3,d1.w),d3
	sub.w	2(a3,d2.w),d3
	muls	(a3,d0.w),d3
	; + x2(y3 - y1)
	; -------------
	move.w	2(a3,d2.w),d4
	sub.w	2(a3,d0.w),d4
	muls	(a3,d1.w),d4
	add.w	d4,d3
	; + x3(y1 - y2)
	; -------------
	move.w	2(a3,d0.w),d4
	sub.w	2(a3,d1.w),d4
	muls	(a3,d2.w),d4
	add.w	d4,d3
	asr.w	#4,d3
	move.w	d3,4(a2)

	; Normalize vector
	; ----------------
	muls	d3,d3
	move.w	(a2),d1
	muls	d1,d1
	add.w	d3,d1
	move.w	2(a2),d3
	muls	d3,d3
	add.w	d3,d1
	bpl.s	.lpos
	neg.w	d1
.lpos:	; Calculate square root
	; ---------------------	
	moveq	#-1,d2
	clr.w	d2
	cmp.l	d2,d1
	bls.w	.sqrt4
	move.l	#$00010000,d2
	bra.w	.sqrt7
.sqrt4:	moveq	#31,d0
.sqrt5:	bclr	d0,d2
	lsr.l	d2
	cmp.l	d2,d1
	bls.s	.sqrt6
	sub.l	d2,d1
	bset	d0,d2
.sqrt6:	subq	#2,d0
	bcc.s	.sqrt5
	lsr.l	d2
.sqrt7:	move.w	(a2),d3
	muls	d5,d3
	divs	d2,d3
	move.w	d3,(a2)
	move.w	2(a2),d3
	muls	d5,d3
	divs	d2,d3
	move.w	d3,2(a2)
	move.w	4(a2),d3
	muls	d5,d3
	divs	d2,d3
	move.w	d3,4(a2)

	move.w	16(a2),d3
	add.w	d3,d3
	lea	20(a2,d3.w),a2
	dbra	d6,.nrml2
	dbra	d7,.nrml1

	; Calculate x*y values
	; --------------------
	lea	sv_coordinates_list,a0
	move.w	(a0)+,d7
	subq	#1,d7
.xylp1:	move.l	(a0)+,a1
	move.w	(a1)+,d6
	subq	#1,d6
.xylp2:	move.w	(a1)+,d0
	move.w	(a1)+,d1
	addq	#2,a1
	muls	d1,d0
	move.w	d0,(a1)+
	dbra	d6,.xylp2
	dbra	d7,.xylp1

	; Calculate x*y values for normals
	; --------------------------------
	lea	sv_faces_list,a0
	move.w	(a0)+,d7
	subq	#1,d7
.xylp3:	move.l	(a0)+,a1
	move.w	(a1),d6
	addq	#4,a1
	subq	#1,d6
.xylp4:	move.w	(a1),d0
	move.w	2(a1),d1
	muls	d1,d0
	move.w	d0,6(a1)
	move.w	16(a1),d0
	add.w	d0,d0
	lea	20(a1,d0.w),a1
	dbra	d6,.xylp4
	dbra	d7,.xylp3

	; Set an object to begin with
	; ---------------------------
	move.l	sv_coordinates_list+2,sv_coordinates
	move.l	sv_faces_list+2,sv_faces
	move.w	#SV_DISTANCE_MAX,sv_distance

	moveq	#0,d0
	lea	sv_cl_palette+2,a0
	moveq	#16-1,d7
.pah:	move.w	d0,(a0)
	add.w	#$111,d0
	addq	#4,a0
	dbra	d7,.pah

	move.l	#$000c000c,sv_angles_add
	move.l	#$000a000a,sv_angles_add+4
	move.l	#$00080008,sv_angles_add+8
	rts

stencilvector_go:
	clr.b	sv_object_change
	move.l  #sv_cl,cop1lch+custom
	move.l	#stencilvector_main,part_main
	move.l	#stencilvector_vbi,part_vbi
	rts

stencilvector_main:
	lea	custom,a6
	; Use CPU to clear?
	; -----------------
	move.l	sv_faces,a0
	cmp.w	#10,(a0)
	bcs	sv_cpu
	; Clear destination bitplane
	; --------------------------
	waitb
	; Notice that the following blits use these values as well
	; --------------------------------------------------------
	move.l	#-1,bltafwm(a6)
	move.w	#0,bltcon1(a6)
	move.w	#DEST,bltcon0(a6)
	move.w	#12,bltdmod(a6)
	move.l	#sv_planes,d0
	add.l	sv_planes_add,d0
	addq	#6,d0
	move.l	d0,bltdpth(a6)
	move.w	#((SV_PLANES*SV_PLANEHEIGHT)<<6)|(SV_PLANEWIDTH/2-6),bltsize(a6)
	bra	sv_cld

sv_cpu:	; Clear destination bitplane
	; --------------------------
	move.l	#sv_planes+6,d0
	add.l	sv_planes_add,d0
	moveq	#0,d1
	waitb
	; Notice that the following blits use these values as well
	; --------------------------------------------------------
	move.l	#-1,bltafwm(a6)
	move.w	d1,bltcon1(a6)
	move.w	#DEST,bltcon0(a6)
	move.w	#12,bltdmod(a6)
	move.l	d0,bltdpth(a6)
	move.w	#((SV_PLANES*SV_PLANEHEIGHT*6/8)<<6)|(SV_PLANEWIDTH/2-6),bltsize(a6)

	; Clear part of the screen using the CPU
	; --------------------------------------
	move.l	d0,a0
	add.w	#4*SV_PLANESIZE,a0
	moveq	#0,d2
	moveq	#0,d3
	moveq	#0,d4
	moveq	#0,d5
	moveq	#12,d6
	move.l	#(SV_PLANES*SV_PLANEHEIGHT*2/8/16)-1,d7
.clr:	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	sub.w	d6,a0
	movem.l	d1-d5,-(a0)
	dbra	d7,.clr

sv_cld:	; Precalculate sin*cos constants; range +-$3fff
	; ---------------------------------------------
	lea	sinus,a0
	lea	sv_angles,a1
	lea	sv_rotate,a2
	; xx = cos(ax)*cos(ay)
	; xy = sin(ax)*cos(ay)
	; xz = sin(ay)
	; ------------
	move.w	SV_YANGLECOS(a1),d0
	move.w	SV_YANGLESIN(a1),d2
	move.w	SV_XANGLECOS(a1),d3
	move.w	SV_XANGLESIN(a1),d4
	move.w	(a0,d0.w),d0
	move.w	d0,d1
	move.w	(a0,d2.w),d2
	move.w	(a0,d3.w),d3
	move.w	(a0,d4.w),d4
	muls	d3,d0
	swap	d0
	muls	d4,d1
	swap	d1
	asr.w	d2
	move.w	d0,SV_XX(a2)
	move.w	d1,SV_XY(a2)
	move.w	d2,SV_XZ(a2)
	
	; yx = sin(ax)*cos(az) + cos(ax)*sin(ay)*sin(az)
	; yy = -cos(ax)*cos(az) + sin(ax)*sin(ay)*sin(az)
	; yz = -cos(ay)*sin(az)
	; ---------------------
	move.w	SV_ZANGLECOS(a1),d0
	move.w	SV_ZANGLESIN(a1),d2
	move.w	SV_XANGLESIN(a1),d3
	move.w	SV_XANGLECOS(a1),d4
	move.w	SV_YANGLECOS(a1),d5
	move.w	(a0,d0.w),d0
	move.w	d0,d1
	move.w	(a0,d2.w),d2
	move.w	(a0,d3.w),d3
	move.w	(a0,d4.w),d4
	move.w	(a0,d5.w),d5
	muls	d3,d0
	swap	d0
	muls	d4,d1
	swap	d1
	neg.w	d1
	muls	d5,d2
	swap	d2
	neg.w	d2
	move.w	SV_YANGLESIN(a1),d3
	move.w	SV_ZANGLESIN(a1),d4
	move.w	(a0,d3.w),d3
	move.w	(a0,d4.w),d4
	muls	d4,d3
	swap	d3
	add.w	d3,d3
	move.w	SV_XANGLECOS(a1),d4
	move.w	SV_XANGLESIN(a1),d5
	move.w	(a0,d4.w),d4
	move.w	(a0,d5.w),d5
	muls	d3,d4
	swap	d4
	muls	d3,d5
	swap	d5
	add.w	d4,d0
	add.w	d5,d1
	move.w	d0,SV_YX(a2)
	move.w	d1,SV_YY(a2)
	move.w	d2,SV_YZ(a2)

	; zx = sin(ax)*sin(az) - cos(ax)*sin(ay)*cos(az)
	; zy = -cos(ax)*sin(az) - sin(ax)*sin(ay)*cos(az)
	; zz = cos(ay)*cos(az)
	; --------------------
	move.w	SV_ZANGLESIN(a1),d0
	move.w	SV_ZANGLECOS(a1),d2
	move.w	SV_XANGLESIN(a1),d3
	move.w	SV_XANGLECOS(a1),d4
	move.w	SV_YANGLECOS(a1),d5
	move.w	(a0,d0.w),d0
	move.w	d0,d1
	move.w	(a0,d2.w),d2
	move.w	(a0,d3.w),d3
	move.w	(a0,d4.w),d4
	move.w	(a0,d5.w),d5
	muls	d3,d0
	swap	d0
	muls	d4,d1
	swap	d1
	neg.w	d1
	muls	d5,d2
	swap	d2
	move.w	SV_YANGLESIN(a1),d3
	move.w	SV_ZANGLECOS(a1),d4
	move.w	(a0,d3.w),d3
	move.w	(a0,d4.w),d4
	muls	d4,d3
	swap	d3
	add.w	d3,d3
	move.w	SV_XANGLECOS(a1),d4
	move.w	SV_XANGLESIN(a1),d5
	move.w	(a0,d4.w),d4
	move.w	(a0,d5.w),d5
	muls	d3,d4
	swap	d4
	muls	d3,d5
	swap	d5
	sub.w	d4,d0
	sub.w	d5,d1
	move.w	d0,SV_ZX(a2)
	move.w	d1,SV_ZY(a2)
	move.w	d2,SV_ZZ(a2)

	; xxxy = xx*xy
	; yxyy = yx*yy
	; zxzy = zx*zy
	; ------------
	move.w	SV_XX(a2),d0
	move.w	SV_XY(a2),d1
	muls	d1,d0
	move.l	d0,SV_XXXY(a2)
	move.w	SV_YX(a2),d0
	move.w	SV_YY(a2),d1
	muls	d1,d0
	move.l	d0,SV_YXYY(a2)
	move.w	SV_ZX(a2),d0
	move.w	SV_ZY(a2),d1
	muls	d1,d0
	move.l	d0,SV_ZXZY(a2)

	; Rotate coordinates
	; ------------------
	move.l	sv_coordinates,a0
	lea	sv_rotate,a1
	lea	sv_rotated,a2
	move.w	sv_distance,a3
	move.w	#SV_PLANEWIDTH*8/2,a4
	move.w	#SV_PLANEHEIGHT/2,a5
	move.w	(a0)+,d7
	subq	#1,d7
.coord:	move.w	(a0)+,d4
	move.w	(a0)+,d5
	move.w	(a0)+,d6
	move.w	(a0)+,d0
	ext.l	d0
	move.l	d0,a6

	; x' = (xx + y)(xy + x) + z*xz - (xxxy + x*y)
	; -------------------------------------------
	move.w	d4,d0
	add.w	SV_XY(a1),d0
	move.w	d5,d1
	add.w	SV_XX(a1),d1
	muls	d1,d0
	move.w	d6,d1
	muls	SV_XZ(a1),d1
	add.l	d1,d0
	sub.l	SV_XXXY(a1),d0
	sub.l	a6,d0
	; y' = (yx + y)(yy + x) + z*yz - (yxyy + x*y)
	; -------------------------------------------
	move.w	d4,d1
	add.w	SV_YY(a1),d1
	move.w	d5,d2
	add.w	SV_YX(a1),d2
	muls	d2,d1
	move.w	d6,d2
	muls	SV_YZ(a1),d2
	add.l	d2,d1
	sub.l	SV_YXYY(a1),d1
	sub.l	a6,d1
	; z' = (zx + y)(zy + x) + z*zz - (zxzy + x*y)
	; -------------------------------------------
	move.w	d4,d2
	add.w	SV_ZY(a1),d2
	move.w	d5,d3
	add.w	SV_ZX(a1),d3
	muls	d3,d2
	move.w	d6,d3
	muls	SV_ZZ(a1),d3
	add.l	d3,d2
	sub.l	SV_ZXZY(a1),d2
	sub.l	a6,d2

	; Projection
	; ----------
	asr.l	#5,d0
	asr.l	#5,d1
	; Use #4 for a wider angle (or fish eye)
	; --------------------------------------
	asl.l	#3,d2
	swap	d2
	sub.w	a3,d2
	; Store Z coordinate
	; ------------------
	move.w	d2,4(a2)
	divs	d2,d0
	divs	d2,d1
	add.w	a4,d0
	add.w	a5,d1
	; Store projected X and Y
	; -----------------------
	move.w	d0,(a2)+
	move.w	d1,(a2)+
	addq	#4,a2
	dbra	d7,.coord

	; Rotate face normals
	; -------------------
	move.l	sv_faces,a0
	move.w	(a0),d7
	addq	#4,a0
	subq	#1,d7
.norml:	move.w	(a0)+,d4
	move.w	(a0)+,d5
	move.w	(a0)+,d6
	move.w	(a0)+,d0
	ext.l	d0
	move.l	d0,a6

	; x' = (xx + y)(xy + x) + z*xz - (xxxy + x*y)
	; -------------------------------------------
	move.w	d4,d0
	add.w	SV_XY(a1),d0
	move.w	d5,d1
	add.w	SV_XX(a1),d1
	muls	d1,d0
	move.w	d6,d1
	muls	SV_XZ(a1),d1
	add.l	d1,d0
	sub.l	SV_XXXY(a1),d0
	sub.l	a6,d0
	; y' = (yx + y)(yy + x) + z*yz - (yxyy + x*y)
	; -------------------------------------------
	move.w	d4,d1
	add.w	SV_YY(a1),d1
	move.w	d5,d2
	add.w	SV_YX(a1),d2
	muls	d2,d1
	move.w	d6,d2
	muls	SV_YZ(a1),d2
	add.l	d2,d1
	sub.l	SV_YXYY(a1),d1
	sub.l	a6,d1
	; z' = (zx + y)(zy + x) + z*zz - (zxzy + x*y)
	; -------------------------------------------
	move.w	d4,d2
	add.w	SV_ZY(a1),d2
	move.w	d5,d3
	add.w	SV_ZX(a1),d3
	muls	d3,d2
	move.w	d6,d3
	muls	SV_ZZ(a1),d3
	add.l	d3,d2
	sub.l	SV_ZXZY(a1),d2
	sub.l	a6,d2

	asr.l	#7,d0
	asr.l	#7,d1
	asr.l	#7,d2
	
	move.w	d0,(a0)+
	move.w	d1,(a0)+
	move.w	d2,(a0)+

	move.w	2(a0),d0
	; Skip number of vertices + 1 (last == first) + 2 (visibility, nverts)
	; --------------------------------------------------------------------
	addq	#3,d0
	add.w	d0,d0

	add.w	d0,a0
	dbra	d7,.norml

	; Check out which faces are visible
	; ---------------------------------
	move.l	sv_faces,a0
	lea	sv_rotated,a1
	move.w	(a0),d7
	addq	#4,a0
	subq	#1,d7
.visib:	lea	16(a0),a0
	lea	-2(a0),a2
	; Skip number of vertices + 1 (last == first)
	; -------------------------------------------
	move.w	(a0)+,a3
	addq	#1,a3
	add.w	a3,a3
	move.w	(a0),d0
	lsl.w	#3,d0
	move.w	(a1,d0.w),d1	;Rx1
	move.w	2(a1,d0.w),d2	;Ry1
	move.w	2(a0),d0
	lsl.w	#3,d0
	move.w	(a1,d0.w),d3	;Rx2
	move.w	2(a1,d0.w),d4	;Ry2
	move.w	4(a0),d0
	lsl.w	#3,d0
	move.w	(a1,d0.w),d5	;Rx3
	move.w	2(a1,d0.w),d6	;Ry3
	sub.w	d1,d3
	sub.w	d1,d5
	sub.w	d2,d4
	sub.w	d2,d6
	muls	d3,d6
	muls	d4,d5
	sub.w	d6,d5
	move.w	d5,(a2)
	add.w	a3,a0
	dbra	d7,.visib

	; Calculate face center z coordinates
	; -----------------------------------
	move.l	sv_faces,a0
	lea	sv_rotated,a1
	lea	sv_faces_z,a2
	move.l	a2,a3
	clr.w	(a2)+
	move.w	(a0),d7
	addq	#4,a0
	subq	#1,d7
.calcz:	; Store face address
	; ------------------
	move.l	a0,a4
	lea	16(a0),a0
	; Number of vertices
	; ------------------
	move.w	(a0)+,d5
	; Check if plane is visible
	; -------------------------
	tst.w	-4(a0)
	bmi.s	.visbl
	; Skip number of vertices + 1 (last == first)
	; -------------------------------------------
	addq	#1,d5
	add.w	d5,d5
	add.w	d5,a0
	bra.s	.cznfc
.visbl:	; Add the Z coordinates of the plane's vertices together
	; ------------------------------------------------------
	moveq	#0,d0
	move.w	d5,d6
	subq	#1,d6
.clzlp:	move.w	(a0)+,d1
	lsl.w	#3,d1
	sub.w	4(a1,d1.w),d0
	dbra	d6,.clzlp
	; Skip last vertex
	; ----------------
	addq	#2,a0
	; Divide by number of vertices to get mean value
	; ----------------------------------------------
	divu	d5,d0
	move.w	d0,(a2)+
	move.l	a4,(a2)+
	; Number of visible faces
	; -----------------------
	add.w	#1,(a3)
.cznfc:	dbra	d7,.calcz

	; Skip sorting if number of faces in object < 30 (could use a var here)
	; ---------------------------------------------------------------------
	move.l	sv_faces,a0
	cmp.w	#30,(a0)
	bcs	.drawf
	; Sort faces by Z coordinate using straight radix sorting
	; -------------------------------------------------------
	lea	sv_faces_z,a0
	move.w	(a0)+,d0
	move.l	a0,a4
	move.w	d0,d6
	move.w	#256,d5
	add.w	d0,d0
	move.w	d0,d3
	add.w	d3,d3
	add.w	d0,d3
	subq	#1,d5
	subq	#1,d6
	lea	sv_rs_tempbuffer,a5
	lea	sv_rs_distcount,a6
	; Two passes (upper byte, lower byte)
	; -----------------------------------
	moveq	#2-1,d7
.radix:	; Clear distribution count
	; ------------------------
	move.l	a6,a0
	move.w	d5,d4
.clrdc:	clr.b	(a0)+
	dbra	d4,.clrdc

	; Calculate distribution
	; ----------------------
	moveq	#0,d0
	move.l	a6,a0
	move.l	a4,a1
	move.w	d6,d4
.cdstc:	move.b	(a1,d7.w),d0
	add.b	#1,(a0,d0.w)
	addq	#6,a1
	dbra	d4,.cdstc

	; Calculate cumulative distribution
	; ---------------------------------
	move.l	a6,a0
	move.w	d5,d4
	subq	#1,d4
.cumul:	move.b	(a0)+,d0
	add.b	d0,(a0)
	dbra	d4,.cumul

	moveq	#0,d0
	move.l	a6,a0
	move.l	a4,a1
	; Start from the last element
	; ---------------------------
	add.w	d3,a1
	move.l	a5,a2
	move.l	a1,a3
	move.w	d6,d4
.spred:	subq	#6,a3
	move.b	(a3,d7.w),d0
	move.b	(a0,d0.w),d1
	subq	#1,d1
	move.b	d1,(a0,d0.w)
	add.w	d1,d1
	move.w	d1,d2
	add.w	d1,d1
	add.w	d2,d1
	move.l	-(a1),2(a2,d1.w)
	move.w	-(a1),(a2,d1.w)
	dbra	d4,.spred

	; Copy the temporary buffer back to the real buffer
	; -------------------------------------------------
	move.l	a5,a0
	move.l	a4,a1
	move.w	d6,d4
.copyt:	move.w	(a0)+,(a1)+
	move.l	(a0)+,(a1)+
	dbra	d4,.copyt
	dbra	d7,.radix

	; Draw faces
	; ----------
.drawf:	lea	sv_rotated,a1
	lea	sv_mask,a2
	lea	sv_faces_z,a3
	lea	sv_boundaries,a4
	lea	sv_mulu_planewidth,a5
	lea	custom,a6
	move.w	(a3)+,d6
	move.w	d6,d0
	add.w	d0,d0
	move.w	d0,d1
	add.w	d0,d0
	add.w	d1,d0
	add.w	d0,a3
	subq	#1,d6
sv_fcs:	; Get a face to render
	; --------------------
	move.l	-(a3),a0
	subq	#2,a3
	; Skip non rotated normal
	; -----------------------
	addq	#8,a0
	; Store rotated normal address
	; ----------------------------
	move.l	a0,-(sp)
	addq	#8,a0
	; Get number of vertices
	; ----------------------
	move.w	(a0)+,d7
	; Clear the previous mask
	; -----------------------
	move.w	(a4),d0
	move.w	2(a4),d2
	move.w	4(a4),d1
	move.w	6(a4),d3
	; Don't clear if boundaries are invalid
	; -------------------------------------
	sub.w	d0,d2
	bmi	sv_ncl
	sub.w	d1,d3
	bmi	sv_ncl
	; Width = x2-x1 + 1, Height = y2-y1 + 1
	; -------------------------------------
	addq	#1,d2
	addq	#1,d3
	
	; Calculate clear starting position (ascending, first word)
	; ---------------------------------------------------------
	lsr.w	#3,d0
	and.w	#$fffe,d0
	add.w	d1,d1
	add.w	(a5,d1.w),d0
	ext.l	d0
	
	; Calculate blit size
	; -------------------
	add.w	#32,d2
	lsr.w	#4,d2
	lsl.w	#6,d3
	or.w	d2,d3
	
	; Calculate modulo
	; ----------------
	add.w	d2,d2
	sub.w	#SV_PLANEWIDTH,d2
	neg.w	d2

	; Clear
	; -----
	add.l	#sv_mask,d0
	waitb
	move.w	#DEST,bltcon0(a6)
	move.w	d2,bltdmod(a6)
	move.l	d0,bltdpth(a6)
	move.w	d3,bltsize(a6)

	; Reset boundary values
	; ---------------------
	move.w	#SV_PLANEWIDTH*8,(a4)
	clr.w	2(a4)
	move.w	#SV_PLANEHEIGHT,4(a4)
	clr.w	6(a4)

sv_ncl:	waitb
	move.w	#$8000,bltadat(a6)
	move.w	#$ffff,bltbdat(a6)
	move.w	#SV_PLANEWIDTH,bltcmod(a6)
	move.w	#SV_PLANEWIDTH,bltdmod(a6)

	; Draw the edges of the face
	; --------------------------
	move.w	(a0)+,d4
	lsl.w	#3,d4
	move.w	(a1,d4.w),SV_OLDX(a5)
	move.w	2(a1,d4.w),SV_OLDY(a5)
	subq	#1,d7
sv_fce:	move.w	SV_OLDX(a5),d0
	move.w	SV_OLDY(a5),d1
	move.w	(a0)+,d4
	lsl.w	#3,d4
	move.w	(a1,d4.w),d2
	move.w	2(a1,d4.w),d3
	move.w	d2,SV_OLDX(a5)
	move.w	d3,SV_OLDY(a5)

	; Check if the new coordinate is beyond previous boundaries
	; ---------------------------------------------------------
	cmp.w	(a4),d2
	bhi.s	.lftok
	move.w	d2,(a4)
.lftok:	cmp.w	2(a4),d2
	bcs.s	.rgtok
	move.w	d2,2(a4)
.rgtok:	cmp.w	4(a4),d3
	bhi.s	.topok
	move.w	d3,4(a4)
.topok:	cmp.w	6(a4),d3
	bcs.s	.botok
	move.w	d3,6(a4)
.botok:
	; Make sure the line is drawn from top to bottom
	; ----------------------------------------------
	cmp.w	d1,d3
	beq.w	sv_nl
	bhi.s	.yok
	exg	d0,d2
	exg	d1,d3
.yok:	moveq	#-1,d5
	move.w	d3,d4
	sub.w	d1,d4
	add.w	d4,d4
	sub.w	d0,d2
	bge.s	.x2gx1
	neg.w	d2
	subq	#2,d5
.x2gx1:	cmp.w	d4,d2
	blo.s	.allok
	subq	#1,d3
.allok:	sub.w	d1,d3
	add.w	d1,d1
	move.w	(a5,d1.w),d1
	ext.l	d1
	move.w	d0,d4
	asr.w	#3,d4
	add.w	d4,d1
	add.l	a2,d1

	move.w	d3,d4
	sub.w	d2,d4
	bge.s	.dygdx
	exg	d2,d3
	subq	#1,d5
.dygdx:	move.b	(a4,d5.w),d5
	and.w	#$00ff,d5
	add.w	d2,d2
	and.w	#$000f,d0
	ror.w	#4,d0
	or.w	#SRCA|SRCC|DEST|ABNC|ANBNC|NABC|NANBC,d0

	waitb

	move.w	d2,bltbmod(a6)
	sub.w	d3,d2
	bge.s	.signl
	or.w	#SIGNFLAG,d5
.signl:	move.w	d2,bltaptl(a6)
	sub.w	d3,d2
	move.w	d2,bltamod(a6)
	move.w	d0,bltcon0(a6)
	move.w	d5,bltcon1(a6)
	move.l	d1,bltcpth(a6)
	move.l	d1,bltdpth(a6)
	lsl.w	#6,d3
	addq	#2,d3
	move.w	d3,bltsize(a6)
	
sv_nl:	dbra	d7,sv_fce

	; Get boundaries (x1, x2, y1, y2)
	; -------------------------------
	move.w	(a4),d0
	move.w	2(a4),d2
	move.w	4(a4),d1
	move.w	6(a4),d3
	move.w	d0,d7
	; Restore rotated normal address
	; ------------------------------
	move.l	(sp)+,a0
	; Width = x2-x1 + 1, Height = y2-y1 + 1
	; -------------------------------------
	sub.w	d0,d2
	bmi	sv_nf
	sub.w	d1,d3
	bmi	sv_nf
	addq	#1,d2
	addq	#1,d3

	; Stencil X position
	; ------------------
	move.w	(a0),d4
	asr.w	#SV_NORMAL_SHIFT,d4
	add.w	#SV_STENCIL_WIDTH*8,d4
	sub.w	d2,d4
	lsr.w	d4
	; Stencil Y position
	; ------------------
	move.w	2(a0),d5
	asr.w	#SV_NORMAL_SHIFT,d5
	add.w	#SV_STENCIL_HEIGHT,d5
	sub.w	d3,d5
	lsr.w	d5
	
	; Calculate blit starting position (ascending, first word)
	; --------------------------------------------------------
	lsr.w	#3,d0
	and.w	#$fffe,d0
	add.w	d1,d1
	move.w	(a5,d1.w),d1
	add.w	d0,d1
	ext.l	d1

	; Calculate fill starting position (descending, last word)
	; --------------------------------------------------------
	move.w	d3,d0
	add.w	d0,d0
	subq	#2,d0
	move.w	(a5,d0.w),d0
	add.w	d1,d0
	add.w	#32,d2
	lsr.w	#4,d2
	add.w	d2,d0
	add.w	d2,d0
	subq	#2,d0
	ext.l	d0

	; Calculate blit size
	; -------------------
	lsl.w	#6,d3
	or.w	d2,d3

	; Calculate modulo
	; ----------------
	add.w	d2,d2
	sub.w	#SV_PLANEWIDTH,d2
	neg.w	d2

	; Calculate stencil starting position (ascending, first word)
	; -----------------------------------------------------------
	swap	d7
	move.w	d4,d7

	lsr.w	#3,d4
	and.w	#$fffe,d4
	ext.l	d4
	add.w	d5,d5
	add.w	(a5,d5.w),d4

	; Fill the image
	; --------------
	add.l	#sv_mask,d0
	waitb
	move.w	#SRCA|DEST|ABC|ABNC|ANBC|ANBNC,bltcon0(a6)
	move.w	#BLITREVERSE|FILL_OR,bltcon1(a6)
	move.w	d2,bltamod(a6)
	move.w	d2,bltdmod(a6)
	move.l	d0,bltapth(a6)
	move.l	d0,bltdpth(a6)
	move.w	d3,bltsize(a6)

	; Calculate stencil right shift
	; -----------------------------
	swap	d7
	move.w	d7,d5
	swap	d7
	and.w	#15,d5
	and.w	#15,d7
	; Destination coords == shift right, stencil coords == shift left
	; ---------------------------------------------------------------
	sub.w	d7,d5
	bpl.s	.steno
	; If shift value negative, blit one more word
	; -------------------------------------------
	subq	#2,d1
	subq	#2,d2
	addq	#1,d3
	and.w	#15,d5
.steno:	ror.w	#4,d5
	or.w	#SRCA|SRCB|SRCC|DEST|ABC|ABNC|NANBC|ANBC,d5

	; Copy with mask (all planes)
	; ---------------------------
	move.l	d1,d0
	add.l	#sv_mask,d0
	add.l	#sv_planes,d1
	add.l	sv_planes_add,d1
	add.l	#sv_stencil,d4
	waitb
	move.w	d5,bltcon0(a6)
	move.w	#0,bltcon1(a6)
	move.w	d2,bltamod(a6)
	move.w	d2,bltbmod(a6)
	move.w	d2,bltcmod(a6)
	move.w	d2,bltdmod(a6)
	moveq	#SV_PLANES-1,d7
sv_clp:	waitb
	move.l	d4,bltapth(a6)
	move.l	d0,bltbpth(a6)
	move.l	d1,bltcpth(a6)
	move.l	d1,bltdpth(a6)
	move.w	d3,bltsize(a6)
	add.l	#SV_STENCIL_SIZE,d4
	add.l	#SV_PLANESIZE,d1
	dbra	d7,sv_clp
sv_nf:	dbra	d6,sv_fcs

	move.b	#1,render
	rts	

stencilvector_pre_vbi:
	movem.l	d1-d2,-(sp)

	lea	vv_palettes,a0
	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	cmp.w	#123,d0
	bhi.s	.noset
	move.w	d0,d1
	and.w	#3,d1
	bne.s	.noset
	tst.b	sv_pre_set
	bne.s	.setok
	move.b	#1,sv_pre_set
	move.b	#1,sv_pre_wait
	move.w	#17,sv_pre_fader
	bra.s	.setok
.noset:	clr.b	sv_pre_set
.setok:	tst.w	sv_pre_fader
	beq.s	.npal
	eor.b	#1,sv_pre_wait
	bne.s	.waitd
	sub.w	#1,sv_pre_fader
.waitd:	; Fade palette out
	; ----------------
	lsr.w	d0
	and.w	#14,d0
	move.w	(a0,d0.w),d0
	move.w	sv_pre_fader,d1
	lsl.w	#4,d1
	lea	table_fade,a0
	add.w	d1,a0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a0,d0.w),d0
	move.b	(a0,d1.w),d1
	move.b	(a0,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,ne_cl_palette+2

.npal:	movem.l	(sp)+,d1-d2
	rts

stencilvector_vbi:
	movem.l	d1-d2/a1-a2/d7,-(sp)

	move.w	sv_distance,d0
	cmp.w	sv_distance_old,d0
	beq.s	.npal
	move.w	d0,sv_distance_old
	move.l	#SV_DISTANCE_MAX,d1
	sub.w	d0,d1
	divu	#80,d1
	lsl.w	#4,d1
	; Fade palette out
	; ----------------
	lea	sv_palettes_list,a0
	add.w	sv_object,a0
	move.l	(a0),a0
	lea	table_fade,a1
	add.w	d1,a1
	lea	sv_cl_palette+2,a2
	moveq	#16-1,d7
.fdpl2:	move.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,(a2)
	addq	#4,a2
	dbra	d7,.fdpl2

.npal:	; Check if it is time to change the object
	; ----------------------------------------
	move.l	sc_position,d0	
	sub.l	#30*PATTERNLENGTH+1,d0
	and.w	#255,d0
	cmp.w	#60,d0
	beq.s	.obchg
	cmp.w	#124,d0
	beq.s	.obchg
	cmp.w	#245,d0
	bne.s	.noobc
.obchg:	move.b	#1,sv_object_change

	; If the object is about to be changed move it far away first
	; -----------------------------------------------------------
.noobc:	tst.b	sv_object_change
	beq.s	.near
	cmp.w	#SV_DISTANCE_MAX,sv_distance
	beq.s	.disto
	add.w	#55,sv_distance
	bra.s	.disto
	; Otherwise bring the object near
	; -------------------------------
.near:	cmp.w	#SV_DISTANCE_MIN,sv_distance
	beq.s	.disto
	sub.w	#55,sv_distance
.disto:	tst.b	sv_angles_lock
	bne.s	.lock1
	move.l	sv_angles_add,d0
	add.l	d0,sv_angles
.lock1:	tst.b	sv_angles_lock+1
	bne.s	.lock2
	move.l	sv_angles_add+4,d0
	add.l	d0,sv_angles+4
.lock2:	tst.b	sv_angles_lock+2
	bne.s	.lock3
	move.l	sv_angles_add+8,d0
	add.l	d0,sv_angles+8
.lock3:	move.l	sc_position,d0	
	add.w	#128,d0
	subq	#1,d0
	and.w	#255,d0
	cmp.w	#208,d0
	bcs.s	.and
	cmp.w	#$07ff,sv_angles
	bcs.s	.xok
	move.l	#$00000200,sv_angles
	move.b	#1,sv_angles_lock
.xok:	cmp.w	#$07ff,sv_angles+4
	bcs.s	.yok
	move.l	#$00000200,sv_angles+4
	move.b	#1,sv_angles_lock+1
.yok:	cmp.w	#$07ff,sv_angles+8
	bcs.s	.zok
	move.l	#$00000200,sv_angles+8
	move.b	#1,sv_angles_lock+2
.zok:
.and:	and.l	#$07ff07ff,sv_angles
	and.l	#$07ff07ff,sv_angles+4
	and.l	#$07ff07ff,sv_angles+8
.anded:	tst.b	render
	beq	.vbiok
	move.l	#sv_planes,d0
	add.l	sv_planes_add,d0
	lea	sv_cl_bpl1pth,a0
	moveq	#SV_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#SV_PLANESIZE,d0
	dbra	d7,.setplanesloop

	tst.b	sv_object_change
	beq.s	.nchob
	cmp.w	#SV_DISTANCE_MAX,sv_distance
	bne.s	.nchob
	clr.b	sv_object_change
	move.w	sv_object,d0
	addq	#4,d0
	move.w	d0,sv_object
	lea	sv_faces_list+2,a0
	move.l	(a0,d0.w),sv_faces
	lea	sv_coordinates_list+2,a0
	move.l	(a0,d0.w),sv_coordinates
	sub.l	#$00040004,sv_angles_add
	add.l	#$00020002,sv_angles_add+8

.nchob:	eor.l	#SV_PLANES*SV_PLANESIZE,sv_planes_add
	clr.b	render
.vbiok:	movem.l	(sp)+,d1-d2/a1-a2/d7
	rts

jellylogo:
	; Clear memory
	; ------------
	lea	jl_cl,a0
	move.l	#jl_requirements_chipmem,d7
	bsr	clearmemory
	lea	jl_planes_add,a0
	move.l	#jl_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	jl_ct,a0
	lea	jl_cl,a1
	move.w	#(jl_ct_data-jl_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Decrunch bitmap
	; ---------------
	lea	jl_bitmap,a0
	lea	jl_bitmap1_stc,a1
	bsr	decrunch

	; Set palette
	; -----------
	lea	jl_bitmap+JL_PLANES*JL_PLANESIZE,a0
	lea	jl_cl_palette+2,a1
	moveq	#8-1,d7
.cppal:	move.w	(a0)+,(a1)
	addq	#4,a1
	dbra	d7,.cppal

	; Screen setup
	; ------------
	move.l	#jl_planes,d0
	lea	jl_cl_bpl1pth,a0
	moveq	#JL_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#JL_PLANEWIDTH,d0
	dbra	d7,.setplanesloop

	move.l	#$360,jl_multiplier
	move.w	#92,jl_sinusadd
	move.w	#512,jl_sinuspointer
	move.w	#JL_PLANEWIDTH*8,jl_x
	rts

jellylogo_go:
	move.l  #jl_cl,cop1lch+custom
	move.l	#jellylogo_main,part_main
	move.l	#jellylogo_vbi,part_vbi
	rts

jellylogo_main:
	cmp.b	#4,jl_reset
	beq.s	.clear
	cmp.b	#1,jl_reset
	bne.s	jl_nrs

	; Clear the bitplanes
	; -------------------
.clear:	lea	custom,a6
	moveq	#0,d0
	waitb
	move.l	#-1,bltafwm(a6)
	move.w	d0,bltcon1(a6)
	move.w	#DEST,bltcon0(a6)
	move.w	d0,bltdmod(a6)
	move.l	#jl_planes,bltdpth(a6)
	move.w	#((2*JL_PLANES*JL_PLANEHEIGHT)<<6)|(JL_PLANEWIDTH/2),bltsize(a6)

	; Reset the effect
	; ----------------
	move.l	#$360,jl_multiplier
	move.w	#92,jl_sinusadd
	move.w	#512,jl_sinuspointer
	move.w	#JL_PLANEWIDTH*8,jl_x
	lea	jl_bitmap,a0
	lea	jl_bitmap2_stc,a1
	bsr	decrunch
	add.b	#1,jl_reset

jl_nrs:	lea	jl_bitmap,a0
	lea	jl_planes,a1
	add.l	jl_planes_add,a1
	lea	sinus,a2
	move.l	jl_multiplier,d6
	move.l	d6,d7
	mulu	#JL_PLANEHEIGHT,d6
	lsl.l	#8,d6
	lsl.l	#8,d7
	move.l	d7,a3
	move.w	jl_x,a4
	lea	custom,a6
	waitb
	move.l	#-1,bltafwm(a6)
	move.w	jl_sinuspointer,d0
	move.w	(a2,d0.w),d0
	move.w	#$7fff,a5
	moveq	#0,d2
	move.w	#JL_PLANEHEIGHT-1,d7
jl_blp:	move.l	a0,d4
	move.l	a1,d5
	swap	d6
	; X add
	; -----
	move.w	d0,d1
	move.w	a5,d3
	sub.w	(a2),d3
	addq	#8,a2
	muls	d3,d1
	add.l	d1,d1
	swap	d1
	muls	d6,d1
	bpl.s	.noneg
	add.l	#$00010000,d1
.noneg:	swap	d1
	add.w	a4,d1
	bmi.s	jl_xng
	; X positive: Width = PLANEWIDTH/2 - X/16, Modulo = X/8
	; -----------------------------------------------------
	move.w	d1,d3
	lsr.w	#4,d3
	move.w	d3,d2
	neg.w	d3
	add.w	#JL_PLANEWIDTH/2,d3
	; Don't draw if the line goes outside the screen
	; ----------------------------------------------
	bmi	jl_nxt
	beq	jl_nxt
	or.w	#(1<<6),d3
	add.w	d2,d2
	and.w	#15,d1
	ror.w	#4,d1
	or.w	#SRCA|DEST|ABC|ABNC|ANBC|ANBNC,d1
	add.l	d2,d5
	waitb
	move.w	#0,bltcon1(a6)
	bra.s	jl_dbl
	; X negative: Width = PLANEWIDTH/2 + X/16, Modulo = X/8
	; -----------------------------------------------------
jl_xng:	neg.w	d1
	move.w	d1,d3
	lsr.w	#4,d3
	move.w	d3,d2
	sub.w	#JL_PLANEWIDTH/2,d3
	; Don't draw if the line goes outside the screen
	; ----------------------------------------------
	bpl	jl_nxt
	neg.w	d3
	or.w	#(1<<6),d3
	add.w	d2,d2
	and.w	#15,d1
	ror.w	#4,d1
	or.w	#SRCA|DEST|ABC|ABNC|ANBC|ANBNC,d1
	add.l	#JL_PLANES*JL_PLANEWIDTH-2,d4
	add.l	#JL_PLANES*JL_PLANEWIDTH-2,d5
	sub.l	d2,d5
	waitb
	move.w	#BLITREVERSE,bltcon1(a6)
jl_dbl:	move.w	d1,bltcon0(a6)
	move.w	d2,bltamod(a6)
	move.w	d2,bltdmod(a6)
	move.l	d4,bltapth(a6)
	move.l	d5,bltdpth(a6)
	move.w	d3,bltsize(a6)
	waitb	
	move.w	d3,bltsize(a6)
	waitb	
	move.w	d3,bltsize(a6)
jl_nxt:	lea	JL_PLANES*JL_PLANEWIDTH(a0),a0
	lea	JL_PLANES*JL_PLANEWIDTH(a1),a1
	swap	d6
	sub.l	a3,d6
	dbra	d7,jl_blp

	move.b	#1,render
	rts

jellylogo_vbi:
	movem.l	d1-d2/a1-a2/d7,-(sp)

	tst.w	jl_x
	beq.s	.xok
	sub.w	#16,jl_x
	bne.s	.nsin
.xok:	tst.l	jl_multiplier
	beq.s	.nsin
	sub.l	#3,jl_multiplier
.nmult:	move.w	jl_sinusadd,d0
	add.w	d0,jl_sinuspointer
	cmp.w	#2048,jl_sinuspointer
	bcs.s	.nsin
	sub.w	#2048,jl_sinuspointer
	add.w	#4,jl_sinusadd

.nsin:	cmp.b	#3,jl_reset
	beq.s	.fade2
	tst.b	jl_reset
	bne	.npal
	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#63,d0
	cmp.w	#61,d0
	bcs.w	.npal
	mulu	#6,d0
	addq	#6,d0
	sub.w	tp_wait,d0
	move.w	#64*6-1,d1
	bra.s	.fade
.fade2:	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#63,d0
	cmp.w	#57,d0
	bcs.s	.npal
	mulu	#6,d0
	addq	#6,d0
	sub.w	tp_wait,d0
	move.w	#60*6-1,d1
.fade:	sub.w	d0,d1
	bmi.s	.npal
	cmp.w	#16,d1
	bhi.s	.npal
	lsl.w	#4,d1
	bne.s	.nlast
	add.b	#1,jl_reset
	; Fade palette
	; ------------
.nlast:	lea	jl_bitmap+JL_PLANES*JL_PLANESIZE,a0
	lea	table_fade,a1
	add.w	d1,a1
	lea	jl_cl_palette+2,a2
	moveq	#8-1,d7
.fdpal:	move.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,(a2)
	addq	#4,a2
	dbra	d7,.fdpal
.npal:	tst.b	render
	beq.s	.vbiok

	; Screen setup
	; ------------
	move.l	#jl_planes,d0
	add.l	jl_planes_add,d0
	lea	jl_cl_bpl1pth,a0
	moveq	#JL_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#JL_PLANEWIDTH,d0
	dbra	d7,.setplanesloop

	cmp.b	#5,jl_reset
	beq.s	.reset
	cmp.b	#2,jl_reset
	bne.s	.nrest
	; Set palette
	; -----------
.reset:	lea	jl_bitmap+JL_PLANES*JL_PLANESIZE,a0
	lea	jl_cl_palette+2,a1
	moveq	#8-1,d7
.cppal:	move.w	(a0)+,(a1)
	addq	#4,a1
	dbra	d7,.cppal
	add.b	#1,jl_reset
.nrest:	eor.l	#JL_PLANES*JL_PLANESIZE,jl_planes_add
	clr.b	render
.vbiok:	movem.l	(sp)+,d1-d2/a1-a2/d7
	rts

vectorvideo:
	; Clear memory
	; ------------
	lea	vv_cl,a0
	move.l	#vv_requirements_chipmem,d7
	bsr	clearmemory
	lea	vv_planes_add,a0
	move.l	#vv_requirements_fastmem,d7
	bsr	clearmemory

	; Copy copperlist
	; ---------------
	lea	vv_ct,a0
	lea	vv_cl,a1
	move.w	#(vv_ct_data-vv_ct)/4-1,d7
.cplst:	move.l	(a0)+,(a1)+
	dbra	d7,.cplst

	; Screen setup
	; ------------
	move.l	#vv_planes,d0
	lea	vv_cl_bpl1pth,a0
	moveq	#VV_PLANES-1,d7
.setplanesloop:
	move.w	d0,4(a0)
	swap	d0
	move.w	d0,(a0)
	swap	d0
	addq	#8,a0
	add.l	#VV_PLANESIZE,d0
	dbra	d7,.setplanesloop

	; Create multiply table
	; ---------------------
	moveq	#0,d0
	lea	vv_mulu_planewidth,a0
	move.w	#VV_PLANEHEIGHT-1,d7
.mulu:	move.w	d0,(a0)+
	add.w	#VV_PLANEWIDTH,d0
	dbra	d7,.mulu

	; Create octants table
	; --------------------
	move.b	#0|ONEDOT|LINEMODE,vv_mulu_planewidth-1	;y1<y2, x1<x2, dx<dy = okt6
	move.b	#16|ONEDOT|LINEMODE,vv_mulu_planewidth-2	;y1<y2, x1<x2, dx>dy = okt7
	move.b	#8|ONEDOT|LINEMODE,vv_mulu_planewidth-3	;y1<y2, x1>x2, dx<dy = okt5
	move.b	#20|ONEDOT|LINEMODE,vv_mulu_planewidth-4	;y1<y2, x1>x2, dx>dy = okt4
	rts

vectorvideo_go:
	move.l  #vv_cl,cop1lch+custom
	move.l	#vectorvideo_main,part_main
	move.l	#vectorvideo_vbi,part_vbi
	rts

vectorvideo_main:
	; Clear destination bitplane
	; --------------------------
	lea	custom,a6
	move.l	#vv_planes,d0
	add.l	vv_planes_add,d0
	moveq	#0,d1
	waitb
	move.l	#-1,bltafwm(a6)
	move.w	d1,bltcon1(a6)
	move.w	#DEST,bltcon0(a6)
	move.w	d1,bltdmod(a6)
	move.l	d0,bltdpth(a6)
	move.w	#((VV_PLANES*VV_PLANEHEIGHT)<<6)|(VV_PLANEWIDTH/2),bltsize(a6)

	; Prepare blitter for line drawing
	; --------------------------------
	waitb
	move.w	#$8000,bltadat(a6)
	move.w	#$ffff,bltbdat(a6)
	move.w	#VV_PLANEWIDTH,bltcmod(a6)
	move.w	#VV_PLANEWIDTH,bltdmod(a6)

	; Draw the lines
	; --------------
	lea	vv_table,a0
	add.l	vv_pointer,a0
	move.l	(a0),a0
	move.l	d0,a1
	lea	VV_PLANES*VV_PLANESIZE(a1),a5
	lea	vv_mulu_planewidth,a2
vv_polygon:
	move.b	(a0)+,d7
	lsl.w	#8,d7
	move.b	(a0)+,d7
	tst.w	d7
	bne.s	.go
	lea	VV_PLANESIZE(a1),a1
	cmp.l	a5,a1
	bcs.s	vv_polygon
	bra.w	vv_fill
.go:	move.w	d7,d6
	add.w	d6,d6
	moveq	#0,d0
	moveq	#0,d1
	move.b	(a0,d6.w),d0
	add.w	d0,d0
	move.b	1(a0,d6.w),d1
	move.w	d0,a3
	move.w	d1,a4
vv_loop:
	move.w	a3,d0
	move.w	a4,d1
	moveq	#0,d2
	moveq	#0,d3
	move.b	(a0)+,d2
	add.w	d2,d2
	move.b	(a0)+,d3
	move.w	d2,a3
	move.w	d3,a4
	; Make sure the line is drawn from top to bottom
	; ----------------------------------------------
	cmp.w	d1,d3
	beq.w	vv_nl
	bhi.s	.yok
	exg	d0,d2
	exg	d1,d3
.yok:	moveq	#-1,d5
	move.w	d3,d4
	sub.w	d1,d4
	add.w	d4,d4
	sub.w	d0,d2
	bge.s	.x2gx1
	neg.w	d2
	subq	#2,d5
.x2gx1:	cmp.w	d4,d2
	blo.s	.allok
	subq	#1,d3
.allok:	sub.w	d1,d3
	add.w	d1,d1
	move.w	(a2,d1.w),d1
	ext.l	d1
	move.w	d0,d4
	asr.w	#3,d4
	add.w	d4,d1
	add.l	a1,d1

	move.w	d3,d4
	sub.w	d2,d4
	bge.s	.dygdx
	exg	d2,d3
	subq	#1,d5
.dygdx:	move.b	(a2,d5.w),d5
	and.w	#$00ff,d5
	add.w	d2,d2
	and.w	#$000f,d0
	ror.w	#4,d0
	or.w	#SRCA|SRCC|DEST|ABNC|ANBNC|NABC|NANBC,d0

	waitb
	move.w	d2,bltbmod(a6)
	sub.w	d3,d2
	bge.s	.signl
	or.w	#SIGNFLAG,d5
.signl:	move.w	d2,bltaptl(a6)
	sub.w	d3,d2
	move.w	d2,bltamod(a6)
	move.w	d0,bltcon0(a6)
	move.w	d5,bltcon1(a6)
	move.l	d1,bltcpth(a6)
	move.l	d1,bltdpth(a6)
	lsl.w	#6,d3
	addq	#2,d3
	move.w	d3,bltsize(a6)
vv_nl:	dbra	d7,vv_loop
	bra	vv_polygon

	; Fill the image
	; --------------
vv_fill:
	move.l	#vv_planes,d0
	add.l	vv_planes_add,d0
	add.l	#VV_PLANES*VV_PLANESIZE-2,d0
	moveq	#0,d1
	waitb
	move.w	#SRCA|DEST|ABC|ABNC|ANBC|ANBNC,bltcon0(a6)
	move.w	#BLITREVERSE|FILL_OR,bltcon1(a6)
	move.l	d1,bltamod(a6)
	move.l	d0,bltapth(a6)
	move.l	d0,bltdpth(a6)
	move.w	#((VV_PLANES*VV_PLANEHEIGHT)<<6)|(VV_PLANEWIDTH/2),bltsize(a6)
	waitb

	move.b	#1,render
	rts

vectorvideo_vbi:
	movem.l	d1-d2/a1-a2,-(sp)
	
	lea	vv_palettes,a0
	move.l	sc_position,d0	
	subq	#1,d0
	and.w	#127,d0
	move.w	d0,d1
	and.w	#3,d1
	bne.s	.noset
	tst.b	vv_set
	bne.s	.setok
	move.w	d0,d1
	lsr.w	d1
	and.w	#14,d1
	move.w	(a0,d1.w),vv_palette_current
	addq	#2,d1
	and.w	#14,d1
	move.w	(a0,d1.w),vv_palette_current+2
	move.b	#1,vv_set
	move.b	#1,vv_wait
	move.w	#17,vv_fader
	bra	.setok
.noset:	clr.b	vv_set
.setok:	tst.w	vv_fader
	beq.w	.npal
	eor.b	#1,vv_wait
	bne.s	.waitd
	sub.w	#1,vv_fader
.waitd:	; Fade palette out
	; ----------------
	move.w	vv_fader,d1
	lsl.w	#4,d1
	lea	vv_palette_current,a0
	lea	table_fade,a1
	add.w	d1,a1
	lea	vv_cl_palette+2,a2
	move.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,(a2)
	addq	#4,a2
	move.w	(a0)+,d0
	move.w	d0,d1
	move.w	d0,d2
	lsr.w	#8,d0
	lsr.w	#4,d1
	and.w	#$f,d1
	and.w	#$f,d2
	move.b	(a1,d0.w),d0
	move.b	(a1,d1.w),d1
	move.b	(a1,d2.w),d2
	lsl.w	#8,d0
	lsl.w	#4,d1
	or.w	d1,d0
	or.w	d2,d0
	move.w	d0,(a2)
	move.w	vv_cl_palette+2,ne_cl_palette+2

.npal:	add.w	#1,vv_frame

	tst.b	render
	beq.s	.vbiok

	; Display the rendered buffer
	; ---------------------------
	move.l	#vv_planes,d0
	add.l	vv_planes_add,d0
	move.w	d0,vv_cl_bpl1ptl
	swap	d0
	move.w	d0,vv_cl_bpl1pth

	; Switch buffers
	; --------------
	eor.l	#VV_PLANES*VV_PLANESIZE,vv_planes_add

	moveq	#0,d0
	move.w	vv_frame,d0
	divu	#3,d0
	and.l	#$ffff,d0
	add.l	d0,d0
	add.l	d0,d0
	cmp.l	#VV_FRAMES*4,d0
	bcs.s	.frame
	moveq	#0,d0
	clr.w	vv_frame
.frame:	move.l	d0,vv_pointer
	clr.b	render
.vbiok:	movem.l	(sp)+,d1-d2/a1-a2
	rts

end:	move.b	#1,quit
	rts

;-----------------------------------------------------------------------------
;- S404 highly optimized data decruncher v1.1 turbo
;- 27.11.93 by Marcus 'Cozine' Ottosson
;-----------------------------------------------------------------------------
;- Based on S404 data_decruncher v0.2
;- (c) 1993 by Jouni 'Mr.Spiv' Korhonen (SWSW)
;-----------------------------------------------------------------------------
;- call with registers: a0 = destination address
;-                      a1 = crunched data
;-----------------------------------------------------------------------------

; uses d0-a6


decrunch:
_l0:		addq	#8,a1			; Skip ID string & security
						; length..
		move.l	a0,a5
		add.l	(a1)+,a0
		add.l	(a1),a1
		moveq	#0,d4
		moveq	#16,d5
		movem.w	(a1),d2/d6/d7
		not.w	d4
		lea	_loff6(pc),a3
		lea	_llen5a(pc),a4
		moveq	#1,d0
		moveq	#-1,d3
		bra.s	_ltest1

_lins:		subq.w	#8,d7
		bpl.s	_lins2
_lins1:		move.w	d7,d1
		addq.w	#8,d7
		lsl.l	d7,d6
		move.w	-(a1),d6
		neg.w	d1
		lsl.l	d1,d6
		addq.w	#8,d7
		swap	d6
		move.b	d6,-(a0)
		swap	d6
		cmp.l	a0,a5
		dbhs	d7,_lmain
		bra.s	_lexma

_lins2:		rol.w	#8,d6
		move.b	d6,-(a0)
_ltest1:	cmp.l	a0,a5
		dbhs	d7,_lmain
_lexma		bhs.s	_lexit

_lmain1:	move.w	-(a1),d6
		moveq	#15,d7
_lmain:		add.w	d6,d6
		bcc.s	_lins

		dbf	d7,_llen1
		move.w	-(a1),d6
		moveq	#15,d7
_llen1:		add.w	d6,d6
		bcs.s	_llen6
		dbf	d7,_llen2
		move.w	-(a1),d6
		moveq	#15,d7
_llen2:		moveq	#2,d1
		moveq	#2,d3
		add.w	d6,d6
		bcs.s	_llen5
		dbf	d7,_llen3
		move.w	-(a1),d6
		moveq	#15,d7
_llen3:		add.w	d6,d6
		bcc.s	_llen4
		moveq	#4,d1
		moveq	#6,d3
		lea	_llen3a(pc),a6
		bra.s	_lbits
_llen3a:	add.w	d1,d3
		cmp.w	#15,d1
		blo.s	_loff1

		moveq	#5,d1
		moveq	#14,d3
		lea	_llen3b(pc),a6
		bra.s	_lbits

_llen4:		moveq	#21,d3
_lloop:		moveq	#8,d1
_llen5:		move.l	a4,a6
		bra.s	_lbits
_llen5a:	add.w	d1,d3
		not.b	d1
		dbeq	d7,_loff2
		bne.s	_loff2a	
		beq.s	_lloop

_loff6:		add.w	d1,a2
		move.b	(a2),-(a0)
_lcopy:		move.b	-(a2),-(a0)
		dbf	d3,_lcopy
_ltest:		cmp.l	a0,a5
		dbhs	d7,_lmain
		blo.s	_lmain1
_lexit:		rts

_llen6:		dbf	d7,_llen7
		move.w	-(a1),d6
		moveq	#15,d7
_llen7:		add.w	d6,d6
		addx.w	d0,d3
_loff1:		dbf	d7,_loff2
_loff2a:	move.w	-(a1),d6
		moveq	#15,d7
_loff2:		add.w	d6,d6
		bcs.s	_loff3

		dbf	d7,_loff4
		move.w	-(a1),d6
		moveq	#15,d7
_loff4:		moveq	#9,d1
		lea	32(a0),a2
		add.w	d6,d6
		bcc.s	_loff5
		moveq	#5,d1
		move.l	a0,a2
		bra.s	_loff5
_loff3:		lea	544(a0),a2
		move.w	d2,d1
_loff5:		move.l	a3,a6

_lbits:		and.l	d4,d6
		sub.w	d1,d7
		bpl.s	_lbits2
		add.w	d7,d1
		lsl.l	d1,d6
		move.w	d7,d1
		move.w	-(a1),d6
		neg.w	d1
		add.w	d5,d7
_lbits2:	lsl.l	d1,d6
		move.l	d6,d1
		swap.w	d1
		jmp	(a6)

_lpins2:	moveq	#-1,d3
		bra.w	_lins2

_l2ins2:	rol.w	#8,d6
		move.b	d6,-(a0)
_l2ins1:	lsl.l	d7,d6
		move.w	-(a1),d6
		lsl.l	d1,d6
		swap	d6
		move.b	d6,-(a0)
		swap	d6
		subq.w	#2,d3
		bgt.s	_l2ins2
		beq.s	_lpins2
		addq.w	#8,d7
		bra.s	_ltest

_llen3b:	add.w	d1,d3
		move.b	_lnewd1(pc,d7),d1
		bpl.s	_l2ins1
		subq.w	#8,d7
		dbf	d3,_l2ins2

_lnewd1:	dc.b	$08,$07,$06,$05,$04,$03,$02,$01
		dc.b	$88,$87,$86,$85,$84,$83,$82,$81

; Startup code
; ------------
StartUp:
	; Open libraries
	; --------------
	move.l	4.w,a6
	moveq	#0,d0
	lea	name_graphics,a1
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,base_graphics
	bne	.base_graphicsok
	move.b	#1,quit
	rts

.base_graphicsok:
	; Get Vector Base Register
	; ------------------------
	jsr	_LVOForbid(a6)
	move.w	AttnFlags(a6),d0
	beq	.no680x0				; 68010-040 bits 0-3
	lea	GetVBR(pc),a5
	jsr	_LVOSuperVisor(a6)

	; Disable caches
	; -------------
	moveq	#0,d0
	move.l	#CACR_CopyBack|CACR_EnableE|CACR_DBE|CACR_ClearD|CACR_EnableD|CACR_FreezeD|CACR_IBE|CACR_ClearI|CACR_FreezeI|CACR_EnableI,d1
	jsr	_LVOCacheControl(a6)
	move.l	d0,cachebits_old

.no680x0:
	; Store old values
	; ----------------
	move.l	tp_vbr,a5
	move.l	base_graphics,a6
	move.l	gb_ActiView(a6),gb_ActiView_old
	move.l 	gb_copinit(a6),gb_copinit_old
	move.l	$6c(a5),vbi_old
	move.l	$78(a5),cia_old
	sub.l	a1,a1
	ifne	FINALVERSION
	jsr	_LVOLoadView(a6)
	endc
	jsr	_LVOWaitTOF(a6)
	jsr	_LVOWaitTOF(a6)

	; Calculate fade table
	; --------------------
	lea	table_fade,a0
	moveq	#0,d0
	moveq	#17-1,d7
.mulu1:	moveq	#0,d1
	moveq	#16-1,d6
.mulu2:	move.w	d1,d2
	mulu	d0,d2
	lsr.w	#4,d2
	move.b	d2,(a0)+
	addq	#1,d1
	dbra	d6,.mulu2
	addq	#1,d0
	dbra	d7,.mulu1
	
	; Disable DMA and interrupts for now
	; ----------------------------------
	lea	custom,a6
	move.w	dmaconr(a6),dmaconr_old
	move.w	intenar(a6),intenar_old
	move.w	#DMAF_BLITHOG|DMAF_ALL,dmacon(a6)
	move.w	#$ffff-INTF_SETCLR,intena(a6)

start:	clr.b	quit
	clr.b	render
	clr.l	part
	clr.l	part_main
	clr.l	part_vbi
	clr.w	ne_cl_palette+2
	move	#(STARTPATTERN-1),tp_patternnumber
	move.l	#(STARTPATTERN-1)*PATTERNLENGTH,sc_position

	; Reset CIA values
	; ----------------
	move.l	tp_vbr,a5
	lea	custom,a6
	lea	ciab,a1
	ori.b	#2,ciaa+ciaprb
	clr.b	ciacra(a1)
	clr.b	ciacrb(a1)
	move.b	#$6b,ciatalo(a1)
	move.b	#$37,ciatahi(a1)
	move.b	#$6b,ciatblo(a1)
	move.b	#1,ciatbhi(a1)
	move.b	#$7f,ciaicr(a1)
	move.b	#$83,ciaicr(a1)
	move.b	#$11,ciacra(a1)
	clr.w	aud0vol(a6)	; vol (.l clears also dat)
	clr.w	aud1vol(a6)
	clr.w	aud2vol(a6)
	clr.w	aud3vol(a6)

	; Set up interrupts and copperlist
	; --------------------------------
	move.l	#interrupt_level3,$6c(a5)
	move.l  #ne_cl,cop1lch(a6)

	; Start the module player
	; -----------------------
	lea	module,a0
	lea	sample,a1
	move.l	a0,tp_data
	move.l	a1,tp_samples
	jsr	tp_init

	; Enable interrupts and DMA
	; -------------------------
	lea	custom,a6
	move.w	#INTF_BLIT|INTF_VERTB,intreq(a6)
	move.w	#INTF_BLIT|INTF_VERTB,intreq(a6)
	move.w	#DMAF_SETCLR|DMAF_BLITTER|DMAF_COPPER|DMAF_RASTER,dmacon(a6)
	move.w	#INTF_SETCLR|INTF_INTEN|INTF_VERTB,intena(a6)
	rts

; Shut down and clean up
; ----------------------
ShutDown:
	; Disable interrupts and DMA
	; --------------------------
	lea	custom,a6
	move.w	#INTF_BLIT|INTF_VERTB,intreq(a6)
	move.w	#INTF_BLIT|INTF_VERTB,intreq(a6)
	move.w	#$ffff-INTF_SETCLR,intena(a6)
	waitb
	move.w	#DMAF_COPPER,dmacon(a6)

	; Stop the module player
	; ----------------------
	jsr	tp_end

	tst.l	loop
	bne	start

	; Restore old values
	; ------------------
	lea	custom,a6
	move.l	gb_copinit_old,cop1lch(a6)
	clr.w	copjmp1(a6)
	move.l	tp_vbr,a5
	move.w	#DMAF_SETCLR|DMAF_COPPER,dmacon(a6)
	move.l	vbi_old,$6c(a5)
	move.l	cia_old,$78(a5)
	move.w	dmaconr_old,d0
	or.w	#DMAF_SETCLR,d0
	move.w	d0,dmacon(a6)
	move.w	intenar_old,d0
	or.w	#INTF_SETCLR|INTF_INTEN,d0
	move.w	d0,intena(a6)
	move.l	base_graphics,a6
	move.l	gb_ActiView_old,a1
	jsr	_LVOLoadView(a6)
	jsr	_LVOWaitTOF(a6)
	jsr	_LVOWaitTOF(a6)

	move.l	4.w,a6
	jsr	_LVOPermit(a6)
	tst.l	base_graphics
	beq.b	.nobase_graphics
	move.l	base_graphics,a1
	jsr	_LVOCloseLibrary(a6)
.nobase_graphics:
	move.w	AttnFlags(a6),d0
	beq.b	.nocache		; 68010-040 0-3 etc.
	move.l	cachebits_old,d0
	move.l	#CACR_CopyBack|CACR_EnableE|CACR_DBE|CACR_ClearD|CACR_EnableD|CACR_FreezeD|CACR_IBE|CACR_ClearI|CACR_FreezeI|CACR_EnableI,d1
	jsr	_LVOCacheControl(a6)
.nocache:
	tst.l	message_dos
	beq.b	.nomessage
	move.l	message_dos,a1
	jsr	_LVOReplyMsg(a6)
.nomessage:
	moveq	#0,d0
	rts

; Get VBR address
; ---------------
GetVBR:	ORI	#$0700,SR
	movec	vbr,d0
	move.l	d0,tp_vbr
	RTE

	ifne	FINALVERSION
; Handle command line arguments and icon tooltypes
; ------------------------------------------------
SystemStartUp:
	move.l	4.w,a6
	sub.l	a1,a1
	jsr	_LVOFindTask(a6)
	move.l	d0,a4
	tst.l	pr_CLI(a4)
	bne	CLI
	lea	pr_MsgPort(a4),a0
	jsr	_LVOWaitPort(a6)
	lea	pr_MsgPort(a4),a0
	jsr	_LVOGetMsg(a6)
	move.l	d0,message_dos

	; Get current directory
	; ---------------------
	moveq	#36,d0
	lea	name_dos,a1
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,base_dos
	beq	.nobase_dos
	move.l	d0,a6
	move.l	#string_progdir,d1
	move.l	#ACCESS_READ,d2
	jsr	_LVOLock(a6)
	move.l	d0,lock
	beq	.nolock
	move.l	d0,d1
	jsr	_LVOCurrentDir(a6)
	move.l	d0,currentdir_old

	; Open the icon and get tooltypes
	; -------------------------------
	move.l	4.w,a6
	moveq	#0,d0
	lea	name_icon,a1
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,base_icon
	beq	.nobase_icon
	move.l	d0,a6
	move.l	ln_Name(a4),a0
	jsr	_LVOGetDiskObject(a6)
	move.l	d0,diskobject
	beq	.nodiskobject
	move.l	d0,a0
	move.l	do_ToolTypes(a0),a0
	lea	tt_loop,a1		; LOOP tooltype
	jsr	_LVOFindToolType(a6)
	move.l	d0,loop
	move.l	diskobject,a0
	jsr	_LVOFreeDiskObject(a6)
.nodiskobject:
	move.l	4.w,a6
	move.l	base_icon,a1
	jsr	_LVOCloseLibrary(a6)
.nobase_icon:
	move.l	base_dos,a6
	move.l	currentdir_old,d1
	jsr	_LVOCurrentDir(a6)
	move.l	lock,d1
	jsr	_LVOUnLock(a6)
.nolock:
	move.l	4.w,a6
	move.l	base_dos,a1
	jsr	_LVOCloseLibrary(a6)
.nobase_dos:
	rts

CLI:	; Handle command line arguments
	; -----------------------------
	moveq	#36,d0
	lea	name_dos,a1
	jsr	_LVOOpenLibrary(a6)
	move.l	d0,base_dos
	beq	.nobase_dos
	move.l	d0,a6
	move.l	#ra_template,d1
	move.l	#ra_array,d2
	moveq	#0,d3		; struct rdargs : NULL
	jsr	_LVOReadArgs(a6)
	move.l	d0,ra_rdargs
	beq	.nordargs
	move.l	ra_rdargs,d1
	jsr	_LVOFreeArgs(a6)
.nordargs:
	move.l	4.w,a6
	move.l	base_dos,a1
	jsr	_LVOCloseLibrary(a6)
.nobase_dos:

StrtOK:	rts
	endc

;************************************************************************
;**                                                                    **
;**                 TrackerPacker V3.1 Replayroutine                   **
;**                                                                    **
;**         coded by CRAZY CRACK the BlitterBlaster of Complex         **
;**                                                                    **
;**                       last coding : 26.06.94                       **
;**                                                                    **
;************************************************************************

no=0
yes=1

VLB=1		;This Version needs the System to be killed. And you have to
		;jump to "tp_play" every Vertical Blank !
CIA=0		;This Version also needs the System to be killed. But will
		;replay the module on its own, as long as the level 6 Interrupt
		;is active.
SystemCIA=-1	;Yeah, and this one replays the Module with all the wonderful
		;advantages of real CIA-timing. And it uses real System-
		;interrupts for it. So it will run perfect with Multitasking !

replaymode=CIA	;what kind of replaying do you want to use ?

pt1.1=no	;protracker v1.1 compatible (default=pt2.0)
syncs=no	;do you use vibrato or tremolo with sync ?
funk=no		;do you use the ef-comand ?
vbruse=yes	;use vectortableoffset ?
volume=no	;use volumesliding ?
split=yes	;use a splitted Song- and Samplefiles
choosestart=yes	;do you want to start the song from any other point than the
		;beginning ?
switch=no	;do you want to switch ON/OFF any voices ?
suck=no		;das ya dick wanna b suckd ?
		;(sorry, haven't been implementated yet)

tp_init:
	lea	tp_wait(pc),a0
	move	#1,(a0)
	clr	tp_pattcount-tp_wait(a0)
	move	#6,tp_speed-tp_wait(a0)
	move	#-1,tp_shitpon-tp_wait(a0)
	move.l	tp_data(pc),a1
	lea	28(a1),a1
	move	(a1)+,d7
	lea	(a1,d7.w),a2
	lsr	#3,d7
	move	(a2)+,d0
	move.l	a2,tp_pattadr-tp_wait(a0)
	move.l	a2,tp_pattadr3-tp_wait(a0)
	moveq	#0,d1
	moveq	#0,d2
tp_initpattern:
	move	(a2)+,d1
	cmp	d1,d2
	bgt.s	tp_initpattok
	move	d1,d2
tp_initpattok:
	subq	#1,d0
	bne.s	tp_initpattern
	move.l	a2,tp_pattadr2-tp_wait(a0)
	move.l	a2,tp_pattlistadr-tp_wait(a0)
	lea	8(a2,d2.w),a2
	move	(a2)+,d0
	move.l	a2,tp_pattdataadr-tp_wait(a0)
	moveq	#30,d6
	sub	d7,d6
	subq	#1,d7
	lea	(a2,d0.w),a3
	ifne	split
	move.l	tp_samples(pc),a3
	endc
	move.l	a3,d5
	lea	tp_instlist(pc),a2
tp_initinst:
	moveq	#0,d0
	move.b	(a1)+,d0
	mulu	#72,d0
	add	#tp_notelist-tp_wait,d0
	move	d0,(a2)+
	moveq	#0,d0
	move.b	(a1)+,d0
	move	d0,(a2)+
	move.l	a3,(a2)+
	lea	(a3),a4
	moveq	#0,d0
	move	(a1)+,d0
	add	d0,a3
	add	d0,a3
	moveq	#0,d1
	move	(a1)+,d1
	add	d1,a4
	add	d1,a4
	move.l	a4,(a2)+
	move	d0,(a2)+
	move	(a1)+,(a2)+
	dbra	d7,tp_initinst
	tst	d6
	bmi.s	tp_initsamplesok
	moveq	#0,d0
	moveq	#1,d1
tp_sampleinitloop2:
	move.l	d0,(a2)+
	move.l	d5,(a2)+
	move.l	d5,(a2)+
	move.l	d1,(a2)+
	dbra	d6,tp_sampleinitloop2
tp_initsamplesok:

	ifne	choosestart
	move	tp_patternnumber(pc),d1
	bsr	tp_otherpattern
	endc

	moveq	#0,d0
	moveq	#63,d1
	lea	tp_voice0dat(pc),a1
	move.b	d0,51(a1)
	move	d1,52(a1)
	move.b	d0,51+58(a1)
	move	d1,52+58(a1)
	move.b	d0,51+116(a1)
	move	d1,52+116(a1)
	move.b	d0,51+174(a1)
	move	d1,52+174(a1)

	lea	$dff002,a5
	iflt	replaymode
	move.l	4.w,a6
	jsr	-132(a6)
	else
	move	#$2000,$98(a5)
	endc
	move	d0,$a6(a5)
	move	d0,$b6(a5)
	move	d0,$c6(a5)
	move	d0,$d6(a5)
	move	#$f,$94(a5)

	iflt	replaymode
	move.l	240(a6),a0	;CIA B Interrupt serverstruktur
	move.l	(a0),a0		;CIA B Interruptstruktur
	lea	-42(a0),a6	;CIA-Resourcestruktur
	move.l	a6,tp_ciab_resource
	moveq	#3,d0
	and.b	40(a6),d0
	beq.s	tp_ciaintfree
	move.l	4.w,a6
	jsr	-138(a6)
	moveq	#-1,d0
	rts
tp_ciaintfree:
	lea	$bfd000,a1
	ori.b	#2,$1001(a1)
	clr.b	$e00(a1)
	clr.b	$f00(a1)
	move.b	#$6b,$400(a1)
	move.b	#$37,$500(a1)
	move.b	#$6b,$600(a1)
	move.b	#1,$700(a1)
	move.b	#$7f,$d00(a1)
	move.b	#$83,$d00(a1)
	move.b	#$11,$e00(a1)
	moveq	#0,d0
	lea	tp_ciab_timerastruktur(pc),a1
	jsr	-6(a6)
	moveq	#1,d0
	lea	tp_ciab_timerbstruktur(pc),a1
	jsr	-6(a6)
	else
	ifgt	replaymode
	lea	tp_dmaonint(pc),a2
	else
	lea	tp_mainint(pc),a2
	endc
	move.l	a2,tp_int1pon-tp_wait(a0)
	ifne	vbruse
	move.l	tp_vbr(pc),a1
	move.l	$78(a1),tp_oldint-tp_wait(a0)
	move.l	a2,$78(a1)
	else
	move.l	$78.w,tp_oldint-tp_wait(a0)
	move.l	a2,$78.w
	endc
	lea	tp_voiceloopint(pc),a2
	move.l	a2,tp_int3pon-tp_wait(a0)
	lea	$bfd000,a1
	ori.b	#2,$1001(a1)
	ifgt	replaymode
	clr.b	$e00(a1)
	endc
	clr.b	$f00(a1)
	ifgt	replaymode
	move.b	#$6b,$400(a1)
	move.b	#$37,$500(a1)
	endc
	move.b	#$52,$400(a1)
	move.b	#$38,$500(a1)
	move.b	#$6b,$600(a1)
	move.b	#1,$700(a1)
	move.b	#$7f,$d00(a1)
	ifgt	replaymode
	move.b	#$82,$d00(a1)
	else
	move.b	#$83,$d00(a1)
	move.b	#$11,$e00(a1)
	move	#$e000,$98(a5)
	endc
	endc

	iflt	replaymode
	move.l	4.w,a6
	jsr	-138(a6)
	moveq	#0,d0
	endc
	rts

tp_end:
	iflt	replaymode
	move.l	4.w,a6
	jsr	-132(a6)
	move.l	tp_ciab_resource(pc),a6
	moveq	#0,d0
	jsr	-12(a6)
	moveq	#1,d0
	jsr	-12(a6)
	lea	$dff002,a5
	else
	lea	$dff002,a5
	move	#$2000,$98(a5)
	ifne	vbruse
	move.l	tp_vbr(pc),a1
	move.l	tp_oldint(pc),$78(a1)
	else
	move.l	tp_oldint(pc),$78.w
	endc
	endc
	moveq	#0,d0
	move	d0,$a6(a5)
	move	d0,$b6(a5)
	move	d0,$c6(a5)
	move	d0,$d6(a5)
	move	#$f,$94(a5)
	iflt	replaymode
	move.l	4.w,a6
	jsr	-138(a6)
	endc
	rts

tp_mainint:
tp_play:
	movem.l	d0-a5,-(a7)

	lea	$dff002,a5
	ifeq	replaymode
	move	#$2000,$9a(a5)
	btst	#0,$bfdd00
	beq	tp_nomainint
	endc
	moveq	#0,d4
	lea	tp_wait(pc),a0
	clr.b	tp_dmaon-tp_wait+1(a0)
	subq	#1,(a0)
	beq	tp_newline
tp_playeffects:
	lea	tp_voice0dat+6(pc),a1
	move	(a1)+,d0
	beq.s	tp_novoice1
	lea	$9e(a5),a3
	jsr	tp_fxplaylist-4(pc,d0.w)
tp_novoice1:
	lea	tp_voice1dat+6(pc),a1
	move	(a1)+,d0
	beq.s	tp_novoice2
	lea	$ae(a5),a3
	jsr	tp_fxplaylist-4(pc,d0.w)
tp_novoice2:
	lea	tp_voice2dat+6(pc),a1
	move	(a1)+,d0
	beq.s	tp_novoice3
	lea	$be(a5),a3
	jsr	tp_fxplaylist-4(pc,d0.w)
tp_novoice3:
	lea	tp_voice3dat+6(pc),a1
	move	(a1)+,d0
	beq.s	tp_novoice4
	lea	$ce(a5),a3
	jsr	tp_fxplaylist-4(pc,d0.w)
tp_novoice4:
	move.b	tp_dmaon+1(pc),d4
	ifne	funk
	beq	tp_funkit
	bra	tp_initnewsamples
	else
	bne	tp_initnewsamples
	movem.l	(a7)+,d0-a5
	ifeq	replaymode
	nop
	rte
	else
	rts
	endc
	endc
tp_fxplaylist:
	bra	tp_voicefx1
	bra	tp_voicefx2
	bra	tp_voicefx3
	bra	tp_voicefx4
	bra	tp_voicefx5
	bra	tp_voicefx6
	bra	tp_voicefx7
	bra	tp_voicefx0
	bra	tp_voicefxe9do
	bra	tp_voicefxa
	bra	tp_voicefxecdo
	bra	tp_voicefxeddo

tp_newline:
	add.l	#1,sc_position
	move	tp_speed(pc),(a0)
	tst	tp_pattdelay-tp_wait(a0)
	beq.s	tp_nopatterndelay
	subq	#1,tp_pattdelay-tp_wait(a0)
	bra	tp_playeffects
tp_nopatterndelay:
	tst	tp_pattrepeat-tp_wait(a0)
	bne.s	tp_repeatit
	subq	#1,tp_pattcount-tp_wait(a0)
	bpl	tp_playline
	move	#63,tp_pattcount-tp_wait(a0)
	move.l	tp_pattadr(pc),a1
	move	(a1)+,tp_pattadrpon-tp_wait(a0)
	cmp.l	tp_pattadr2(pc),a1
	blt.s	tp_pattadrok
	move.l	tp_pattadr3(pc),a1
tp_pattadrok:
	move.l	a1,tp_pattadr-tp_wait(a0)
tp_repeatit:
	clr	tp_pattrepeat-tp_wait(a0)
	move	tp_pattadrpon(pc),d0
	move.l	tp_pattlistadr(pc),a1
	movem	(a1,d0.w),d0-d3
	moveq	#-2,d4
	move.l	tp_pattdataadr(pc),a1
	move.b	d4,tp_voice0dat-tp_wait+1(a0)
	add.l	a1,d0
	move.l	d0,tp_voice0dat-tp_wait+2(a0)
	move.b	d4,tp_voice1dat-tp_wait+1(a0)
	add.l	a1,d1
	move.l	d1,tp_voice1dat-tp_wait+2(a0)
	move.b	d4,tp_voice2dat-tp_wait+1(a0)
	add.l	a1,d2
	move.l	d2,tp_voice2dat-tp_wait+2(a0)
	move.b	d4,tp_voice3dat-tp_wait+1(a0)
	add.l	a1,d3
	move.l	d3,tp_voice3dat-tp_wait+2(a0)

	move	tp_shitpon(pc),d0
	bne.s	tp_noshit
	moveq	#1,d0
	bra.s	tp_shit
tp_noshit:
	moveq	#0,d0
tp_shit:

	add	tp_newpattpos(pc),d0
	beq.s	tp_playline
	cmp.w	#64,d0
	bne.s	tp_pattinrange
	clr	tp_newpattpos-tp_wait(a0)
	clr	tp_pattcount-tp_wait(a0)
	moveq	#-1,d7
	move	d7,tp_shitpon-tp_wait(a0)
	bra	tp_nopatterndelay
tp_pattinrange:

	sub	d0,tp_pattcount-tp_wait(a0)
	clr	tp_newpattpos-tp_wait(a0)
	lea	tp_voice0dat+2(pc),a1
	subq	#1,d0
	moveq	#3,d7
tp_pattinitloop:
	move	d0,d6
	moveq	#0,d2
	move.l	(a1),a2
tp_pattsearchloop:
	move.b	(a2)+,d1
	bmi.s	tp_pattslab1
	moveq	#$f,d1
	and.b	(a2)+,d1
	beq.s	tp_pattslab3
	bra.s	tp_pattslab2
tp_pattslab1:
	add.b	d1,d1
	bpl.s	tp_pattslab2
	asr.b	#1,d1
	addq.b	#1,d1
	add.b	d1,d6
	bpl.s	tp_pattslab3
	add.b	d6,d6
	subq.b	#2,d6
	move	d6,d2
	moveq	#0,d6
	bra.s	tp_pattslab3
tp_pattslab2:
	addq.l	#1,a2
tp_pattslab3:
	dbra	d6,tp_pattsearchloop
	move.b	d2,-1(a1)
	move.l	a2,(a1)
	lea	58(a1),a1
	dbra	d7,tp_pattinitloop

tp_playline:
	move	#$1f0,d3
	move	#-1,tp_shitpon-tp_wait(a0)
	lea	tp_voice0dat+1(pc),a1
	addq.b	#2,(a1)+
	bmi.s	tp_playvoice0end
	moveq	#1,d4
	lea	$9e(a5),a3
	bsr	tp_playvoice
tp_playvoice0end:
	move	26(a1),$a4(a5)
	lea	tp_voice1dat+1(pc),a1
	addq.b	#2,(a1)+
	bmi.s	tp_playvoice1end
	moveq	#2,d4
	lea	$ae(a5),a3
	bsr	tp_playvoice
tp_playvoice1end:
	move	26(a1),$b4(a5)
	lea	tp_voice2dat+1(pc),a1
	addq.b	#2,(a1)+
	bmi.s	tp_playvoice2end
	moveq	#4,d4
	lea	$be(a5),a3
	bsr	tp_playvoice
tp_playvoice2end:
	move	26(a1),$c4(a5)
	lea	tp_voice3dat+1(pc),a1
	addq.b	#2,(a1)+
	bmi.s	tp_playvoice3end
	moveq	#8,d4
	lea	$ce(a5),a3
	bsr.s	tp_playvoice
tp_playvoice3end:
	move	26(a1),$d4(a5)
	move.b	tp_dmaon+1(pc),d4
tp_initnewsamples:
	ifne	switch
	move.b	tp_voiceoff(pc),d3
	not.b	d3
	and.b	d3,d4
	move.b	d4,tp_dmaon+1-tp_wait(a0)
	endc
	move	d4,$94(a5)
	ifeq	replaymode
	lea	tp_dmaonint(pc),a1
	ifne	vbruse
	move.l	tp_vbr(pc),a2
	move.l	a1,$78(a2)
	else
	move.l	a1,$78.w
	endc
	endc
	ifgt	replaymode
	move	#$e000,$98(a5)
	endc
	move.b	#$19,$bfdf00
	ifne	funk
tp_funkit:
	lea	tp_voice0dat+48(pc),a1
	moveq	#3,d7
tp_funkloop:
	move.b	(a1)+,d4
	beq.s	tp_funkend
	move.b	tp_funklist-tp_wait(a0,d4.w),d4
	add.b	d4,(a1)
	bpl.s	tp_funkend
	clr.b	(a1)
	move.l	-31(a1),a2
	movem	-25(a1),d0-d1
	addq	#1,d1
	add	d0,d0
	cmp	d0,d1
	blo.s	tp_funkok
	moveq	#0,d1
tp_funkok:
	not.b	(a2,d1.w)
	move	d1,-23(a1)
tp_funkend:
	lea	57(a1),a1
	dbra	d7,tp_funkloop
	endc
tp_nomainint:
	movem.l	(a7)+,d0-a5
	ifeq	replaymode
	nop
	rte
	else
	rts
	endc
tp_playvoice:
	move.l	(a1)+,a2
	moveq	#0,d0
	move.b	(a2)+,d0
	bmi	tp_playnonewnote
	moveq	#0,d1
	move.b	(a2)+,d1
	moveq	#$f,d2
	and.b	d1,d2
	beq.s	tp_noeffect
	move.b	(a2)+,3(a1)
	add	d2,d2
	add	d2,d2
tp_noeffect:
	move	d2,(a1)
	add.b	d0,d0
	bpl.s	tp_noupperinst
	eor.b	#$fe,d0
	bset	#8,d1
tp_noupperinst:
	and	d3,d1
	beq.s	tp_nonewinst
	move.w	d1,d5
	lsr.w	#4,d5
	movem.l	tp_instlist-tp_wait-16(a0,d1.w),d5-d7/a4
	movem.l	d5-d7/a4,4(a1)

	ifne	switch
	move.b	tp_voiceoff(pc),d6
	and.b	d4,d6
	bne.s	tp_no1
	ifne	volume
	mulu	tp_volume(pc),d5
	lsr	#8,d5
	endc
	move	d5,8(a3)
tp_no1	else
	ifne	volume
	mulu	tp_volume(pc),d5
	lsr	#8,d5
	endc
	move	d5,8(a3)
	endc

	ifne	funk
	clr	20(a1)
	endc
tp_nonewinst:
	move.l	a2,-(a1)
	tst	d0
	beq.s	tp_newnoteend
	jsr	tp_fxinitlist(pc,d2.w)
	add	8(a1),d0
	move	-2(a0,d0.w),26(a1)
	or.b	d4,tp_dmaon-tp_wait+1(a0)
	ifne	syncs
	tst.b	32(a1)
	beq.s	tp_novibnoc
	clr.b	35(a1)
tp_novibnoc:
	tst.b	38(a1)
	beq.s	tp_notremnoc
	clr.b	41(a1)
tp_notremnoc:
	endc
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	d4,d5
	bne.s	tp_no2
	move.l	12(a1),(a3)+
	move	20(a1),(a3)
tp_no2	else
	move.l	12(a1),(a3)+
	move	20(a1),(a3)
	endc
	rts
tp_playnonewnote:
	add.b	d0,d0
	bmi.s	tp_donothing
	move	d0,(a1)
	move.b	(a2)+,3(a1)
	move.l	a2,-(a1)
	move	d0,d2
	moveq	#0,d0
tp_newnoteend:
	jmp	tp_fxinitlist(pc,d2.w)
tp_donothing:
	clr	(a1)
	move.l	a2,-(a1)
	ifne	pt1.1
	move.b	d0,-(a1)
	addq.l	#6,(a7)
	else
	move.b	d0,-1(a1)
	endc
tp_fxinitlist:
	rts
	nop
	rts
	nop
	rts
	nop
	bra	tp_voicefx3init
	bra	tp_voicefx4init
	bra	tp_voicefx5init
	rts
	nop
	bra	tp_voicefx7init
	bra	tp_voicefx0init
	bra	tp_voicefx9
	rts
	nop
	bra	tp_voicefxb
	bra	tp_voicefxc
	bra	tp_voicefxd
	bra	tp_voicefxeinit
tp_voicefxf:
	clr	4(a1)
	move	6(a1),d1
	bne	spdoke
	move.b	#1,quit
spdoke:	cmp	#32,d1
	bge.s	tp_voicefxcia
	move	d1,tp_speed-tp_wait(a0)
	move	d1,(a0)
	rts
tp_voicefxcia:
	ifle	replaymode
	move.l	#1773447,d2
	divu	d1,d2
	move.b	d2,$bfd400
	lsr	#8,d2
	move.b	d2,$bfd500
	endc
	rts
	
tp_voicefx0init:
	tst	d0
	beq.s	tp_voicefx0initlab1
	cmp	#70,d0
	beq.s	tp_voicefx0end
	add	8(a1),d0
	lea	-2(a0,d0.w),a4
	move.l	a4,52(a1)
	addq.l	#4,(a7)
	rts
tp_voicefx0initlab1:
	move	8(a1),d2
	lea	70(a0,d2.w),a4
	move.l	a4,d2
	lea	-34(a4),a4
	move	26(a1),d1
	cmp	(a4),d1
	bhs.s	.high18
	lea	18(a4),a4
	cmp	(a4),d1
	bhs.s	.high10
.low8:
	addq	#8,a4
	cmp	(a4),d1
	bhs.s	.high6
.low4:
	addq	#4,a4
	cmp	(a4),d1
	bhs.s	.high2
.low2:
	addq	#4,a4
	cmp	(a4),d1
	bhs.s	.high2
.low0:
	addq	#2,a4
	cmp	(a4),d1
	bhs.s	.found
	subq	#2,a4
	bra.s	.found
.high18:
	lea	-18(a4),a4
	cmp	(a4),d1
	blt.s	.low8
.high10:
	lea	-10(a4),a4
	cmp	(a4),d1
	blt.s	.low4
.high6:
	subq	#6,a4
	cmp	(a4),d1
	blt.s	.low2
.high2:
	cmp	-(a4),d1
	blt.s	.low0
.found:
	cmp.l	a4,d2
	beq.s	tp_voicefx0end
	move.l	a4,52(a1)
	rts
tp_voicefx0end:
	clr	4(a1)
	rts

	dc.b	1,0,-1,1,0,-1,1,0,-1,1,0,-1,1,0,-1,1
	dc.b	0,-1,1,0,-1,1,0,-1,1,0,-1,1,0,-1,1,0
tp_voicefx0:
	move	(a1)+,d1
	move	18(a1),d0
	move	(a0),d2
	sub	tp_speed(pc),d2
	move.b	tp_voicefx0-1(pc,d2.w),d2
	beq.s	tp_arp0
	bmi.s	tp_arp2
	lsr	#4,d1
	bra.s	tp_arp1
tp_arp2:
	and	#$f,d1
tp_arp1:
	move.l	44(a1),a4
	add	d1,d1

	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-10(a1),d5
	bne.s	tp_no3
	move	(a4,d1.w),6(a3)
tp_no3:
	else
	move	(a4,d1.w),6(a3)
	endc
	rts
tp_arp0:
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-10(a1),d5
	bne.s	tp_no4
	move	d0,6(a3)
tp_no4:	else
	move	d0,6(a3)
	endc
	rts

tp_voicefx1:
	move	20(a1),d1
	sub	(a1),d1
	and	#$fff,d1
	moveq	#113,d2
	cmp	d2,d1
	bpl.s	tp_voicefx1lab1
	move	d2,d1			;and #$f000,d0;or d1,d0 ???
tp_voicefx1lab1:
	move	d1,20(a1)
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-8(a1),d5
	bne.s	tp_no5
	move	d1,6(a3)
tp_no5:	else
	move	d1,6(a3)
	endc
	rts

tp_voicefx2:
	move	20(a1),d1
	add	(a1),d1
	cmp	#856,d1
	bmi.s	tp_voicefx2lab1
	move	#856,d1
	clr	-2(a1)
tp_voicefx2lab1:
	move	d1,20(a1)
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-8(a1),d5
	bne.s	tp_no6
	move	d1,6(a3)
tp_no6:	else
	move	d1,6(a3)
	endc
	rts

tp_voicefx3init:
	move	6(a1),d1
	beq.s	tp_voicefx5init
	tst	30(a1)
	bpl.s	tp_fx3initnochange
	neg	d1
tp_fx3initnochange:
	move	d1,30(a1)
tp_voicefx5init:
	tst	d0
	beq.s	tp_voicefx3initlab6
	addq.l	#4,a7
	addq.l	#6,(a7)
	move	8(a1),d2
;	cmp	#72*8+(tp_notelist-tp_wait),d2
;	blt.s	tp_voicefx3initlab3
;	subq	#2,d0
;	bgt.s	tp_voicefx3initlab3
;	moveq	#2,d0
tp_voicefx3initlab3:
	add	d0,d2
	move	-2(a0,d2.w),d0
	move	d0,28(a1)
	sub	26(a1),d0
	bpl.s	tp_voicefx3initlab5
	tst	30(a1)
	bmi.s	tp_voicefx3initlab4
	neg	30(a1)
tp_voicefx3initlab4:
	rts
tp_voicefx3initlab5:
	tst	30(a1)
	bpl.s	tp_voicefx3initlab6
	neg	30(a1)
tp_voicefx3initlab6:
	rts

tp_voicefx3:
	move	22(a1),d2
	beq.s	tp_voicefx3end
	move	24(a1),d1
	bmi.s	tp_voicefx3sub
	add	20(a1),d1
	cmp	d2,d1
	blt.s	tp_voicefx3ok
	bra.s	tp_voicefx3setok
tp_voicefx3sub:
	add	20(a1),d1
	cmp	d2,d1
	bgt.s	tp_voicefx3ok
tp_voicefx3setok:
	move	d2,d1
	clr	22(a1)
	clr	-2(a1)
tp_voicefx3ok:
	move	d1,20(a1)
	tst.b	42(a1)
	beq.s	tp_voicefx3skip
	move	2(a1),d2
	lea	(a0,d2.w),a4
	moveq	#35,d2
tp_voicefx3search:
	cmp	(a4)+,d1
	bhs.s	tp_voicefx3notefound
	dbra	d2,tp_voicefx3search
tp_voicefx3notefound:
	move	-2(a4),d1
tp_voicefx3skip:
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-8(a1),d5
	bne.s	tp_no15
	move	d1,6(a3)
tp_no15:
	else
	move	d1,6(a3)
	endc
tp_voicefx3end:
	rts

tp_voicefx5:
	bsr.s	tp_voicefx3
	bra.s	tp_voicefxa

tp_voicefx4init:
	move	6(a1),d1
	beq.s	tp_voicefx4initend
	moveq	#$f,d2
	and	d1,d2
	beq.s	tp_voicefx4initlab1
	move	d2,36(a1)
tp_voicefx4initlab1:
	and	#$f0,d1
	beq.s	tp_voicefx4initend
	lsr	#2,d1
	move.b	d1,34(a1)
tp_voicefx4initend:
	rts

tp_voicefx4:
	moveq	#$7f,d0
	and.b	29(a1),d0
	move.b	27(a1),d2
	beq.s	tp_voicefx4sine
	add	d0,d0
	subq.b	#1,d2
	beq.s	tp_voicefx4rampdown
	st	d0
	bra.s	tp_voicefx4set
tp_voicefx4rampdown:
	tst.b	29(a1)
	bpl.s	tp_voicefx4set
	not.b	d0	
	bra.s	tp_voicefx4set
tp_voicefx4sine:
	lsr	#2,d0
	move.b	tp_vibratolist-tp_wait(a0,d0.w),d0
tp_voicefx4set:
	mulu	30(a1),d0
	lsr	#7,d0
	tst.b	29(a1)
	bpl.s	tp_voicefx4nosub
	neg	d0
tp_voicefx4nosub:
	add	20(a1),d0
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-8(a1),d5
	bne.s	tp_no7
	move	d0,6(a3)
tp_no7:	else
	move	d0,6(a3)
	endc
	move.b	28(a1),d0
	add.b	d0,29(a1)
	rts

tp_voicefx6:
	bsr.s	tp_voicefx4
tp_voicefxa:
	move	(a1),d1
	add.b	5(a1),d1
	bmi.s	tp_voicefxalab1
	moveq	#$40,d2
	cmp.b	d2,d1
	bcs.s	tp_voicefxaend
	move	d2,d1
	clr	-2(a1)
	bra.s	tp_voicefxaend
tp_voicefxalab1:
	moveq	#0,d1
	clr	-2(a1)
tp_voicefxaend:
	move	d1,4(a1)
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-8(a1),d5
	bne.s	tp_no8
	ifne	volume
	mulu	tp_volume(pc),d1
	lsr	#8,d1
	endc
	move	d1,8(a3)
tp_no8:	else
	ifne	volume
	mulu	tp_volume(pc),d1
	lsr	#8,d1
	endc
	move	d1,8(a3)
	endc
	rts

tp_voicefx7init:
	move	6(a1),d1
	beq.s	tp_voicefx7initend
	moveq	#$f,d2
	and	d1,d2
	beq.s	tp_voicefx7initlab1
	move	d2,42(a1)
tp_voicefx7initlab1:
	and	#$f0,d1
	beq.s	tp_voicefx7initend
	lsr	#2,d1
	move.b	d1,40(a1)
tp_voicefx7initend:
	rts

tp_voicefx7:
	moveq	#$7f,d0
	and.b	35(a1),d0
	move.b	33(a1),d2
	beq.s	tp_voicefx7sine
	add	d0,d0
	subq.b	#1,d2
	beq.s	tp_voicefx7rampdown
	st	d0
	bra.s	tp_voicefx7set
tp_voicefx7rampdown:
	tst.b	35(a1)
	bpl.s	tp_voicefx7set
	not.b	d0	
	bra.s	tp_voicefx7set
tp_voicefx7sine:
	lsr	#2,d0
	move.b	tp_vibratolist-tp_wait(a0,d0.w),d0
tp_voicefx7set:
	mulu	36(a1),d0
	lsr	#7,d0
	tst.b	35(a1)
	bpl.s	tp_voicefx7nosub
	neg	d0
tp_voicefx7nosub:
	add	4(a1),d0
	bpl.s	tp_voicefx7noneg
	clr	d0
	bra.s	tp_voicefx7ok
tp_voicefx7noneg:
	moveq	#40,d1
	cmp	d1,d0
	bls.s	tp_voicefx7ok
	move	d1,d0
tp_voicefx7ok:
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-8(a1),d5
	bne.s	tp_no9
	ifne	volume
	mulu	tp_volume(pc),d1
	lsr	#8,d1
	endc
	move	d1,8(a3)
tp_no9:	else
	ifne	volume
	mulu	tp_volume(pc),d1
	lsr	#8,d1
	endc
	move	d1,8(a3)
	endc
	move.b	34(a1),d0
	add.b	d0,35(a1)
	rts

tp_voicefx9:
	tst	d0
	beq.s	tp_voicefx9normal

	ifne	funk
	moveq	#0,d1
	move.b	46(a1),d1
	beq.s	tp_voicefx9funkend
	move.b	tp_funklist-tp_wait(a0,d1.w),d1
	add.b	d1,47(a1)
	bpl.s	tp_voicefx9funkend
	clr.b	47(a1)
	move.l	16(a1),a2
	movem	22(a1),d1-d2
	addq	#1,d2
	add	d1,d1
	cmp	d1,d2
	blo.s	tp_voicefx9funkok
	moveq	#0,d2
tp_voicefx9funkok:
	not.b	(a2,d2.w)
	move	d2,24(a1)
tp_voicefx9funkend:
	endc

	move.l	(a7),-(a7)
	lea	tp_voicefx9after(pc),a4
	move.l	a4,4(a7)
tp_voicefx9normal:
	clr	4(a1)
	moveq	#0,d1
	move	6(a1),d1
	beq.s	tp_voicefx9after
	lsl	#7,d1
	move	d1,44(a1)
tp_voicefx9after:
	move	44(a1),d1
	sub	d1,20(a1)
	ble.s	tp_voicefx9skip
	add	d1,d1
	add.l	d1,12(a1)
	rts
tp_voicefx9skip:
	move	#1,20(a1)
	rts

tp_voicefxb:
	clr	4(a1)
	move	6(a1),d1
	clr	tp_pattcount-tp_wait(a0)
tp_otherpattern:
	move.l	tp_pattadr3(pc),a1
	add.w	d1,d1
	add.w	d1,a1
	move.l	a1,tp_pattadr-tp_wait(a0)
	rts

tp_voicefxc:
	move	6(a1),d1
	move	d1,10(a1)
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	d4,d5
	bne.s	tp_no10
	ifne	volume
	mulu	tp_volume(pc),d1
	lsr	#8,d1
	endc
	move	d1,8(a3)
tp_no10:
	else
	ifne	volume
	mulu	tp_volume(pc),d1
	lsr	#8,d1
	endc
	move	d1,8(a3)
	endc
	clr	4(a1)
	rts

tp_voicefxd:
	clr	4(a1)
	clr	tp_pattcount-tp_wait(a0)
	move	6(a1),tp_newpattpos-tp_wait(a0)
	clr.b	tp_shitpon-tp_wait(a0)
	rts

tp_voicefxeinit:
	moveq	#-$10,d1
	and	6(a1),d1
	lsr	#2,d1
	jmp	tp_voicefxeinitlist(pc,d1.w)
tp_voicefxeinitlist:
	bra	tp_voicefxe0
	bra	tp_voicefxe1
	bra	tp_voicefxe2
	bra	tp_voicefxe3
	bra	tp_voicefxe4
	bra	tp_voicefxe5
	bra	tp_voicefxe6
	bra	tp_voicefxe7
	rts
	nop
	bra	tp_voicefxe9
	bra	tp_voicefxea
	bra	tp_voicefxeb
	bra	tp_voicefxec
	bra	tp_voicefxed
	bra	tp_voicefxee
tp_voicefxef:
	clr	4(a1)
	ifne	funk
	moveq	#$f,d2
	and	6(a1),d2
	move.b	d2,46(a1)
	endc
	rts

tp_voicefxe0:
	clr	4(a1)
	moveq	#1,d2
	and	6(a1),d2
	bne.s	tp_voicefxe0clr
	bclr	#1,$bfe001
	rts
tp_voicefxe0clr:
	bset	d2,$bfe001
	rts

tp_voicefxe1:
	tst	d0
	beq.s	tp_voicefxe1ok
	move	8(a1),d1
	add	d0,d1
	move	-2(a0,d1.w),26(a1)
	moveq	#10,d0
	add.l	d0,(a7)
tp_voicefxe1ok:
	addq.l	#4,a1
	clr	(a1)+
	and	#$f,(a1)
	bsr	tp_voicefx1
	subq.l	#6,a1
	rts

tp_voicefxe2:
	tst	d0
	beq.s	tp_voicefxe2ok
	move	8(a1),d1
	add	d0,d1
	move	-2(a0,d1.w),26(a1)
	moveq	#10,d0
	add.l	d0,(a7)
tp_voicefxe2ok:
	addq.l	#4,a1
	clr	(a1)+
	and	#$f,(a1)
	bsr	tp_voicefx2
	subq.l	#6,a1
	rts

tp_voicefxe3:
	clr	4(a1)
	moveq	#$f,d2
	and	6(a1),d2
	move.b	d2,48(a1)
	rts

tp_voicefxe4:
	clr	4(a1)
	moveq	#$3,d2
	and	6(a1),d2
	move.b	d2,33(a1)
	btst	#2,6(a1)
	beq.s	tp_voicefxe4ok
	st	32(a1)
	rts
tp_voicefxe4ok:
	clr.b	32(a1)
	rts

tp_voicefxe5:
	clr	4(a1)
	moveq	#$f,d2
	and	6(a1),d2
	mulu	#72,d2
	add	#tp_notelist-tp_wait,d2
	move	d2,8(a1)
	rts

tp_voicefxe6:
	clr	4(a1)
	moveq	#$f,d2
	and	6(a1),d2
	beq.s	tp_voicefxe6start
	subq.b	#1,49(a1)
	beq.s	tp_voicefxe6end
	bpl.s	tp_voicefxe6doloop
	move.b	d2,49(a1)
tp_voicefxe6doloop:
	moveq	#63,d2
	move	d2,tp_pattcount-tp_wait(a0)
	sub	50(a1),d2
	move	d2,tp_newpattpos-tp_wait(a0)
	st	tp_pattrepeat-tp_wait(a0)
tp_voicefxe6end:
	rts
tp_voicefxe6start:
	move	tp_pattcount(pc),50(a1)
	rts

tp_voicefxe7:
	clr	4(a1)
	moveq	#$f,d2
	and	6(a1),d2
	move.b	d2,39(a1)
	btst	#2,6(a1)
	beq.s	tp_voicefxe7ok
	st	38(a1)
	rts
tp_voicefxe7ok:
	clr.b	38(a1)
	rts

tp_voicefxe9:
	move	#$9*4,4(a1)
	and	#$f,6(a1)
	beq.s	tp_voicefxe9clear
	tst	d0
	bne.s	tp_voicefxe9end
tp_voicefxe9clear:
	clr	4(a1)
tp_voicefxe9end:
	rts
tp_voicefxe9do:
	moveq	#0,d1
	move	tp_speed(pc),d1
	sub	(a0),d1
	divu	(a1),d1
	swap	d1
	tst	d1
	bne.s	tp_voicefxe9end
tp_voicefxe9play:
	move.b	-8(a1),d1
	or.b	d1,tp_dmaon-tp_wait+1(a0)
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-8(a1),d5
	bne.s	tp_no11
	move.l	6(a1),(a3)+
	move	14(a1),(a3)
tp_no11:
	else
	move.l	6(a1),(a3)+
	move	14(a1),(a3)
	endc
	rts

tp_voicefxea:
	addq.l	#4,a1
	clr	(a1)+
	and	#$f,(a1)
	bsr	tp_voicefxa
	subq.l	#6,a1
	rts

tp_voicefxeb:
	addq.l	#4,a1
	clr	(a1)+
	and	#$f,(a1)
	neg.b	1(a1)
	bsr	tp_voicefxa
	subq.l	#6,a1
	rts

tp_voicefxec:
	move	#$b*4,4(a1)
	and	#$f,6(a1)
	bne.s	tp_voicefxecend
	clr	4(a1)
	clr	10(a1)
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	d4,d5
	bne.s	tp_no12
	clr	8(a3)
tp_no12:
	else
	clr	8(a3)
	endc
tp_voicefxecend:
	rts
tp_voicefxecdo:
	subq	#1,(a1)
	bne.s	tp_voicefxecend
	clr	-(a1)
	clr	6(a1)
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-6(a1),d5
	bne.s	tp_no13
	clr	8(a3)
tp_no13:
	else
	clr	8(a3)
	endc
	rts

tp_voicefxed:
	move	#$c*4,4(a1)
	tst	d0
	beq.s	tp_voicefxednoinit
	and	#$f,6(a1)
	beq.s	tp_voicefxednoinit
	add	8(a1),d0
	move	-2(a0,d0.w),26(a1)
	addq	#4,a7
	addq.l	#6,(a7)
	rts
tp_voicefxednoinit:
	clr	4(a1)
tp_voicefxedend:
	rts
tp_voicefxeddo:
	subq	#1,(a1)
	bne.s	tp_voicefxedend
	clr	-2(a1)
	ifne	switch
	move.b	tp_voiceoff(pc),d5
	and.b	-8(a1),d5
	bne.s	tp_no14
	move	20(a1),6(a3)
tp_no14:
	else
	move	20(a1),6(a3)
	endc
	bra	tp_voicefxe9play

tp_voicefxee:
	clr	4(a1)
	moveq	#$f,d1
	and	6(a1),d1
	move	d1,tp_pattdelay-tp_wait(a0)
	clr.b	tp_shitpon-tp_wait+1(a0)
	rts

tp_dmaonint:
	iflt	replaymode
	move.l	a0,-(a7)
	move.b	#$19,$bfdf00
	move	tp_dmaon(pc),$dff096
	move.l	tp_ciab_resource(pc),a0
	move.l	#tp_voiceloopint,80(a0)
	move.l	(a7)+,a0
	rts
	else
	btst	#1,$bfdd00
	beq.s	tp_nodmaonint
	move.b	#$19,$bfdf00
	move	tp_dmaon(pc),$dff096
	ifne	vbruse
	move.l	a0,-(a7)
	move.l	tp_vbr(pc),a0
	move.l	tp_int3pon(pc),$78(a0)
	move.l	(a7)+,a0
	else
	move.l	tp_int3pon(pc),$78.w
	endc
tp_nodmaonint:
	move	#$2000,$dff09c
	nop
	rte
	endc

tp_voiceloopint:
	iflt	replaymode
	move.l	a0,-(a7)
	else
	btst	#1,$bfdd00
	beq.s	tp_novoiceloopint
	endc
	ifne	switch
	btst	#0,tp_voiceoff
	bne.s	tp_intnovoice0
	move.l	tp_voice0dat+18(pc),$dff0a0
	move	tp_voice0dat+24(pc),$dff0a4
tp_intnovoice0
	btst	#1,tp_voiceoff
	bne.s	tp_intnovoice1
	move.l	tp_voice1dat+18(pc),$dff0b0
	move	tp_voice1dat+24(pc),$dff0b4
tp_intnovoice1
	btst	#2,tp_voiceoff
	bne.s	tp_intnovoice2
	move.l	tp_voice2dat+18(pc),$dff0c0
	move	tp_voice2dat+24(pc),$dff0c4
tp_intnovoice2
	btst	#3,tp_voiceoff
	bne.s	tp_intnovoice3
	move.l	tp_voice3dat+18(pc),$dff0d0
	move	tp_voice3dat+24(pc),$dff0d4
tp_intnovoice3
	else
	move.l	tp_voice0dat+18(pc),$dff0a0
	move	tp_voice0dat+24(pc),$dff0a4
	move.l	tp_voice1dat+18(pc),$dff0b0
	move	tp_voice1dat+24(pc),$dff0b4
	move.l	tp_voice2dat+18(pc),$dff0c0
	move	tp_voice2dat+24(pc),$dff0c4
	move.l	tp_voice3dat+18(pc),$dff0d0
	move	tp_voice3dat+24(pc),$dff0d4
	endc
	iflt	replaymode
	move.l	tp_ciab_resource(pc),a0
	move.l	#tp_dmaonint,80(a0)
	move.l	(a7)+,a0
	rts
	else
	ifne	vbruse
	move.l	a0,-(a7)
	move.l	tp_vbr(pc),a0
	move.l	tp_int1pon(pc),$78(a0)
	move.l	(a7)+,a0
	else
	move.l	tp_int1pon(pc),$78.w
	endc
tp_novoiceloopint:
	move	#$2000,$dff09c
	nop
	rte
	endc

tp_shitpon:dc		-1
tp_pattcount:dc		1
tp_wait:dc		1
tp_pattadr:dc.l		0
tp_pattadr2:dc.l	0
tp_pattadr3:dc.l	0
tp_pattlistadr:dc.l	0
tp_pattdataadr:dc.l	0
tp_oldint:dc.l		0
tp_int1pon:dc.l		0
tp_int3pon:dc.l		0
tp_newpattpos:dc	0
tp_pattdelay:dc		0
tp_pattrepeat:dc	0
tp_pattadrpon:dc	0
	ifne	choosestart
tp_patternnumber:dc	0
	endc
tp_data:dc.l		0
	ifne	split
tp_samples:dc.l		0
	endc
	ifne	switch
tp_voiceoff:dc.b	%0000		;Bitx=Voicex (0=ON,1=OFF)
	even
	endc
tp_dmaon:dc		$8000
tp_funklist:
	dc.b	0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128
tp_vibratolist:
	dc.b	0,24,49,74,97,120,141,161
	dc.b	180,197,212,224,235,244,250,253
	dc.b	255,253,250,244,235,224,212,197
	dc.b	180,161,141,120,97,74,49,24
tp_instlist:blk.b	31*16,0
tp_speed:dc		6
	ifne	vbruse
tp_vbr:dc.l		0
	endc
	ifne	volume
tp_volume:dc		255		;0=off,255=max. volume
	endc
	iflt	replaymode
tp_ciab_resource	dc.l	0
tp_ciab_timerastruktur
	dc.l	0,0
	dc.b	2,0
	dc.l	tp_timeraname
	dc.l	0,tp_mainint
tp_ciab_timerbstruktur
	dc.l	0,0
	dc.b	2,0
	dc.l	tp_timerbname
	dc.l	0,tp_dmaonint
tp_timeraname
	dc.b	"TP_TimerA",0
tp_timerbname
	dc.b	"TP_TimerB",0
	even
	endc
tp_notelist:
	dc	856,808,762,720,678,640,604,570,538,508,480,453
	dc	428,404,381,360,339,320,302,285,269,254,240,226
	dc	214,202,190,180,170,160,151,143,135,127,120,113

	dc	850,802,757,715,674,637,601,567,535,505,477,450
	dc	425,401,379,357,337,318,300,284,268,253,239,225
	dc	213,201,189,179,169,159,150,142,134,126,119,113

	dc	844,796,752,709,670,632,597,563,532,502,474,447
	dc	422,398,376,355,335,316,298,282,266,251,237,224
	dc	211,199,188,177,167,158,149,141,133,125,118,112

	dc	838,791,746,704,665,628,592,559,528,498,470,444
	dc	419,395,373,352,332,314,296,280,264,249,235,222
	dc	209,198,187,176,166,157,148,140,132,125,118,111

	dc	832,785,741,699,660,623,588,555,524,495,467,441
	dc	416,392,370,350,330,312,294,278,262,247,233,220
	dc	208,196,185,175,165,156,147,139,131,124,117,110

	dc	826,779,736,694,655,619,584,551,520,491,463,437
	dc	413,390,368,347,328,309,292,276,260,245,232,219
	dc	206,195,184,174,164,155,146,138,130,123,116,109

	dc	820,774,730,689,651,614,580,547,516,487,460,434
	dc	410,387,365,345,325,307,290,274,258,244,230,217
	dc	205,193,183,172,163,154,145,137,129,122,115,109

	dc	814,768,725,684,646,610,575,543,513,484,457,431
	dc	407,384,363,342,323,305,288,272,256,242,228,216
	dc	204,192,181,171,161,152,144,136,128,121,114,108

	dc	907,856,808,762,720,678,640,604,570,538,508,480
	dc	453,428,404,381,360,339,320,302,285,269,254,240
	dc	226,214,202,190,180,170,160,151,143,135,127,120

	dc	900,850,802,757,715,675,636,601,567,535,505,477
	dc	450,425,401,379,357,337,318,300,284,268,253,238
	dc	225,212,200,189,179,169,159,150,142,134,126,119

	dc	894,844,796,752,709,670,632,597,563,532,502,474
	dc	447,422,398,376,355,335,316,298,282,266,251,237
	dc	223,211,199,188,177,167,158,149,141,133,125,118

	dc	887,838,791,746,704,665,628,592,559,528,498,470
	dc	444,419,395,373,352,332,314,296,280,264,249,235
	dc	222,209,198,187,176,166,157,148,140,132,125,118

	dc	881,832,785,741,699,660,623,588,555,524,494,467
	dc	441,416,392,370,350,330,312,294,278,262,247,233
	dc	220,208,196,185,175,165,156,147,139,131,123,117

	dc	875,826,779,736,694,655,619,584,551,520,491,463
	dc	437,413,390,368,347,328,309,292,276,260,245,232
	dc	219,206,195,184,174,164,155,146,138,130,123,116

	dc	868,820,774,730,689,651,614,580,547,516,487,460
	dc	434,410,387,365,345,325,307,290,274,258,244,230
	dc	217,205,193,183,172,163,154,145,137,129,122,115

	dc	862,814,768,725,684,646,610,575,543,513,484,457
	dc	431,407,384,363,342,323,305,288,272,256,242,228
	dc	216,203,192,181,171,161,152,144,136,128,121,114

tp_voice0dat:
	dc.b	1
	blk.b	57,0
tp_voice1dat:
	dc.b	2
	blk.b	57,0
tp_voice2dat:
	dc.b	4
	blk.b	57,0
tp_voice3dat:
	dc.b	8
	blk.b	57,0

		section	ChipBSS,bss_c
chipmem:	ds.b	(123696+511)&$fffffe00	; ho_requirements_chipmem
		section	BSS,bss
gb_copinit_old:	ds.l	1
gb_ActiView_old:ds.l	1
vbi_old:	ds.l	1
cia_old:	ds.l	1
currentdir_old:	ds.l	1
cachebits_old:	ds.l	1
dmaconr_old:	ds.w	1
intenar_old:	ds.w	1
base_icon:	ds.l	1
base_graphics:	ds.l	1
base_dos:	ds.l	1
diskobject:	ds.l	1
message_dos:	ds.l	1
ra_rdargs:	ds.l	1
ra_array:
loop:		ds.l	1
lock:		ds.l	1
part:		ds.l	1
part_main:	ds.l	1
part_vbi:	ds.l	1
sc_position:	ds.l	1
table_fade:	ds.b	17*16
quit:		ds.b	1
render:		ds.b	1
fastmem:	ds.b	(180630+511)&$fffffe00	; sm_requirements_fastmem

		section	ChipData,data_c
ne_cl:		dc.w $0801,$fffe
ne_cl_fmode:	dc.w fmode,%0000000000000000
ne_cl_bplcon3:	dc.w bplcon3,%0000110000110000
ne_cl_bplcon2:	dc.w bplcon2,%0000000000100100
ne_cl_bplcon1:	dc.w bplcon1,%0000000000000000
ne_cl_bplcon0:	dc.w bplcon0,%0000000000000000
ne_cl_diwstrt:	dc.w diwstrt,$1f71
ne_cl_diwstop:	dc.w diwstop,$31d1
ne_cl_diwhigh:	dc.w diwhigh,$2100
ne_cl_ddfstrt:	dc.w ddfstrt,$88-2*44
ne_cl_ddfstop:	dc.w ddfstop,$80+2*44
ne_cl_palette:	dc.w $180,$000
		dc.w $ffff,$fffe

		incdir	"include:majorrelease/"
sample:		incbin	"major release.smp"

		section	FastData,data
string_version:	dc.b	"$VER:Major Release 1.0 (2004-08-07) (C)2004 dA JoRMaS",0
string_progdir:	dc.b	"PROGDIR:",0
ra_template:	dc.b	"LOOP/S",0
tt_loop:	dc.b	"LOOP",0
name_graphics:	dc.b	"graphics.library",0
		ifne	FINALVERSION
name_icon:	dc.b	"icon.library",0
		endc
name_dos:	dc.b	"dos.library",0
		even
		; Part table (time, init)
		; -----------------------
parts:		dc.l	0*PATTERNLENGTH+1,jellylogo
		dc.l	0*PATTERNLENGTH+1,jellylogo_go
		dc.l	1*PATTERNLENGTH+61,bitmapzoomer
		dc.l	2*PATTERNLENGTH+1,bitmapzoomer_go
		dc.l	3*PATTERNLENGTH+53,fullscreenscrollersinus
		dc.l	4*PATTERNLENGTH+1,fullscreenscrollersinus_go
		dc.l	5*PATTERNLENGTH+50,discopallo
		dc.l	6*PATTERNLENGTH+1,discopallo_go
		dc.l	7*PATTERNLENGTH+60,zoomrotate
		dc.l	8*PATTERNLENGTH+1,zoomrotate_go
		dc.l	9*PATTERNLENGTH+55,fancywriter
		dc.l	10*PATTERNLENGTH+1,fancywriter_go
		dc.l	11*PATTERNLENGTH+60,insaneplasma
		dc.l	12*PATTERNLENGTH+1,insaneplasma_go
		dc.l	13*PATTERNLENGTH+61,colortunnel
		dc.l	14*PATTERNLENGTH+1,colortunnel_go
		dc.l	15*PATTERNLENGTH+58,imageroll
		dc.l	16*PATTERNLENGTH+1,imageroll_go
		dc.l	17*PATTERNLENGTH+64,horizon
		dc.l	18*PATTERNLENGTH+1,horizon_go
		dc.l	19*PATTERNLENGTH+64,cityscape
		dc.l	20*PATTERNLENGTH+1,cityscape_go
		dc.l	21*PATTERNLENGTH+54,rotate
		dc.l	22*PATTERNLENGTH+1,rotate_go
		dc.l	23*PATTERNLENGTH+57,spheremapping
		dc.l	24*PATTERNLENGTH+1,spheremapping_go
		dc.l	25*PATTERNLENGTH+52,fullscreenscrollerrotate
		dc.l	26*PATTERNLENGTH+1,fullscreenscrollerrotate_go
		dc.l	27*PATTERNLENGTH+64,vectorvideo
		dc.l	28*PATTERNLENGTH+1,vectorvideo_go
		dc.l	29*PATTERNLENGTH+24,stencilvector
		dc.l	30*PATTERNLENGTH+1,stencilvector_go
		dc.l	33*PATTERNLENGTH+58,starwarsscroller
		dc.l	34*PATTERNLENGTH+1,starwarsscroller_go
		dc.l	40*PATTERNLENGTH+1,end
		dc.l	-1

		; Sinus table (common to all effects)
		; -----------------------------------
sinus:		include	"/sinus-1024-7fff.i"

		; Ordered dithering table (common to all effects)
		; -----------------------------------------------
table_order:	dc.b   0,192, 48,240, 12,204, 60,252,  3,195, 51,243, 15,207, 63,255
		dc.b 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127
		dc.b  32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223
		dc.b 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95
		dc.b   8,200, 56,248,  4,196, 52,244, 11,203, 59,251,  7,199, 55,247
		dc.b 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119
		dc.b  40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215
		dc.b 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87
		dc.b   2,194, 50,242, 14,206, 62,254,  1,193, 49,241, 13,205, 61,253
		dc.b 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125
		dc.b  34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221
		dc.b 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93
		dc.b  10,202, 58,250,  6,198, 54,246,  9,201, 57,249,  5,197, 53,245
		dc.b 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117
		dc.b  42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213
		dc.b 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85

		; Bitmapzoomer data
		; -----------------
bz_bitmap_stc:	incbin	"bitmapzoomer.raw.stc"
		; Copperlist template
		; -------------------
bz_ct:		dc.w $1c01,$fffe
bz_ct_bplcon1:	dc.w bplcon1,%0000000000000000
bz_ct_bplcon0:	dc.w bplcon0,%0000000000000000+$1000*BZ_PLANES
bz_ct_diwstrt:	dc.w diwstrt,$a8a1-256*(BZ_PLANEHEIGHT/2)
bz_ct_diwstop:	dc.w diwstop,$30a1
bz_ct_ddfstrt:	dc.w ddfstrt,$88-2*BZ_PLANEWIDTH
bz_ct_ddfstop:	dc.w ddfstop,$80+2*BZ_PLANEWIDTH
bz_ct_palette:	dc.w $180,$000,$182,$111,$184,$222,$186,$333
		dc.w $188,$444,$18a,$555,$18c,$666,$18e,$777
		dc.w $190,$888,$192,$999,$194,$aaa,$196,$bbb
		dc.w $198,$ccc,$19a,$ddd,$19c,$eee,$19e,$fff
bz_ct_bpl1mod:	dc.w bpl1mod,(BZ_PLANES-1)*BZ_PLANEWIDTH
bz_ct_bpl2mod:	dc.w bpl2mod,(BZ_PLANES-1)*BZ_PLANEWIDTH
		dc.w bpl1pth
bz_ct_bpl1pth:	dc.w 0,bpl1ptl
bz_ct_bpl1ptl:	dc.w 0,bpl2pth
bz_ct_bpl2pth:	dc.w 0,bpl2ptl
bz_ct_bpl2ptl:	dc.w 0,bpl3pth
bz_ct_bpl3pth:	dc.w 0,bpl3ptl
bz_ct_bpl3ptl:	dc.w 0,bpl4pth
bz_ct_bpl4pth:	dc.w 0,bpl4ptl
bz_ct_bpl4ptl:	dc.w 0
		dc.w bplcon0,0
bz_ct_data:

		; 2x2chunky data (zoomrotate, spheremapping, colortunnel)
		; -------------------------------------------------------
ch_ct:		dc.w $1c01,$fffe
ch_ct_bplcon1:	dc.w bplcon1,%0000000000000000
ch_ct_bplcon0:	dc.w bplcon0,%0000000000000000+$1000*CH_PLANES
ch_ct_diwstrt:	dc.w diwstrt,$a881-256*CH_PLANEHEIGHT
ch_ct_diwstop:	dc.w diwstop,$3081
ch_ct_ddfstrt:	dc.w ddfstrt,$88-2*CH_PLANEWIDTH
ch_ct_ddfstop:	dc.w ddfstop,$80+2*CH_PLANEWIDTH
ch_ct_palette:	dc.w $180,$fff,$182,$fff,$184,$fff,$186,$fff
		dc.w $188,$fff,$18a,$fff,$18c,$fff,$18e,$fff
		dc.w $190,$fff,$192,$fff,$194,$fff,$196,$fff
		dc.w $198,$fff,$19a,$fff,$19c,$fff,$19e,$fff
ch_ct_bpl1mod:	dc.w bpl1mod,0
ch_ct_bpl2mod:	dc.w bpl2mod,0
		dc.w bpl4pth
ch_ct_bpl1pth:	dc.w 0,bpl4ptl
ch_ct_bpl1ptl:	dc.w 0,bpl2pth
ch_ct_bpl2pth:	dc.w 0,bpl2ptl
ch_ct_bpl2ptl:	dc.w 0,bpl3pth
ch_ct_bpl3pth:	dc.w 0,bpl3ptl
ch_ct_bpl3ptl:	dc.w 0,bpl1pth
ch_ct_bpl4pth:	dc.w 0,bpl1ptl
ch_ct_bpl4ptl:	dc.w 0
ch_ct_data:

ch_conversion:	dc.w	$0000,$0303,$0c0c,$0f0f
		dc.w	$3030,$3333,$3c3c,$3f3f
		dc.w	$c0c0,$c3c3,$cccc,$cfcf
		dc.w	$f0f0,$f3f3,$fcfc,$ffff
zr_source_stc:	incbin	"zoomrotate.raw.stc"
sm_source_stc:	incbin	"spheremapping.raw.stc"
sm_write_stc:	incbin	"spheremapping.68k.stc"
ct_write_stc:	incbin	"colortunnel.68k.stc"
zr_palette:	dc.w	$000,$000,$111,$112,$222,$223,$334,$444
		dc.w	$445,$556,$667,$778,$779,$889,$99b,$aac
sm_palette:	dc.w	$000,$bbb,$da8,$89c,$68c,$b87,$f00,$779
		dc.w	$976,$865,$568,$347,$544,$245,$123,$fff
ct_palette:	dc.w	$000,$500,$a11,$f22,$f42,$f82,$fc2,$ff2
		dc.w	$af2,$5f2,$2f2,$2f7,$2ff,$2af,$25a,$525

		; Cityscape data
		; --------------
cs_ct:		dc.w $1c01,$fffe
cs_ct_bplcon1:	dc.w bplcon1,%0000000000000000
cs_ct_bplcon0:	dc.w bplcon0,%0000000000000000+$1000*5
cs_ct_diwstrt:	dc.w diwstrt,$3071
cs_ct_diwstop:	dc.w diwstop,$20d1
cs_ct_ddfstrt:	dc.w ddfstrt,$88-2*CS_PLANEWIDTH
cs_ct_ddfstop:	dc.w ddfstop,$80+2*CS_PLANEWIDTH
		dc.w dmacon,$20
cs_ct_palette:	dc.w $184,$fff,$186,$fff,$18c,$fff,$18e,$fff
		dc.w $194,$fff,$196,$fff,$19c,$fff,$19e,$fff
		dc.w $1a4,$fff,$1a6,$fff,$1ac,$fff,$1ae,$fff
		dc.w $1b4,$fff,$1b6,$fff,$1bc,$fff,$1be,$fff
		dc.w $180,$000
cs_ct_bpl1mod:	dc.w bpl1mod,0
cs_ct_bpl2mod:	dc.w bpl2mod,0
		dc.w bpl1pth
cs_ct_bpl1pth:	dc.w 0,bpl1ptl
cs_ct_bpl1ptl:	dc.w 0,bpl2pth
cs_ct_bpl2pth:	dc.w 0,bpl2ptl
cs_ct_bpl2ptl:	dc.w 0,bpl3pth
cs_ct_bpl3pth:	dc.w 0,bpl3ptl
cs_ct_bpl3ptl:	dc.w 0,bpl4pth
cs_ct_bpl4pth:	dc.w 0,bpl4ptl
cs_ct_bpl4ptl:	dc.w 0,bpl5pth
cs_ct_bpl5pth:	dc.w 0,bpl5ptl
cs_ct_bpl5ptl:	dc.w 0
cs_ct_data:

		; Building coordinates (angle, distance, height)
		; ----------------------------------------------
cs_coords:	dc.w	16
		dc.w	0,0,25
		dc.w	0,90,70
		dc.w	0,150,40
		dc.w	512,30,90
		dc.w	512,90,50
		dc.w	512,150,30
		dc.w	1024,30,50
		dc.w	1024,90,70
		dc.w	1024,150,40
		dc.w	1536,30,20
		dc.w	1536,90,100
		dc.w	1536,150,50
		dc.w	256,120,70
		dc.w	768,120,30
		dc.w	1280,120,50
		dc.w	1782,120,20

		; Background gradient colors
		; --------------------------
cs_gradient:	dc.w	$ff0,$fe0,$fd0,$fc0,$fb0,$fa0,$f90,$f80
		dc.w	$f70,$f60,$f50,$f40,$f30,$f20,$f10,$f00
		; Building color
		; --------------
cs_citycolor:	dc.w	$200

		; Discopallo data
		; ---------------
dp_ct:		dc.w $1c01,$fffe
dp_ct_bplcon1:	dc.w bplcon1,%0000000000000000
dp_ct_bplcon0:	dc.w bplcon0,%0000000000000000+$1000*DP_PLANES
dp_ct_diwstrt:	dc.w diwstrt,$a871-256*DP_PLANEHEIGHT/2
dp_ct_diwstop:	dc.w diwstop,$28d1
dp_ct_ddfstrt:	dc.w ddfstrt,$78-2*DP_PLANEWIDTH
dp_ct_ddfstop:	dc.w ddfstop,$70+2*DP_PLANEWIDTH
dp_ct_palette:	dc.w $180,$000,$182,$000,$184,$000,$186,$000
		dc.w $188,$000,$18a,$000,$18c,$000,$18e,$000
		dc.w $190,$000,$192,$000,$194,$000,$196,$000
		dc.w $198,$000,$19a,$000,$19c,$000,$19e,$000
		dc.w $1a0,$000,$1a2,$000,$1a4,$000,$1a6,$000
		dc.w $1a8,$000,$1aa,$000,$1ac,$000,$1ae,$000
		dc.w $1b0,$000,$1b2,$000,$1b4,$000,$1b6,$000
		dc.w $1b8,$000,$1ba,$000,$1bc,$000,$1be,$000
dp_ct_bpl1mod:	dc.w bpl1mod,(DP_PLANES-1)*DP_PLANEWIDTH
dp_ct_bpl2mod:	dc.w bpl2mod,(DP_PLANES-1)*DP_PLANEWIDTH
		dc.w bpl1pth
dp_ct_bpl1pth:	dc.w 0,bpl1ptl
dp_ct_bpl1ptl:	dc.w 0,bpl2pth
dp_ct_bpl2pth:	dc.w 0,bpl2ptl
dp_ct_bpl2ptl:	dc.w 0,bpl3pth
dp_ct_bpl3pth:	dc.w 0,bpl3ptl
dp_ct_bpl3ptl:	dc.w 0,bpl4pth
dp_ct_bpl4pth:	dc.w 0,bpl4ptl
dp_ct_bpl4ptl:	dc.w 0,bpl5pth
dp_ct_bpl5pth:	dc.w 0,bpl5ptl
dp_ct_bpl5ptl:	dc.w 0
		dc.w bplcon0,0
		dc.w cop2lch
dp_ct_cop2lch:	dc.w 0,cop2lcl
dp_ct_cop2lcl:	dc.w 0,copjmp2
		dc.w 0
dp_ct_data:

dp_texture_stc:	incbin	"discopallo.raw16.stc"

		; Fancy writer data
		; -----------------
fw_ct:		dc.w $1c01,$fffe
fw_ct_bplcon1:	dc.w bplcon1,%0000000000010000
fw_ct_bplcon0:	dc.w bplcon0,%0000000000000001+$1000*(FW_PLANES+1)
fw_ct_diwstrt:	dc.w diwstrt,$a881-256*FW_PLANEHEIGHT/2
fw_ct_diwstop:	dc.w diwstop,$27c1
fw_ct_ddfstrt:	dc.w ddfstrt,$88-2*FW_PLANEWIDTH
fw_ct_ddfstop:	dc.w ddfstop,$80+2*FW_PLANEWIDTH
fw_ct_palette:	dc.w $180,$804,$182,$fff,$184,$402,$186,$fff
		dc.w $188,$402,$18a,$fff,$18c,$201,$18e,$fff
fw_ct_bpl1mod:	dc.w bpl1mod,0
fw_ct_bpl2mod:	dc.w bpl2mod,0
		dc.w bpl1pth
fw_ct_bpl1pth:	dc.w 0,bpl1ptl
fw_ct_bpl1ptl:	dc.w 0,bpl2pth
fw_ct_bpl2pth:	dc.w 0,bpl2ptl
fw_ct_bpl2ptl:	dc.w 0,bpl3pth
fw_ct_bpl3pth:	dc.w 0,bpl3ptl
fw_ct_bpl3ptl:	dc.w 0
		dc.w $ffff,$fffe
fw_ct_data:

fw_palette:	dc.w $804,$fff,$402,$fff,$402,$fff,$201,$fff
fw_symbol_stc:	incbin	"symbol.raw.stc"
fw_font_stc:	incbin	"fancywriterfont.raw.stc"
fw_font_widths:	incbin	"fancywriterfont.wid"
fw_font_left:	dc.b	0	;  
		dc.b	0	; !
		dc.b	0	; "
		dc.b	0	; #
		dc.b	0	; $
		dc.b	0	; %
		dc.b	0	; &
		dc.b	0	; '
		dc.b	0	; (
		dc.b	0	; )
		dc.b	0	; *
		dc.b	0	; +
		dc.b	0	; ,
		dc.b	0	; -
		dc.b	0	; .
		dc.b	0	; /
		dc.b	0	; 0
		dc.b	0	; 1
		dc.b	0	; 2
		dc.b	0	; 3
		dc.b	0	; 4
		dc.b	0	; 5
		dc.b	0	; 6
		dc.b	0	; 7
		dc.b	0	; 8
		dc.b	0	; 9
		dc.b	0	; :
		dc.b	0	; ;
		dc.b	0	; <
		dc.b	0	; =
		dc.b	0	; >
		dc.b	0	; ?
		dc.b	0	; @
		dc.b	0	; A
		dc.b	0	; B
		dc.b	0	; C
		dc.b	0	; D
		dc.b	0	; E
		dc.b	0	; F
		dc.b	0	; G
		dc.b	0	; H
		dc.b	0	; I
		dc.b	0	; J
		dc.b	0	; K
		dc.b	0	; L
		dc.b	0	; M
		dc.b	0	; N
		dc.b	0	; O
		dc.b	0	; P
		dc.b	0	; Q
		dc.b	0	; R
		dc.b	0	; S
		dc.b	0	; T
		dc.b	0	; U
		dc.b	0	; V
		dc.b	0	; W
		dc.b	0	; X
		dc.b	0	; Y
		dc.b	0	; Z
		dc.b	0	; [
		dc.b	0	; \
		dc.b	0	; ]
		dc.b	0	; ^
		dc.b	0	; _
		dc.b	0	; `
		dc.b	0	; a
		dc.b	0	; b
		dc.b	0	; c
		dc.b	0	; d
		dc.b	0	; e
		dc.b	0	; f
		dc.b	0	; g
		dc.b	0	; h
		dc.b	0	; i
		dc.b	3	; j
		dc.b	0	; k
		dc.b	0	; l
		dc.b	0	; m
		dc.b	0	; n
		dc.b	0	; o
		dc.b	0	; p
		dc.b	0	; q
		dc.b	0	; r
		dc.b	0	; s
		dc.b	0	; t
		dc.b	0	; u
		dc.b	0	; v
		dc.b	0	; w
		dc.b	0	; x
		dc.b	0	; y
		dc.b	0	; z
		dc.b	0	; {
		dc.b	0	; |
		dc.b	0	; }
		dc.b	0	; ~
fw_font_right:	dc.b	0	;  
		dc.b	0	; !
		dc.b	0	; "
		dc.b	0	; #
		dc.b	0	; $
		dc.b	0	; %
		dc.b	0	; &
		dc.b	1	; '
		dc.b	0	; (
		dc.b	0	; )
		dc.b	0	; *
		dc.b	0	; +
		dc.b	0	; ,
		dc.b	0	; -
		dc.b	0	; .
		dc.b	3	; /
		dc.b	0	; 0
		dc.b	0	; 1
		dc.b	0	; 2
		dc.b	0	; 3
		dc.b	0	; 4
		dc.b	0	; 5
		dc.b	0	; 6
		dc.b	0	; 7
		dc.b	0	; 8
		dc.b	0	; 9
		dc.b	0	; :
		dc.b	0	; ;
		dc.b	0	; <
		dc.b	0	; =
		dc.b	0	; >
		dc.b	0	; ?
		dc.b	0	; @
		dc.b	0	; A
		dc.b	0	; B
		dc.b	0	; C
		dc.b	0	; D
		dc.b	0	; E
		dc.b	3	; F
		dc.b	0	; G
		dc.b	0	; H
		dc.b	0	; I
		dc.b	0	; J
		dc.b	0	; K
		dc.b	0	; L
		dc.b	0	; M
		dc.b	0	; N
		dc.b	0	; O
		dc.b	0	; P
		dc.b	0	; Q
		dc.b	0	; R
		dc.b	1	; S
		dc.b	4	; T
		dc.b	0	; U
		dc.b	0	; V
		dc.b	0	; W
		dc.b	0	; X
		dc.b	0	; Y
		dc.b	0	; Z
		dc.b	0	; [
		dc.b	0	; \
		dc.b	0	; ]
		dc.b	0	; ^
		dc.b	0	; _
		dc.b	0	; `
		dc.b	0	; a
		dc.b	0	; b
		dc.b	0	; c
		dc.b	0	; d
		dc.b	0	; e
		dc.b	0	; f
		dc.b	0	; g
		dc.b	0	; h
		dc.b	0	; i
		dc.b	0	; j
		dc.b	0	; k
		dc.b	0	; l
		dc.b	0	; m
		dc.b	0	; n
		dc.b	0	; o
		dc.b	0	; p
		dc.b	0	; q
		dc.b	0	; r
		dc.b	0	; s
		dc.b	0	; t
		dc.b	0	; u
		dc.b	0	; v
		dc.b	0	; w
		dc.b	0	; x
		dc.b	0	; y
		dc.b	0	; z
		dc.b	0	; {
		dc.b	0	; |
		dc.b	0	; }
		dc.b	0	; ~

fw_text:	dc.b	10,10
		dc.b	"        Welcome to dA JoRMaS' contribution to the",10
		dc.b	"       Assembly 2004 oldskool demo competition called",10,10
		dc.b	"                            Major Release",10,10
		dc.b	"     This demo runs on the classic Amiga 500 platform:",10
		dc.b	"7MHz 68000,512kB chip memory,512kB fast memory,",10
		dc.b	"     4 channel stereo sound and some coprocessor magic",10,10
		dc.b	"                             Enjoy the show!",10
		dc.b	0
		even

		; Fullscreen scroller
		; -------------------
fs_ct:		dc.w $1c01,$fffe
fs_ct_bplcon1:	dc.w bplcon1,%0000000000000000
fs_ct_bplcon0:	dc.w bplcon0,%0000000000000000+$1000*FS_PLANES
fs_ct_diwstrt:	dc.w diwstrt,$a8a1-256*FS_PLANEHEIGHT/2
fs_ct_diwstop:	dc.w diwstop,$28a1
fs_ct_ddfstrt:	dc.w ddfstrt,$88-2*FS_PLANEWIDTH
fs_ct_ddfstop:	dc.w ddfstop,$80+2*FS_PLANEWIDTH
fs_ct_palette:	dc.w $180,$fff,$182,$fff,$184,$fff,$186,$fff
		dc.w $188,$fff,$18a,$fff,$18c,$fff,$18e,$fff
		dc.w $190,$fff,$192,$fff,$194,$fff,$196,$fff
		dc.w $198,$fff,$19a,$fff,$19c,$fff,$19e,$fff
fs_ct_bpl1mod:	dc.w bpl1mod,0
fs_ct_bpl2mod:	dc.w bpl2mod,0
		dc.w bpl1pth
fs_ct_bpl1pth:	dc.w 0,bpl1ptl
fs_ct_bpl1ptl:	dc.w 0,bpl2pth
fs_ct_bpl2pth:	dc.w 0,bpl2ptl
fs_ct_bpl2ptl:	dc.w 0,bpl3pth
fs_ct_bpl3pth:	dc.w 0,bpl3ptl
fs_ct_bpl3ptl:	dc.w 0,bpl4pth
fs_ct_bpl4pth:	dc.w 0,bpl4ptl
fs_ct_bpl4ptl:	dc.w 0
		dc.w $ffff,$fffe
fs_ct_data:

fs_background_1_stc:	incbin	"fullscreenscrollersinus.raw.stc"
fs_background_2_stc:	incbin	"fullscreenscrollerrotate.raw.stc"
;fs_pointers_1:		incbin	"fullscreenscrollersinus.pointers"
fs_pointers_2:		incbin	"fullscreenscrollerrotate.pointers"
;fs_data_1_stc:		incbin	"fullscreenscrollersinus.data.stc"
fs_data_2_stc:		incbin	"fullscreenscrollerrotate.data.stc"
fs_palette_1:	dc.w	$0fc8,$0ea6,$0e84,$0d72,$0c62,$0b51,$0741,$0210
		dc.w	$0c30,$0b30,$0b30,$0a20,$0820,$0710,$0410,$0100
fs_palette_2:	dc.w	$0421,$0210,$0811,$0863,$0b95,$0fd7,$0fe9,$0ffc
		dc.w	$0873,$0984,$0b74,$0ba5,$0cb6,$0fe7,$0fe8,$0fe9

		; Horizon
		; -------
ho_ct:		dc.w	$1401,$fffe
ho_ct_bplcon1:	dc.w	bplcon1,%0000000000000000
ho_ct_bplcon0:	dc.w	bplcon0,%0000000000000001
ho_ct_diwstrt:	dc.w	diwstrt,$a881-256*HO_PLANEHEIGHT/2
ho_ct_diwstop:	dc.w	diwstop,$28c1
ho_ct_ddfstrt:	dc.w	ddfstrt,$88-2*HO_PLANEWIDTH
ho_ct_ddfstop:	dc.w	ddfstop,$80+2*HO_PLANEWIDTH
ho_ct_palette:	dc.w	$180,$000
ho_ct_bpl1mod:	dc.w	bpl1mod,0
ho_ct_bpl2mod:	dc.w	bpl2mod,0
		dc.w	bpl1pth
ho_ct_bpl1pth:	dc.w	0,bpl1ptl
ho_ct_bpl1ptl:	dc.w	0,bpl2pth
ho_ct_bpl2pth:	dc.w	0,bpl2ptl
ho_ct_bpl2ptl:	dc.w	0,bpl3pth
ho_ct_bpl3pth:	dc.w	0,bpl3ptl
ho_ct_bpl3ptl:	dc.w	0,bpl4pth
ho_ct_bpl4pth:	dc.w	0,bpl4ptl
ho_ct_bpl4ptl:	dc.w	0,bpl5pth
ho_ct_bpl5pth:	dc.w	0,bpl5ptl
ho_ct_bpl5ptl:	dc.w	0,cop2lch
ho_ct_cop2lch:	dc.w	0,cop2lcl
ho_ct_cop2lcl:	dc.w	0
		dc.w	$1801,$fffe
		dc.w	copjmp2,0
		; Double size for double buffering
		; --------------------------------
ho_ct_data1:	dc.w	$182,$fd0,$184,$fb0,$186,$fb0
		dc.w	$188,$f90,$18a,$f90,$18c,$f90,$18e,$f90
		dc.w	$190,$f70,$192,$f70,$194,$f70,$196,$f70
		dc.w	$198,$f70,$19a,$f70,$19c,$f70,$19e,$f70
		dc.w	$1a2,$fd0,$1a4,$fb0,$1a6,$fb0
		dc.w	$1a8,$f90,$1aa,$f90,$1ac,$f90,$1ae,$f90
		dc.w	$1b0,$f70,$1b2,$f70,$1b4,$f70,$1b6,$f70
		dc.w	$1b8,$f70,$1ba,$f70,$1bc,$f70,$1be,$f70
;		ds.w	64+56
ho_ct_data2:	dc.w	$182,$fd0,$184,$fb0,$186,$fb0
		dc.w	$188,$f90,$18a,$f90,$18c,$f90,$18e,$f90
		dc.w	$190,$f70,$192,$f70,$194,$f70,$196,$f70
		dc.w	$198,$f70,$19a,$f70,$19c,$f70,$19e,$f70
		dc.w	$1a2,$fd0,$1a4,$fb0,$1a6,$fb0
		dc.w	$1a8,$f90,$1aa,$f90,$1ac,$f90,$1ae,$f90
		dc.w	$1b0,$f70,$1b2,$f70,$1b4,$f70,$1b6,$f70
		dc.w	$1b8,$f70,$1ba,$f70,$1bc,$f70,$1be,$f70
;		ds.w	64+56
ho_ct_data:
		; Coordinates address (.l), height (.w), z (.w), zoom (.w)
		; --------------------------------------------------------
horizon_table:	dc.l	horizon_1
		dc.w	0,256,0,0
		dc.l	horizon_2
		dc.w	0,200,0,0
		dc.l	horizon_3
		dc.w	0,144,0,0
		dc.l	horizon_4
		dc.w	0,88,0,0
horizon_end:

horizon_1:	dc.w	127, 83
		dc.w	49, 78
		dc.w	33, 74
		dc.w	0, 54
		dc.w	-11, 47
		dc.w	-15, 21
		dc.w	-19, 10
		dc.w	-29, 2
		dc.w	-58, 1
		dc.w	-67, 2
		dc.w	-73, 6
		dc.w	-76, 19
		dc.w	-79, 35
		dc.w	-80, 50
		dc.w	-98, 61
		dc.w	-106, 66
		dc.w	-106, 66
		dc.w	-107, 66
		dc.w	-111, 66
		dc.w	-128, 69
		dc.l	-1

horizon_2:	dc.w	127, 70
		dc.w	121, 63
		dc.w	104, 65
		dc.w	63, 68
		dc.w	61, 65
		dc.w	36, 59
		dc.w	32, 58
		dc.w	30, 59
		dc.w	22, 53
		dc.w	18, 44
		dc.w	14, 43
		dc.w	0, 42
		dc.w	-10, 47
		dc.w	-11, 45
		dc.w	-13, 44
		dc.w	-25, 39
		dc.w	-31, 37
		dc.w	-53, 40
		dc.w	-55, 41
		dc.w	-57, 29
		dc.w	-59, 23
		dc.w	-60, 19
		dc.w	-62, 8
		dc.w	-78, 1
		dc.w	-79, 3
		dc.w	-82, 8
		dc.w	-84, 15
		dc.w	-85, 28
		dc.w	-86, 47
		dc.w	-87, 50
		dc.w	-98, 51
		dc.w	-103, 57
		dc.w	-105, 57
		dc.w	-128, 58
		dc.l	-1

horizon_3:	dc.w	127, 82
		dc.w	114, 81
		dc.w	99, 78
		dc.w	94, 76
		dc.w	81, 73
		dc.w	80, 67
		dc.w	78, 35
		dc.w	76, 29
		dc.w	75, 23
		dc.w	74, 20
		dc.w	73, 15
		dc.w	72, 7
		dc.w	71, 5
		dc.w	70, 1
		dc.w	67, 2
		dc.w	63, 2
		dc.w	61, 7
		dc.w	58, 6
		dc.w	57, 13
		dc.w	53, 12
		dc.w	48, 11
		dc.w	47, 20
		dc.w	45, 14
		dc.w	44, 32
		dc.w	40, 38
		dc.w	38, 45
		dc.w	32, 41
		dc.w	29, 43
		dc.w	26, 44
		dc.w	26, 48
		dc.w	16, 58
		dc.w	5, 55
		dc.w	-5, 50
		dc.w	-26, 48
		dc.w	-50, 44
		dc.w	-61, 43
		dc.w	-77, 39
		dc.w	-87, 36
		dc.w	-98, 34
		dc.w	-108, 31
		dc.w	-121, 27
		dc.w	-127, 27
		dc.w	-128, 82
		dc.l	-1

horizon_4:	dc.w	127, 73
		dc.w	118, 68
		dc.w	100, 64
		dc.w	96, 61
		dc.w	95, 55
		dc.w	94, 45
		dc.w	93, 39
		dc.w	89, 37
		dc.w	87, 34
		dc.w	80, 34
		dc.w	69, 41
		dc.w	67, 52
		dc.w	64, 45
		dc.w	62, 61
		dc.w	51, 70
		dc.w	35, 71
		dc.w	30, 72
		dc.w	18, 71
		dc.w	6, 71
		dc.w	-3, 72
		dc.w	-7, 70
		dc.w	-19, 66
		dc.w	-22, 63
		dc.w	-31, 56
		dc.w	-32, 51
		dc.w	-34, 44
		dc.w	-35, 35
		dc.w	-36, 35
		dc.w	-36, 19
		dc.w	-37, 13
		dc.w	-41, 14
		dc.w	-41, 27
		dc.w	-43, 33
		dc.w	-48, 28
		dc.w	-50, 28
		dc.w	-52, 17
		dc.w	-53, 8
		dc.w	-58, 6
		dc.w	-63, 3
		dc.w	-82, 3
		dc.w	-86, 0
		dc.w	-97, 5
		dc.w	-100, 29
		dc.w	-101, 38
		dc.w	-102, 49
		dc.w	-103, 52
		dc.w	-104, 54
		dc.w	-112, 60
		dc.w	-114, 62
		dc.w	-120, 66
		dc.w	-128, 73
		dc.l	-1

ho_colors:	dc.w	$ff0,$fe0,$fd0,$fc0,$fb0,$fa0,$f90,$f80
		dc.w	$f70,$f60,$f50,$f40,$f30,$f20,$f10,$f00
ho_gradient:	dc.w	$f69,$f78,$f87,$f96,$fa5,$fb4,$fc3,$fd2
		dc.w	$fe1,$ff0,$ff1

		; Imageroll data
		; --------------
ir_ct:		dc.w $1801,$fffe
ir_ct_bplcon1:	dc.w bplcon1,%0000000000000000
ir_ct_bplcon0:	dc.w bplcon0,%0000100000000001+$1000*IR_PLANES
ir_ct_diwstrt:	dc.w diwstrt,$1a71
ir_ct_diwstop:	dc.w diwstop,$30d1
ir_ct_ddfstrt:	dc.w ddfstrt,$88-2*IR_PLANEWIDTH
ir_ct_ddfstop:	dc.w ddfstop,$80+2*IR_PLANEWIDTH
ir_ct_palette:	dc.w $180,$000,$182,$fff,$184,$222,$186,$333
		dc.w $188,$444,$18a,$555,$18c,$666,$18e,$777
		dc.w $190,$888,$192,$999,$194,$aaa,$196,$bbb
		dc.w $198,$ccc,$19a,$ddd,$19c,$eee,$19e,$fff
ir_ct_bpl1mod:	dc.w bpl1mod,(IR_PLANES-1)*IR_PLANEWIDTH
ir_ct_bpl2mod:	dc.w bpl2mod,(IR_PLANES-1)*IR_PLANEWIDTH
		dc.w bpl1pth
ir_ct_bpl1pth:	dc.w 0,bpl1ptl
ir_ct_bpl1ptl:	dc.w 0,bpl2pth
ir_ct_bpl2pth:	dc.w 0,bpl2ptl
ir_ct_bpl2ptl:	dc.w 0,bpl3pth
ir_ct_bpl3pth:	dc.w 0,bpl3ptl
ir_ct_bpl3ptl:	dc.w 0,bpl4pth
ir_ct_bpl4pth:	dc.w 0,bpl4ptl
ir_ct_bpl4ptl:	dc.w 0,bpl5pth
ir_ct_bpl5pth:	dc.w 0,bpl5ptl
ir_ct_bpl5ptl:	dc.w 0,bpl6pth
ir_ct_bpl6pth:	dc.w 0,bpl6ptl
ir_ct_bpl6ptl:	dc.w 0,cop2lch
ir_ct_cop2lch:	dc.w 0,cop2lcl
ir_ct_cop2lcl:	dc.w 0,copjmp2
		dc.w 0
ir_ct_data:

ir_picture_stc:	incbin	"imageroll.raw.stc"
ir_low:		dc.b	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,38,39,40,42,43,45,47,49,52
ir_high:	dc.b	123,121,119,117,115,114,112,111,110,109,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,84,83,82,81,80,78,77,76,74,72,71,68,65,59

		; Insane plasma
		; -------------
ip_ct:		dc.w $1c01,$fffe
ip_ct_bplcon1:	dc.w bplcon1,%0000000000000000
ip_ct_bplcon0:	dc.w bplcon0,%0000000000000001+$1000*6
ip_ct_diwstrt:	dc.w diwstrt,$3581
ip_ct_diwstop:	dc.w diwstop,$1bc1
ip_ct_ddfstrt:	dc.w ddfstrt,$88-2*IP_PLANEWIDTH
ip_ct_ddfstop:	dc.w ddfstop,$80+2*IP_PLANEWIDTH
		dc.w dmacon,$20
ip_ct_palette:	dc.w $180,$000,$182,$000,$188,$000,$18a,$000
		dc.w $1a0,$000,$1a2,$000,$1a8,$000,$1aa,$000
ip_ct_bpl1mod:	dc.w bpl1mod,-IP_PLANEWIDTH
ip_ct_bpl2mod:	dc.w bpl2mod,0
		dc.w bpl2pth
ip_ct_bpl2pth:	dc.w 0,bpl2ptl
ip_ct_bpl2ptl:	dc.w 0,bpl4pth
ip_ct_bpl4pth:	dc.w 0,bpl4ptl
ip_ct_bpl4ptl:	dc.w 0
		dc.w cop1lcl
ip_ct_cop1lcl:	dc.w 0,cop1lch
ip_ct_cop1lch:	dc.w 0
		dc.w copjmp1,0
ip_ct_1:	dc.w bpl1pth
ip_ct_bpl1pth1:	dc.w 0,bpl1ptl
ip_ct_bpl1ptl1:	dc.w 0,bpl3pth
ip_ct_bpl3pth1:	dc.w 0,bpl3ptl
ip_ct_bpl3ptl1:	dc.w 0,bpl5pth
ip_ct_bpl5pth1:	dc.w 0,bpl5ptl
ip_ct_bpl5ptl1:	dc.w 0,bpl6pth
ip_ct_bpl6pth1:	dc.w 0,bpl6ptl
ip_ct_bpl6ptl1:	dc.w 0
ip_ct_data1:
ip_ct_2:	dc.w bpl1pth
ip_ct_bpl1pth2:	dc.w 0,bpl1ptl
ip_ct_bpl1ptl2:	dc.w 0,bpl3pth
ip_ct_bpl3pth2:	dc.w 0,bpl3ptl
ip_ct_bpl3ptl2:	dc.w 0,bpl5pth
ip_ct_bpl5pth2:	dc.w 0,bpl5ptl
ip_ct_bpl5ptl2:	dc.w 0,bpl6pth
ip_ct_bpl6pth2:	dc.w 0,bpl6ptl
ip_ct_bpl6ptl2:	dc.w 0
ip_ct_data2:
ip_ct_data:

ip_palette1:	dc.w	$850,$960,$a70,$b70,$c80,$d90,$e90,$fa0
		dc.w	$803,$904,$a04,$b05,$c05,$d06,$e06,$f07
		dc.w	$308,$409,$409,$40a,$50b,$50c,$60d,$60f
ip_palette2:	dc.w	$208,$209,$209,$20a,$20b,$30c,$30d,$30f
		dc.w	$680,$790,$8a0,$9b0,$ac0,$bd0,$be0,$cf0
		dc.w	$078,$079,$08a,$09b,$0ac,$0bd,$0be,$0cf
ip_image_stc:	incbin	"insaneplasma.raw.stc"

		; Rotate data
		; -----------
ro_ct:		dc.w $1c01,$fffe
ro_ct_bplcon1:	dc.w bplcon1,%0000000000000000
ro_ct_bplcon0:	dc.w bplcon0,%0000000000000000+$1000*RO_PLANES
ro_ct_diwstrt:	dc.w diwstrt,$a8a1-256*((RO_PLANEHEIGHT-2)/2)
ro_ct_diwstop:	dc.w diwstop,$28a1
ro_ct_ddfstrt:	dc.w ddfstrt,$90-2*RO_PLANEWIDTH
ro_ct_ddfstop:	dc.w ddfstop,$88+2*RO_PLANEWIDTH
ro_ct_palette:	dc.w $180,$fff,$182,$fff,$184,$fff,$186,$fff
ro_ct_bpl1mod:	dc.w bpl1mod,(RO_PLANES-1)*RO_PLANEWIDTH
ro_ct_bpl2mod:	dc.w bpl2mod,(RO_PLANES-1)*RO_PLANEWIDTH
		dc.w bpl1pth
ro_ct_bpl1pth:	dc.w 0,bpl1ptl
ro_ct_bpl1ptl:	dc.w 0,bpl2pth
ro_ct_bpl2pth:	dc.w 0,bpl2ptl
ro_ct_bpl2ptl:	dc.w 0
		dc.w $ffff,$fffe
ro_ct_data:

ro_palette:	dc.w $805,$b37,$d7b,$f9d

		; Star wars scroller data
		; -----------------------
sw_ct:		dc.w $1c01,$fffe
sw_ct_bplcon1:	dc.w bplcon1,%0000000000000000
sw_ct_bplcon0:	dc.w bplcon0,%0000000000000000+$1000*SW_PLANES
sw_ct_diwstrt:	dc.w diwstrt,$a871-256*SW_PLANEHEIGHT/2
sw_ct_diwstop:	dc.w diwstop,$28d1
sw_ct_ddfstrt:	dc.w ddfstrt,$88-2*SW_PLANEWIDTH
sw_ct_ddfstop:	dc.w ddfstop,$80+2*SW_PLANEWIDTH
sw_ct_palette:	dc.w $180,$000,$182,$fe1
sw_ct_bpl1mod:	dc.w bpl1mod,0
sw_ct_bpl2mod:	dc.w bpl2mod,0
		dc.w bpl1pth
sw_ct_bpl1pth:	dc.w 0,bpl1ptl
sw_ct_bpl1ptl:	dc.w 0
		dc.w bplcon0,0
sw_ct_data:

sw_bitmap_stc:	incbin	"starwarsscroller.raw.stc"

		; Stencil vector data
		; -------------------
sv_ct:		dc.w $1c01,$fffe
sv_ct_bplcon1:	dc.w bplcon1,%0000000000000000
sv_ct_bplcon0:	dc.w bplcon0,%0000000000000000+$1000*SV_PLANES
sv_ct_diwstrt:	dc.w diwstrt,$a891-256*SV_PLANEHEIGHT/2
sv_ct_diwstop:	dc.w diwstop,$0091
sv_ct_ddfstrt:	dc.w ddfstrt,$88-2*SV_PLANEWIDTH
sv_ct_ddfstop:	dc.w ddfstop,$80+2*SV_PLANEWIDTH
sv_ct_palette:	dc.w $180,$000,$182,$000,$184,$000,$186,$000
		dc.w $188,$000,$18a,$000,$18c,$000,$18e,$000
		dc.w $190,$000,$192,$000,$194,$000,$196,$000
		dc.w $198,$000,$19a,$000,$19c,$000,$19e,$000
sv_ct_bpl1mod:	dc.w bpl1mod,0
sv_ct_bpl2mod:	dc.w bpl2mod,0
		dc.w bpl1pth
sv_ct_bpl1pth:	dc.w 0,bpl1ptl
sv_ct_bpl1ptl:	dc.w 0,bpl2pth
sv_ct_bpl2pth:	dc.w 0,bpl2ptl
sv_ct_bpl2ptl:	dc.w 0,bpl3pth
sv_ct_bpl3pth:	dc.w 0,bpl3ptl
sv_ct_bpl3ptl:	dc.w 0,bpl4pth
sv_ct_bpl4pth:	dc.w 0,bpl4ptl
sv_ct_bpl4ptl:	dc.w 0
		dc.w $f801,$fffe
		dc.w bplcon0,0
		dc.w $ffff,$fffe
sv_ct_data:

sv_palette_cube:	dc.w $000,$100,$211,$311,$422,$532,$643,$753
			dc.w $864,$975,$a86,$b97,$ca8,$db9,$eca,$fdb
sv_palette_24faces:	dc.w $000,$111,$222,$333,$444,$555,$666,$777
			dc.w $888,$999,$aaa,$bbb,$ccc,$ddd,$eee,$fff
sv_palette_symbol:	dc.w $000,$210,$320,$430,$540,$650,$761,$871
			dc.w $982,$a92,$ba3,$cb3,$dc4,$ed5,$fe6,$ff6

sv_faces_cube:	; Number of faces, normal vector length
		; -------------------------------------
		dc.w	6, (1<<(SV_NORMAL_SHIFT-4))*27
		; Room for face normal coordinates and X*Y value,
		; Room for rotated face normal coordinates,
		; Room for visibility value,
		; Number of vertices in face,
		; Vertex offsets (*4)
		; -------------------
		dc.w	0,0,0,0, 0,0,0, 0, 4, 0,1,2,3,0
		dc.w	0,0,0,0, 0,0,0, 0, 4, 4,7,6,5,4
		dc.w	0,0,0,0, 0,0,0, 0, 4, 0,4,5,1,0
		dc.w	0,0,0,0, 0,0,0, 0, 4, 2,6,7,3,2
		dc.w	0,0,0,0, 0,0,0, 0, 4, 0,3,7,4,0
		dc.w	0,0,0,0, 0,0,0, 0, 4, 1,5,6,2,1

sv_coordinates_cube:
		; Number of coordinates
		; ---------------------
		dc.w	8
		; X, Y, Z and room for X*Y value
		; ------------------------------
		dc.w	-25,-25,-25,0	; 0
		dc.w	 25,-25,-25,0	; 4
		dc.w	 25, 25,-25,0	; 8
		dc.w	-25, 25,-25,0	; 12
		dc.w	-25,-25, 25,0	; 16
		dc.w	 25,-25, 25,0	; 20
		dc.w	 25, 25, 25,0	; 24
		dc.w	-25, 25, 25,0	; 28


sv_faces_24faces:
		; Number of faces, normal vector length
		; -------------------------------------
		dc.w	24, (1<<(SV_NORMAL_SHIFT-4))*30
		; Room for face normal coordinates and X*Y value,
		; Room for rotated face normal coordinates,
		; Room for visibility value,
		; Number of vertices in face,
		; Vertex offsets (*4)
		; -------------------
		dc.w	0,0,0,0, 0,0,0, 0, 3, 0,1,8,0
		dc.w	0,0,0,0, 0,0,0, 0, 3, 1,2,8,1
		dc.w	0,0,0,0, 0,0,0, 0, 3, 2,3,8,2
		dc.w	0,0,0,0, 0,0,0, 0, 3, 3,0,8,3
		dc.w	0,0,0,0, 0,0,0, 0, 3, 4,9,5,4
		dc.w	0,0,0,0, 0,0,0, 0, 3, 5,9,6,5
		dc.w    0,0,0,0, 0,0,0, 0, 3, 6,9,7,6
		dc.w    0,0,0,0, 0,0,0, 0, 3, 7,9,4,7
		dc.w	0,0,0,0, 0,0,0, 0, 3, 0,4,10,0
		dc.w	0,0,0,0, 0,0,0, 0, 3, 4,5,10,4
		dc.w	0,0,0,0, 0,0,0, 0, 3, 5,1,10,5
		dc.w	0,0,0,0, 0,0,0, 0, 3, 1,0,10,1
		dc.w	0,0,0,0, 0,0,0, 0, 3, 3,11,7,3
		dc.w	0,0,0,0, 0,0,0, 0, 3, 7,11,6,7
		dc.w	0,0,0,0, 0,0,0, 0, 3, 6,11,2,6
		dc.w	0,0,0,0, 0,0,0, 0, 3, 2,11,3,2
		dc.w	0,0,0,0, 0,0,0, 0, 3, 0,12,4,0
		dc.w	0,0,0,0, 0,0,0, 0, 3, 4,12,7,4
		dc.w	0,0,0,0, 0,0,0, 0, 3, 7,12,3,7
		dc.w	0,0,0,0, 0,0,0, 0, 3, 3,12,0,3
		dc.w	0,0,0,0, 0,0,0, 0, 3, 1,5,13,1
		dc.w	0,0,0,0, 0,0,0, 0, 3, 5,6,13,5
		dc.w	0,0,0,0, 0,0,0, 0, 3, 6,2,13,6
		dc.w	0,0,0,0, 0,0,0, 0, 3, 2,1,13,2

sv_coordinates_24faces:
		; Number of coordinates
		; ---------------------
		dc.w	14
		; X, Y, Z and room for X*Y value
		; ------------------------------
		dc.w	-25,-25,-25,0		; 0
		dc.w	25,-25,-25,0		; 4
		dc.w	25,25,-25,0		; 8
		dc.w	-25,25,-25,0		; 12
		dc.w	-25,-25,25,0		; 16
		dc.w	25,-25,25,0		; 20
		dc.w	25,25,25,0		; 24
		dc.w	-25,25,25,0		; 28
		dc.w	0,0,-40,0		; 32
		dc.w	0,0,40,0		; 36
		dc.w	0,-40,0,0		; 40
		dc.w	0,40,0,0		; 44
		dc.w	-40,0,0,0		; 48
		dc.w	40,0,0,0		; 52

sv_faces_symbol:; Number of faces, normal vector length
		; -------------------------------------
		dc.w	30, (1<<(SV_NORMAL_SHIFT-4))*26
		; Room for face normal coordinates and X*Y value,
		; Room for rotated face normal coordinates,
		; Room for visibility value,
		; Number of vertices in face,
		; Vertex offsets (*4)
		; -------------------
		dc.w	0,0,0,0, 0,0,0, 0, 28, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,0
		dc.w	0,0,0,0, 0,0,0, 0, 28, 30,29,28,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30
		dc.w	0,0,0,0, 0,0,0, 0, 4, 0,28,29,1,0
		dc.w	0,0,0,0, 0,0,0, 0, 4, 1,29,30,2,1
		dc.w	0,0,0,0, 0,0,0, 0, 4, 2,30,31,3,2
		dc.w	0,0,0,0, 0,0,0, 0, 4, 3,31,32,4,3
		dc.w	0,0,0,0, 0,0,0, 0, 4, 4,32,33,5,4
		dc.w	0,0,0,0, 0,0,0, 0, 4, 5,33,34,6,5
		dc.w	0,0,0,0, 0,0,0, 0, 4, 6,34,35,7,6
		dc.w	0,0,0,0, 0,0,0, 0, 4, 7,35,36,8,7
		dc.w	0,0,0,0, 0,0,0, 0, 4, 8,36,37,9,8
		dc.w	0,0,0,0, 0,0,0, 0, 4, 9,37,38,10,9
		dc.w	0,0,0,0, 0,0,0, 0, 4, 10,38,39,11,10
		dc.w	0,0,0,0, 0,0,0, 0, 4, 11,39,40,12,11
		dc.w	0,0,0,0, 0,0,0, 0, 4, 12,40,41,13,12
		dc.w	0,0,0,0, 0,0,0, 0, 4, 13,41,42,14,13
		dc.w	0,0,0,0, 0,0,0, 0, 4, 14,42,43,15,14
		dc.w	0,0,0,0, 0,0,0, 0, 4, 15,43,44,16,15
		dc.w	0,0,0,0, 0,0,0, 0, 4, 16,44,45,17,16
		dc.w	0,0,0,0, 0,0,0, 0, 4, 17,45,46,18,17
		dc.w	0,0,0,0, 0,0,0, 0, 4, 18,46,47,19,18
		dc.w	0,0,0,0, 0,0,0, 0, 4, 19,47,48,20,19
		dc.w	0,0,0,0, 0,0,0, 0, 4, 20,48,49,21,20
		dc.w	0,0,0,0, 0,0,0, 0, 4, 21,49,50,22,21
		dc.w	0,0,0,0, 0,0,0, 0, 4, 22,50,51,23,22
		dc.w	0,0,0,0, 0,0,0, 0, 4, 23,51,52,24,23
		dc.w	0,0,0,0, 0,0,0, 0, 4, 24,52,53,25,24
		dc.w	0,0,0,0, 0,0,0, 0, 4, 25,53,54,26,25
		dc.w	0,0,0,0, 0,0,0, 0, 4, 26,54,55,27,26
		dc.w	0,0,0,0, 0,0,0, 0, 4, 27,55,28,0,27
		
sv_coordinates_symbol:
		; Number of coordinates
		; ---------------------
		dc.w	56
		; X, Y, Z and room for X*Y value
		; ------------------------------
		dc.w	-17,3,3,0
		dc.w	-39,3,3,0
		dc.w	-23,35,3,0
		dc.w	-3,35,3,0
		dc.w	-3,-12,3,0
		dc.w	-9,-18,3,0
		dc.w	-2,-34,3,0
		dc.w	3,-34,3,0
		dc.w	10,-18,3,0
		dc.w	4,-12,3,0
		dc.w	4,35,3,0
		dc.w	24,35,3,0
		dc.w	40,3,3,0
		dc.w	18,3,3,0
		dc.w	18,8,3,0
		dc.w	32,8,3,0
		dc.w	21,30,3,0
		dc.w	9,30,3,0
		dc.w	9,-11,3,0
		dc.w	16,-18,3,0
		dc.w	5,-39,3,0
		dc.w	-4,-39,3,0
		dc.w	-15,-18,3,0
		dc.w	-8,-11,3,0
		dc.w	-8,30,3,0
		dc.w	-20,30,3,0
		dc.w	-31,8,3,0
		dc.w	-17,8,3,0

		dc.w	-17,3,-3,0
		dc.w	-39,3,-3,0
		dc.w	-23,35,-3,0
		dc.w	-3,35,-3,0
		dc.w	-3,-12,-3,0
		dc.w	-9,-18,-3,0
		dc.w	-2,-34,-3,0
		dc.w	3,-34,-3,0
		dc.w	10,-18,-3,0
		dc.w	4,-12,-3,0
		dc.w	4,35,-3,0
		dc.w	24,35,-3,0
		dc.w	40,3,-3,0
		dc.w	18,3,-3,0
		dc.w	18,8,-3,0
		dc.w	32,8,-3,0
		dc.w	21,30,-3,0
		dc.w	9,30,-3,0
		dc.w	9,-11,-3,0
		dc.w	16,-18,-3,0
		dc.w	5,-39,-3,0
		dc.w	-4,-39,-3,0
		dc.w	-15,-18,-3,0
		dc.w	-8,-11,-3,0
		dc.w	-8,30,-3,0
		dc.w	-20,30,-3,0
		dc.w	-31,8,-3,0
		dc.w	-17,8,-3,0

sv_faces_list:	; Number of objects
		; -----------------
		dc.w	3
		; Coordinate pointers
		; -------------------
		dc.l	sv_faces_cube
		dc.l	sv_faces_24faces
		dc.l	sv_faces_symbol
		dc.l	sv_faces_cube

sv_coordinates_list:
		; Number of objects
		; -----------------
		dc.w	3
		; Coordinate pointers
		; -------------------
		dc.l	sv_coordinates_cube
		dc.l	sv_coordinates_24faces
		dc.l	sv_coordinates_symbol
		dc.l	sv_coordinates_cube

sv_palettes_list:
		; Palette pointers
		; -------------------
		dc.l	sv_palette_cube
		dc.l	sv_palette_24faces
		dc.l	sv_palette_symbol
		dc.l	sv_palette_cube

		; Jelly logo data
		; ---------------
jl_ct:		dc.w $1c01,$fffe
jl_ct_bplcon1:	dc.w bplcon1,%0000000000000000
jl_ct_bplcon0:	dc.w bplcon0,%0000000000000000+$1000*JL_PLANES
jl_ct_diwstrt:	dc.w diwstrt,$a831-256*JL_PLANEHEIGHT/2
jl_ct_diwstop:	dc.w diwstop,$00d1
jl_ct_ddfstrt:	dc.w ddfstrt,$88-2*JL_PLANEWIDTH
jl_ct_ddfstop:	dc.w ddfstop,$80+2*JL_PLANEWIDTH
jl_ct_palette:	dc.w $180,$000,$182,$000,$184,$000,$186,$000
		dc.w $188,$000,$18a,$000,$18c,$000,$18e,$000
jl_ct_bpl1mod:	dc.w bpl1mod,(JL_PLANES-1)*JL_PLANEWIDTH
jl_ct_bpl2mod:	dc.w bpl2mod,(JL_PLANES-1)*JL_PLANEWIDTH
		dc.w bpl1pth
jl_ct_bpl1pth:	dc.w 0,bpl1ptl
jl_ct_bpl1ptl:	dc.w 0,bpl2pth
jl_ct_bpl2pth:	dc.w 0,bpl2ptl
jl_ct_bpl2ptl:	dc.w 0,bpl3pth
jl_ct_bpl3pth:	dc.w 0,bpl3ptl
jl_ct_bpl3ptl:	dc.w 0
		dc.w $c801,$fffe
		dc.w bplcon0,0
		dc.w $ffff,$fffe
jl_ct_data:

jl_bitmap1_stc:	incbin	"jellylogo1.raw.stc"
jl_bitmap2_stc:	incbin	"jellylogo2.raw.stc"

vv_ct:		dc.w $0801,$fffe
vv_ct_bplcon1:	dc.w bplcon1,%0000000000000000
vv_ct_bplcon0:	dc.w bplcon0,%0000000000000001+$1000*VV_PLANES
vv_ct_diwstrt:	dc.w diwstrt,$a871-256*VV_PLANEHEIGHT/2
vv_ct_diwstop:	dc.w diwstop,$28d1
vv_ct_ddfstrt:	dc.w ddfstrt,$88-2*VV_PLANEWIDTH
vv_ct_ddfstop:	dc.w ddfstop,$80+2*VV_PLANEWIDTH
vv_ct_palette:	dc.w $180,$f8f,$182,$8ff
vv_ct_bpl1mod:	dc.w bpl1mod,0
vv_ct_bpl2mod:	dc.w bpl2mod,0
		dc.w bpl1pth
vv_ct_bpl1pth:	dc.w 0,bpl1ptl
vv_ct_bpl1ptl:	dc.w 0
		dc.w $ffff,$fffe
vv_ct_data:

vv_palettes:	dc.w	$8ff,$f8f,$ff8,$f88,$f8f,$8f8,$ff8,$88f
vv_table:	dc.l	vv_000000,vv_000001,vv_000002,vv_000003,vv_000004
		dc.l	vv_000005,vv_000006,vv_000007,vv_000008,vv_000009
		dc.l	vv_000010,vv_000011,vv_000012,vv_000013,vv_000014
		dc.l	vv_000015,vv_000016,vv_000017,vv_000018,vv_000019
		dc.l	vv_000020,vv_000021,vv_000022,vv_000023,vv_000024
		dc.l	vv_000025,vv_000026,vv_000027,vv_000028,vv_000029
		dc.l	vv_000030,vv_000031,vv_000032,vv_000033,vv_000034
		dc.l	vv_000035,vv_000036,vv_000037,vv_000038,vv_000039
		dc.l	vv_000040,vv_000041,vv_000042,vv_000043,vv_000044
		dc.l	vv_000045,vv_000046,vv_000047,vv_000048,vv_000049
		dc.l	vv_000050,vv_000051,vv_000052,vv_000053,vv_000054
		dc.l	vv_000055,vv_000056,vv_000057,vv_000058,vv_000059
		dc.l	vv_000060,vv_000061,vv_000062,vv_000063,vv_000064
		dc.l	vv_000065,vv_000066,vv_000067,vv_000068,vv_000069
		dc.l	vv_000070,vv_000071,vv_000072,vv_000073,vv_000074
		dc.l	vv_000075,vv_000076,vv_000077,vv_000078,vv_000079
		dc.l	vv_000080,vv_000081,vv_000082,vv_000083,vv_000084
		dc.l	vv_000085,vv_000086,vv_000087,vv_000088,vv_000089
;		dc.l	vv_000090,vv_000091,vv_000092,vv_000093,vv_000094
;		dc.l	vv_000095,vv_000096
		dc.l	vv_000097,vv_000098,vv_000099
		dc.l	vv_000100,vv_000101,vv_000102,vv_000103,vv_000104
;		dc.l	vv_000105,vv_000106
		dc.l	vv_000107,vv_000108,vv_000109
		dc.l	vv_000110,vv_000111,vv_000112,vv_000113,vv_000114
;		dc.l	vv_000115,vv_000116
		dc.l	vv_000117,vv_000118,vv_000119
		dc.l	vv_000120,vv_000121,vv_000122,vv_000123,vv_000124
;		dc.l	vv_000125,vv_000126
		dc.l	vv_000127,vv_000128,vv_000129
		dc.l	vv_000130,vv_000131,vv_000132,vv_000133,vv_000134
		dc.l	vv_000135,vv_000136,vv_000137,vv_000138,vv_000139
		dc.l	vv_000140,vv_000141,vv_000142,vv_000143,vv_000144
		dc.l	vv_000145,vv_000146,vv_000147,vv_000148,vv_000149
		dc.l	vv_000150,vv_000151,vv_000152,vv_000153,vv_000154
		dc.l	vv_000155,vv_000156,vv_000157,vv_000158,vv_000159
		dc.l	vv_000160,vv_000161,vv_000162,vv_000163,vv_000164
		dc.l	vv_000165,vv_000166,vv_000167,vv_000168,vv_000169
		dc.l	vv_000170,vv_000171,vv_000172,vv_000173,vv_000174
		dc.l	vv_000175,vv_000176
;		vv_000177,vv_000178,vv_000179
;		dc.l	vv_000180,vv_000181,vv_000182,vv_000183
VV_FRAMES	equ	(*-vv_table)/4

		include	"vectorvideo.i"
		even

module:		incbin	"major release.sng"

bz_cl			equ	chipmem
bz_cl_bplcon0		equ	bz_cl+(bz_ct_bplcon0-bz_ct)
bz_cl_bpl1pth		equ	bz_cl+(bz_ct_bpl1pth-bz_ct)
bz_cl_palette		equ	bz_cl+(bz_ct_palette-bz_ct)
bz_cl_data		equ	bz_cl+(bz_ct_data-bz_ct)
bz_planes		equ	bz_cl_data+(4+256*6+2+2+2)*2+4
bz_bitmap		equ	bz_planes+BZ_PLANESIZE*BZ_PLANES
bz_requirements_chipmem	equ	bz_bitmap+32800-bz_cl
bz_mulu_planewidth	equ	fastmem
bz_srcoffsets		equ	bz_mulu_planewidth+2*BZ_PLANEHEIGHT
bz_destoffsets		equ	bz_srcoffsets+256
bz_wait			equ	bz_destoffsets+256
bz_current		equ	bz_wait+2
bz_direction		equ	bz_current+1
bz_requirements_fastmem	equ	bz_direction+1-bz_mulu_planewidth

ch_cl			equ	chipmem
ch_cl_bplcon0		equ	ch_cl+(ch_ct_bplcon0-ch_ct)
ch_cl_bpl1pth		equ	ch_cl+(ch_ct_bpl1pth-ch_ct)
ch_cl_palette		equ	ch_cl+(ch_ct_palette-ch_ct)
ch_cl_data		equ	ch_cl+(ch_ct_data-ch_ct)
ch_planes		equ	ch_cl_data+(CH_PLANEHEIGHT*2*6+8)*2
ch_chunky		equ	ch_planes+2*CH_PLANESIZE*CH_PLANES
ch_tempbuffer1		equ	ch_chunky+4*CH_CHUNKY_SIZE
ch_tempbuffer2		equ	ch_tempbuffer1+CH_CHUNKY_SIZE
ch_requirements_chipmem	equ	ch_tempbuffer2+CH_CHUNKY_SIZE-ch_cl
ch_planes_add		equ	fastmem
ch_add			equ	ch_planes_add+4
ch_add_current		equ	ch_add+4
ch_c2p_pass		equ	ch_add_current+4
ch_dummy		equ	ch_c2p_pass+1
zr_source		equ	ch_dummy+1
zr_source_exp		equ	zr_source+CH_SOURCE_SIZE
zr_angle		equ	zr_source_exp+4*CH_SOURCE_SIZE*2
zr_angle_add		equ	zr_angle+4
zr_zoom			equ	zr_angle_add+4
zr_requirements_fastmem	equ	zr_zoom+2-ch_planes_add
sm_source		equ	ch_dummy+1
sm_source_exp		equ	sm_source+CH_SOURCE_SIZE
sm_x			equ	sm_source_exp+4*CH_SOURCE_SIZE*2
sm_y			equ	sm_x+2
sm_xsinus		equ	sm_y+2
sm_ysinus		equ	sm_xsinus+2
sm_write		equ	sm_ysinus+2
sm_write_end		equ	sm_write+33150
sm_requirements_fastmem	equ	sm_write_end+2-ch_planes_add
ct_buffer		equ	ch_dummy+1
ct_offset		equ	ct_buffer+CT_MAX_OFFSET*2
ct_rendered:		equ	ct_offset+2
ct_first_sin		equ	ct_rendered+2
ct_first		equ	ct_first_sin+2
ct_base_sin		equ	ct_first+2
ct_mult_sin		equ	ct_base_sin+2
ct_add_sin		equ	ct_mult_sin+2
ct_mult_16		equ	ct_add_sin+2
ct_write		equ	ct_mult_16+256
ct_write_end		equ	ct_write+32640
ct_requirements_fastmem	equ	ct_write_end+2-ch_planes_add

cs_cl			equ	chipmem
cs_cl_bplcon0		equ	cs_cl+(cs_ct_bplcon0-cs_ct)
cs_cl_bpl1pth		equ	cs_cl+(cs_ct_bpl1pth-cs_ct)
cs_cl_bpl2pth		equ	cs_cl+(cs_ct_bpl2pth-cs_ct)
cs_cl_palette		equ	cs_cl+(cs_ct_palette-cs_ct)
cs_cl_data		equ	cs_cl+(cs_ct_data-cs_ct)
cs_planes		equ	cs_cl_data+(((CS_PLANEHEIGHT-1)/16)*34+2+2+2+2+2)*2
cs_requirements_chipmem	equ	cs_planes+6*CS_PLANESIZE-cs_cl
cs_planes_add		equ	fastmem
cs_clipstorage		equ	cs_planes_add+4
cs_clip			equ	cs_clipstorage+16
cs_sinus		equ	cs_clip+2
cs_cosinus		equ	cs_sinus+2
cs_x			equ	cs_cosinus+2
cs_z			equ	cs_x+2
cs_octants		equ	cs_z+2
cs_oldxy		equ	cs_octants+4
cs_mulu_planewidth	equ	cs_oldxy+4
cs_order		equ	cs_mulu_planewidth+CS_PLANEHEIGHT*2
cs_mulu_16		equ	cs_order+32
cs_sinus_add		equ	cs_mulu_16+256
cs_sinus_add_add	equ	cs_sinus_add+4
cs_requirements_fastmem	equ	cs_sinus_add_add+4-cs_planes_add

dp_cl			equ	chipmem
dp_cl_bplcon0		equ	dp_cl+(dp_ct_bplcon0-dp_ct)
dp_cl_bplcon1		equ	dp_cl+(dp_ct_bplcon1-dp_ct)
dp_cl_bpl1pth		equ	dp_cl+(dp_ct_bpl1pth-dp_ct)
dp_cl_ddfstrt		equ	dp_cl+(dp_ct_ddfstrt-dp_ct)
dp_cl_ddfstop		equ	dp_cl+(dp_ct_ddfstop-dp_ct)
dp_cl_cop2lch		equ	dp_cl+(dp_ct_cop2lch-dp_ct)
dp_cl_cop2lcl		equ	dp_cl+(dp_ct_cop2lcl-dp_ct)
dp_cl_data		equ	dp_cl+(dp_ct_data-dp_ct)
dp_planes		equ	dp_cl_data+(4+256*6+34*62+2+2+2)*2*2+4
dp_requirements_chipmem	equ	dp_planes+DP_PLANESIZE*DP_PLANES-dp_cl
dp_planes_add		equ	fastmem
dp_copper_add		equ	dp_planes_add+4
dp_mulu_256		equ	dp_copper_add+4+128*256
dp_ysize		equ	dp_mulu_256+128*256
dp_sizepointer		equ	dp_ysize+2
dp_texturex		equ	dp_sizepointer+2
dp_texturey		equ	dp_texturex+2
dp_texxptr		equ	dp_texturey+2
dp_texyptr		equ	dp_texxptr+2
dp_xsinus		equ	dp_texyptr+2
dp_ysinus		equ	dp_xsinus+2
dp_jellysinus		equ	dp_ysinus+2
dp_jellyptr		equ	dp_jellysinus+2
dp_x			equ	dp_jellyptr+2
dp_ddfstrt		equ	dp_x+2
dp_ddfstop		equ	dp_ddfstrt+2
dp_bplcon1		equ	dp_ddfstop+2
dp_modulo		equ	dp_bplcon1+2
dp_mulu_planewidth	equ	dp_modulo+2+DP_PLANEHEIGHT*2
dp_table		equ	dp_mulu_planewidth
dp_jelly		equ	dp_table+512
dp_xoffsets		equ	dp_jelly+256*32
dp_yoffsets		equ	dp_xoffsets+256
dp_texture		equ	dp_yoffsets+34
dp_texture_hotfix	equ	dp_texture+32768
dp_synced		equ	dp_texture_hotfix+128*2
dp_requirements_fastmem	equ	dp_synced+1-dp_planes_add

fw_cl			equ	chipmem
fw_cl_bplcon0		equ	fw_cl+(fw_ct_bplcon0-fw_ct)
fw_cl_bpl1ptl		equ	fw_cl+(fw_ct_bpl1ptl-fw_ct)
fw_cl_bpl1pth		equ	fw_cl+(fw_ct_bpl1pth-fw_ct)
fw_cl_bpl2ptl		equ	fw_cl+(fw_ct_bpl2ptl-fw_ct)
fw_cl_bpl2pth		equ	fw_cl+(fw_ct_bpl2pth-fw_ct)
fw_cl_bpl3ptl		equ	fw_cl+(fw_ct_bpl3ptl-fw_ct)
fw_cl_bpl3pth		equ	fw_cl+(fw_ct_bpl3pth-fw_ct)
fw_cl_palette		equ	fw_cl+(fw_ct_palette-fw_ct)
fw_planes		equ	fw_cl+(fw_ct_data-fw_ct)
fw_plane		equ	fw_planes+2*FW_PLANES*FW_PLANESIZE
fw_requirements_chipmem	equ	fw_plane+FW_PLANESIZE-fw_cl
fw_planes_add		equ	fastmem
fw_part_speeds		equ	fw_planes_add+4
fw_part_coords		equ	fw_part_speeds+FW_NUMBER_OF_PARTICLES*2*4
fw_sinus		equ	fw_part_coords+FW_NUMBER_OF_PARTICLES*2*3*4
fw_mult			equ	fw_sinus+2
fw_asl			equ	fw_mult+2
fw_random		equ	fw_asl+2
fw_mulu_planewidth	equ	fw_random+2
fw_row_in_use		equ	fw_mulu_planewidth+FW_PLANEHEIGHT*2
fw_mulu_256		equ	fw_row_in_use+FW_ENDING_ROW-FW_STARTING_ROW+128*256
fw_symbol		equ	fw_mulu_256+128*256
fw_font			equ	fw_symbol+7168
fw_written		equ	fw_font+6208
fw_direction		equ	fw_written+1
fw_wait			equ	fw_direction+1
fw_requirements_fastmem	equ	fw_wait+2-fw_planes_add

fs_cl			equ	chipmem
fs_cl_bplcon0		equ	fs_cl+(fs_ct_bplcon0-fs_ct)
fs_cl_bpl1pth		equ	fs_cl+(fs_ct_bpl1pth-fs_ct)
fs_cl_bpl4ptl		equ	fs_cl+(fs_ct_bpl4ptl-fs_ct)
fs_cl_bpl4pth		equ	fs_cl+(fs_ct_bpl4pth-fs_ct)
fs_cl_palette		equ	fs_cl+(fs_ct_palette-fs_ct)
fs_planes		equ	fs_cl+(fs_ct_data-fs_ct)
fs_requirements_chipmem	equ	fs_planes+2*FS_PLANESIZE*FS_PLANES-fs_cl
fs_planes_add		equ	fastmem
fs_pointers		equ	fs_planes_add+4
fs_data			equ	fs_pointers+4
fs_mulu_planewidth	equ	fs_data+4
fs_mulu_256		equ	fs_mulu_planewidth+FS_PLANEHEIGHT*2+128*256
fs_sinus		equ	fs_mulu_256+128*256
fs_scalefactor		equ	fs_sinus+1024*2
fs_scalesinus		equ	fs_scalefactor+2
fs_rotatesinus		equ	fs_scalesinus+2
fs_rotate		equ	fs_rotatesinus+2
fs_yorigin		equ	fs_rotate+2
fs_xposition		equ	fs_yorigin+2
fs_xsinus		equ	fs_xposition+2
fs_sinusadd		equ	fs_xsinus+2
fs_data_1		equ	fs_sinusadd+2
fs_data_2		equ	fs_data_1+2948
fs_synced		equ	fs_data_2+12732
fs_requirements_fastmem	equ	fs_synced+1-fs_planes_add

ho_cl			equ	chipmem
ho_cl_bplcon0		equ	ho_cl+(ho_ct_bplcon0-ho_ct)
ho_cl_bpl1pth		equ	ho_cl+(ho_ct_bpl1pth-ho_ct)
ho_cl_cop2lcl		equ	ho_cl+(ho_ct_cop2lcl-ho_ct)
ho_cl_cop2lch		equ	ho_cl+(ho_ct_cop2lch-ho_ct)
ho_cl_palette		equ	ho_cl+(ho_ct_palette-ho_ct)
ho_cl_data1		equ	ho_cl+(ho_ct_data1-ho_ct)
ho_cl_data2		equ	ho_cl+(ho_ct_data2-ho_ct)+(64+56)*2
ho_planes		equ	ho_cl+(ho_ct_data-ho_ct)+(64+56)*2*2
ho_plane_empty		equ	ho_planes+2*HO_PLANESIZE*HO_PLANES
ho_plane_full		equ	ho_plane_empty+HO_PLANESIZE
ho_requirements_chipmem	equ	ho_plane_full+HO_PLANESIZE-ho_cl
ho_planes_add		equ	fastmem
ho_cl_data_add		equ	ho_planes_add+4
ho_rs_tempbuffer	equ	ho_cl_data_add+4
ho_table		equ	ho_rs_tempbuffer+8*4
ho_copper		equ	ho_table+4
ho_height		equ	ho_copper+8*4
ho_horizon_planes	equ	ho_height+4*2
ho_clear		equ	ho_horizon_planes+5*2
ho_pass			equ	ho_clear+2*2
ho_rs_distcount		equ	ho_pass+2
ho_minxx		equ	ho_rs_distcount+HO_PLANEHEIGHT
ho_minxy		equ	ho_minxx+2
ho_maxxx		equ	ho_minxy+2
ho_maxxy		equ	ho_maxxx+2
ho_substract		equ	ho_maxxy+2
ho_mulu_planewidth	equ	ho_substract+2
ho_frames		equ	ho_mulu_planewidth+HO_PLANES*HO_PLANEHEIGHT*2
ho_speed		equ	ho_frames+4
ho_order		equ	ho_speed+4
ho_requirements_fastmem	equ	ho_order+16*2-ho_planes_add

ir_cl			equ	chipmem
ir_cl_bplcon0		equ	ir_cl+(ir_ct_bplcon0-ir_ct)
ir_cl_bpl1pth		equ	ir_cl+(ir_ct_bpl1pth-ir_ct)
ir_cl_palette		equ	ir_cl+(ir_ct_palette-ir_ct)
ir_cl_cop2lch		equ	ir_cl+(ir_ct_cop2lch-ir_ct)
ir_cl_cop2lcl		equ	ir_cl+(ir_ct_cop2lcl-ir_ct)
ir_cl_data		equ	ir_cl+(ir_ct_data-ir_ct)
ir_planes		equ	ir_cl_data+(IR_RADIUS*2*6+2+4+2)*2*2
ir_requirements_chipmem	equ	ir_planes+IR_PLANESIZE*IR_PLANES-ir_cl
ir_copperlist_add	equ	fastmem
ir_y			equ	ir_copperlist_add+4
ir_wait			equ	ir_y+2
ir_direction		equ	ir_wait+2
ir_requirements_fastmem	equ	ir_direction+1-ir_copperlist_add

ip_cl			equ	chipmem
ip_cl_bplcon0		equ	ip_cl+(ip_ct_bplcon0-ip_ct)
ip_cl_palette		equ	ip_cl+(ip_ct_palette-ip_ct)
ip_cl_bpl2pth		equ	ip_cl+(ip_ct_bpl2pth-ip_ct)
ip_cl_cop1lcl		equ	ip_cl+(ip_ct_cop1lcl-ip_ct)
ip_cl_cop1lch		equ	ip_cl+(ip_ct_cop1lch-ip_ct)
ip_cl_1			equ	ip_cl+(ip_ct_1-ip_ct)
ip_cl_bpl1pth1		equ	ip_cl+(ip_ct_bpl1pth1-ip_ct)
ip_cl_data1		equ	ip_cl+(ip_ct_data1-ip_ct)
ip_cl_2			equ	ip_cl+(ip_ct_2-ip_ct)+(IP_PLANEHEIGHT*16+2+4+2+2)*2
ip_cl_bpl1pth2		equ	ip_cl+(ip_ct_bpl1pth2-ip_ct)+(IP_PLANEHEIGHT*16+2+4+2+2)*2
ip_cl_data2		equ	ip_cl+(ip_ct_data2-ip_ct)+(IP_PLANEHEIGHT*16+2+4+2+2)*2
ip_planes		equ	ip_cl+(ip_ct_data-ip_ct)+(IP_PLANEHEIGHT*16+2+4+2+2)*2*2
ip_planedata		equ	ip_planes+IP_PLANESIZE*IP_PLANES
ip_copperdata		equ	ip_planedata+2*4*IP_PLANEWIDTH
ip_requirements_chipmem	equ	ip_copperdata+16*16*25*2*2-ip_cl
ip_copperadd		equ	fastmem
ip_planeadd		equ	ip_copperadd+4
ip_copperptr		equ	ip_planeadd+4
ip_sinus		equ	ip_copperptr+16*16*4
ip_xsinus11		equ	ip_sinus+1024*2
ip_xsinus12		equ	ip_xsinus11+2
ip_xsinus21		equ	ip_xsinus12+2
ip_xsinus22		equ	ip_xsinus21+2
ip_ysinus11		equ	ip_xsinus22+2
ip_ysinus12		equ	ip_ysinus11+2
ip_ysinus21		equ	ip_ysinus12+2
ip_ysinus22		equ	ip_ysinus21+2
ip_zoom			equ	ip_ysinus22+2
ip_chunky		equ	ip_zoom+2
ip_set			equ	ip_chunky+IP_PLANEWIDTH*8
ip_direction		equ	ip_set+1
ip_requirements_fastmem	equ	ip_direction+1-ip_copperadd

ro_cl			equ	chipmem
ro_cl_bplcon0		equ	ro_cl+(ro_ct_bplcon0-ro_ct)
ro_cl_bpl1pth		equ	ro_cl+(ro_ct_bpl1pth-ro_ct)
ro_cl_palette		equ	ro_cl+(ro_ct_palette-ro_ct)
ro_planes		equ	ro_cl+(ro_ct_data-ro_ct)+4
ro_requirements_chipmem	equ	ro_planes+RO_PLANESIZE*RO_PLANES-ro_cl
ro_mulu_planewidth	equ	fastmem
ro_mulu_256		equ	ro_mulu_planewidth+RO_PLANEHEIGHT*2+128*256
ro_planes_add		equ	ro_mulu_256+128*256
ro_wait			equ	ro_planes_add+2
ro_waitdelta		equ	ro_wait+RO_SIZE/2*2
ro_sinuspointer		equ	ro_waitdelta+RO_SIZE/2*2
ro_multiplier		equ	ro_sinuspointer+2
ro_frame		equ	ro_multiplier+1
ro_requirements_fastmem	equ	ro_frame+1-ro_mulu_planewidth

sw_cl			equ	chipmem
sw_cl_bplcon0		equ	sw_cl+(sw_ct_bplcon0-sw_ct)
sw_cl_bpl1pth		equ	sw_cl+(sw_ct_bpl1pth-sw_ct)
sw_cl_palette		equ	sw_cl+(sw_ct_palette-sw_ct)
sw_cl_data		equ	sw_cl+(sw_ct_data-sw_ct)
sw_planes		equ	sw_cl+(sw_ct_data-sw_ct)+(6+256*6+2+6)*2
sw_requirements_chipmem	equ	sw_planes+520*SW_PLANEWIDTH*SW_PLANES-sw_cl
sw_mulu_planewidth	equ	fastmem
sw_y			equ	sw_mulu_planewidth+SW_HEIGHT*2
sw_rows			equ	sw_y+4
sw_offsets		equ	sw_rows+2
sw_heights		equ	sw_offsets+256
sw_bitmap		equ	sw_heights+256
sw_requirements_fastmem	equ	sw_bitmap+SW_BITMAP_HEIGHT*SW_WIDTH-sw_mulu_planewidth

sv_cl			equ	chipmem
sv_cl_bplcon0		equ	sv_cl+(sv_ct_bplcon0-sv_ct)
sv_cl_bpl1pth		equ	sv_cl+(sv_ct_bpl1pth-sv_ct)
sv_cl_palette		equ	sv_cl+(sv_ct_palette-sv_ct)
sv_planes		equ	sv_cl+(sv_ct_data-sv_ct)
sv_mask			equ	sv_planes+2*SV_PLANESIZE*SV_PLANES
sv_stencil		equ	sv_mask+SV_PLANESIZE
sv_requirements_chipmem	equ	sv_stencil+SV_PLANES*SV_STENCIL_SIZE-sv_cl
sv_planes_add		equ	fastmem
sv_angles_add		equ	sv_planes_add+4
sv_coordinates		equ	sv_angles_add+12
sv_faces		equ	sv_coordinates+4
sv_distance		equ	sv_faces+4
sv_distance_old		equ	sv_distance+2
sv_object		equ	sv_distance_old+2
sv_angles		equ	sv_object+2
sv_rotate		equ	sv_angles+6*2
sv_oldcoords		equ	sv_rotate+15*2
sv_mulu_planewidth	equ	sv_oldcoords+2*2
sv_rotated		equ	sv_mulu_planewidth+SV_STENCIL_HEIGHT*2
sv_faces_z		equ	sv_rotated+56*4*2
sv_rs_tempbuffer	equ	sv_faces_z+(1+3*30)*2
sv_octants		equ	sv_rs_tempbuffer+3*30*2
sv_boundaries		equ	sv_octants+4
sv_rs_distcount		equ	sv_boundaries+4*2
sv_table_sqrt		equ	sv_rs_distcount+256
sv_object_change	equ	sv_table_sqrt+257
sv_angles_lock		equ	sv_object_change+1
sv_requirements_fastmem	equ	sv_object_change+3-sv_planes_add
sv_pre_set		equ	sv_object_change
sv_pre_fader		equ	sv_pre_set+1
sv_pre_wait		equ	sv_pre_fader+2

jl_cl			equ	chipmem
jl_cl_bplcon0		equ	jl_cl+(jl_ct_bplcon0-jl_ct)
jl_cl_bpl1pth		equ	jl_cl+(jl_ct_bpl1pth-jl_ct)
jl_cl_palette		equ	jl_cl+(jl_ct_palette-jl_ct)
jl_planes		equ	jl_cl+(jl_ct_data-jl_ct)
jl_bitmap		equ	jl_cl+(jl_ct_data-jl_ct)+2*JL_PLANES*JL_PLANESIZE
jl_requirements_chipmem	equ	jl_bitmap+JL_PLANES*JL_PLANESIZE+16-jl_cl
jl_planes_add		equ	fastmem
jl_multiplier		equ	jl_planes_add+4
jl_sinuspointer		equ	jl_multiplier+4
jl_sinusadd		equ	jl_sinuspointer+2
jl_x			equ	jl_sinusadd+2
jl_reset		equ	jl_x+2
jl_requirements_fastmem	equ	jl_reset+1-jl_planes_add

vv_cl			equ	chipmem
vv_cl_bplcon0		equ	vv_cl+(vv_ct_bplcon0-vv_ct)
vv_cl_bpl1pth		equ	vv_cl+(vv_ct_bpl1pth-vv_ct)
vv_cl_bpl1ptl		equ	vv_cl+(vv_ct_bpl1ptl-vv_ct)
vv_cl_palette		equ	vv_cl+(vv_ct_palette-vv_ct)
vv_planes		equ	vv_cl+(vv_ct_data-vv_ct)
vv_requirements_chipmem	equ	vv_planes+2*VV_PLANES*VV_PLANESIZE-vv_cl
vv_planes_add		equ	fastmem
vv_pointer		equ	vv_planes_add+4
vv_frame		equ	vv_pointer+4
vv_palette_current	equ	vv_frame+2
vv_octants		equ	vv_palette_current+4
vv_mulu_planewidth	equ	vv_octants+4
vv_fader		equ	vv_mulu_planewidth+2*VV_PLANEHEIGHT
vv_set			equ	vv_fader+2
vv_wait			equ	vv_set+1
vv_requirements_fastmem	equ	vv_wait+1-vv_planes_add
			end
