RELEASE_VERSION	EQU	0			; Inofficial !!!
DEBUG_VERSION	EQU	0			; Debug Code On/Off


	IFEQ DEBUG_VERSION
	opt o-,d-
	ELSE
	opt o-,x+
	ENDC

	incdir	"Includes:"
	include	"exec/exec.i"
	include	"dos/dos.i"
	include	"graphics/gfxbase.i"
	include	"hardware/intbits.i"
	include	"intuition/intuition.i"
	include	"libraries/gadtools.i"
	include	"misc/DevpacMacros.i"
	include	"misc/DeliPlayer6.i"

_LVOWriteChunkyPixels	EQU -1056

;
;
	SECTION GenieCode,Code
;
;

	PLAYERHEADER GenieTagArray

	dc.b '$VER: DrWhoGenie genie module V1.2 (28 Apr 95)',0
	even

GenieTagArray
	dc.l	DTP_RequestKickVersion,39
	dc.l	DTP_RequestDTVersion,17
	dc.l	DTP_PlayerVersion,01<<16+20
	dc.l	DTP_PlayerName,GName
	dc.l	DTP_Creator,CName
	dc.l	DTP_Description,DName
	dc.l	DTP_DeliBase,delibase
	dc.l	DTP_Process,Begin
	dc.l	DTP_Priority,-25
	dc.l	DTP_StackSize,4096
	dc.l	DTP_MsgPort,DeliPort
	dc.l	DTP_NoteInfo,NoteInfo
	dc.l	DTP_NoteSignal,NoteSignal
	dc.l	DTP_Appear,Appear
	dc.l	DTP_Disappear,Disappear
	dc.l	DTP_InitPlayer,InitPlay
	dc.l	DTP_EndPlayer,EndPlay
	dc.l	DTP_InitSound,InitSnd
	dc.l	DTP_EndSound,EndSnd
	dc.l	DTP_StartInt,StartSnd
	dc.l	DTP_StopInt,StopSnd
	dc.l	TAG_DONE

*-----------------------------------------------------------------------*
;
; Genie/Creatorname/Description und lokale Daten

GName	dc.b 'DrWhoGenie',0
CName	dc.b 'written by Delirium in 1994-95',10
	dc.b '(based on the ''DrWho'' routines',10
	dc.b 'programmed by Chaos/Sanity)',0
DName	dc.b 'this genie displays a rotating tunnel',10
	dc.b 'known from the Sanity Demo ''ARTE''',0
	even

	IFNE DEBUG_VERSION

ConsoleName	dc.b 'CON:80/125/400/160/DrWhoGenie_Debug',0
	even

InformationFmt	dc.b '%s',10,0
FuncCallFmt	dc.b '%s called',10,0
MakeLineFmt	dc.b 'SinePtr: %u',10,0
	even

ProcStartTxt	dc.b 'Process started',0
ProcEndTxt	dc.b 'Process ended',0
GadgetupTxt	dc.b 'Gadgetup message',0
OpenWinTxt	dc.b 'OpenWindow called',0
CloseWinTxt	dc.b 'CloseWindow called',0
NoteInitTxt	dc.b 'NoteInit called',0
NoteFiniTxt	dc.b 'NoteFinish called',0
Check2Txt	dc.b 'DTP_Check2',0
ConvertTxt	dc.b 'DTP_Convert',0
InitPlayTxt	dc.b 'DTP_InitPlayer',0
EndPlayTxt	dc.b 'DTP_EndPlayer',0
InitSndTxt	dc.b 'DTP_InitSound',0
EndSndTxt	dc.b 'DTP_EndSound',0
StartIntTxt	dc.b 'DTP_StartInt',0
StopIntTxt	dc.b 'DTP_StopInt',0
VolumeTxt	dc.b 'DTP_Volume',0
BalanceTxt	dc.b 'DTP_Balance',0
AppearTxt	dc.b 'DTP_Appear',0
DisappearTxt	dc.b 'DTP_Disappear',0
	even

_OldOutput	dc.l 0

	ENDC

*-----------------------------------------------------------------------*
;
; Player Process

Begin
	move.l	delibase,a5			; get DeliBase
	move.l	dtg_DOSBase(a5),_DOSBase
	move.l	dtg_GfxBase(a5),_GfxBase
	move.l	dtg_GadToolsBase(a5),_GadToolsBase
	move.l	dtg_IntuitionBase(a5),_IntuitionBase

	lea	mathffpname,a1			; open mathffp.library
	CALLEXEC OldOpenLibrary
	move.l	d0,_MathBase
	beq	Quit				; Error

	lea	mathtransname,a1		; open mathtrans.library
	CALLEXEC OldOpenLibrary
	move.l	d0,_MathTransBase
	beq	RemMFFP				; Error

	lea	utilityname,a1			; open utility.library
	CALLEXEC OldOpenLibrary
	move.l	d0,_UtilityBase
	beq	RemMTrans			; Error

	IFNE DEBUG_VERSION

	move.l	#ConsoleName,d1
	move.l	#MODE_NEWFILE,d2
	CALLDOS Open
	move.l	d0,d1
	beq	RemUtil				; Error
	CALLDOS SelectOutput
	move.l	d0,_OldOutput

	ENDC

	move.l	4.w,a6				; ^ExecBase
	cmpi.w	#39,LIB_VERSION(a6)		; check Exec-Version
	beq.s	OldKick				; WCP is not implemented !

	move.w	WCPFlag,d0
	andi.w	#~NM_ITEMDISABLED,d0
	move.w	d0,WCPFlag

	move.l	_GfxBase,a6
	tst.l	gb_ChunkyToPlanarPtr(a6)	; special C2P hardware present ?
	beq.s	OldKick

	move.w	C2PFlag,d0
	andi.w	#~CHECKED,d0
	move.w	d0,C2PFlag

	move.w	WPAFlag,d0
	andi.w	#~CHECKED,d0
	move.w	d0,WPAFlag

	move.w	WCPFlag,d0
	ori.w	#CHECKED,d0
	move.w	d0,WCPFlag
OldKick
	moveq	#-1,d0				; allocate VBlank Signal
	CALLEXEC AllocSignal
	move.b	d0,VBlankSigBit
	bmi	OldOutput

	move.l	4.w,a6
	move.l	ThisTask(a6),VBlankSigTask	; copy ^ThisTask

	CALLEXEC CreateMsgPort			; Port für Timer besorgen
	move.l	d0,_TimePort
	beq	FreeSig

	lea	TimeRequest,a0			; set ReplyPort for TimeRequest
	move.l	d0,MN_REPLYPORT(a0)

	lea	timername,a0
	lea	TimeRequest,a1
	moveq	#UNIT_VBLANK,d0
	moveq	#0,d1
	CALLEXEC OpenDevice			; timer.device öffnen
	tst.l	d0
	bne	RemTime

	lea	TempRas,a0			; TmpRas initialisieren
	lea	TmpRasBuffer,a1
	move.l	#4096,d0
	CALLGFX InitTmpRas

	lea	TempRPort,a1			; RastPort initialisieren
	CALLGFX InitRastPort

	IFNE DEBUG_VERSION
	move.l	#ProcStartTxt,-(sp)
	lea	InformationFmt(pc),a0
	bsr	WriteInfoTxt
	addq.w	#4,sp
	ENDC

	bsr	GenSinus

	bsr	GenArcSinus

	bsr	SineInit

	bsr	LoadGenieConfig			; Load Config

	bsr	SetColorMode

	move.w	ACTFlag,d0
	andi.w	#CHECKED,d0			; CHECKED ?
	bne.s	Activate
	andi.l	#~WFLG_ACTIVATE,GenieWinFlags+4
Activate
	move.w	PUPFlag,d0
	andi.w	#CHECKED,d0			; CHECKED ?
	beq.s	NoPopup
	bsr	OpenGenieWindow			; Open GenieWindow
NoPopup
	ori.l	#WFLG_ACTIVATE,GenieWinFlags+4

;--------------------------------------------------------------------------
;
; Hauptschleife

MainLoop
	move.l	#SIGBREAKF_CTRL_C,d0		; quit on CTRL-C

	move.b	VBlankSigBit,d1			; VBlankSignal holen
	bset.l	d1,d0

	move.l	DeliPort,a0
	move.b	MP_SIGBIT(a0),d1		; DeliMask holen
	bset.l	d1,d0

	move.l	_GenieWindow,d1			; GenieWindowMask holen
	beq.s	NoGenieWin
	move.l	d1,a0
	move.l	wd_UserPort(a0),a0
	move.b	MP_SIGBIT(a0),d1
	bset.l	d1,d0
NoGenieWin
	bset.b	#0,VBlankSigFlag

	CALLEXEC Wait				; Schlaf gut

	move.l	d0,d2				; copy SignalMask

	btst.l	#SIGBREAKB_CTRL_C,d2		; CTRL-C signal ?
	beq.s	VBlankCollect			; nope !
	bsr	Exit				; suicide :)

VBlankCollect					; test VBlank signal
	move.b	VBlankSigBit,d1
	btst.l	d1,d2
	beq.s	DeliCollect
	bsr	DisplayScope

DeliCollect					; collect DeliTracker msg's
	move.l	DeliPort,a0
	CALLEXEC GetMsg
	tst.l	d0				; Msg da ?
	beq.s	GenieCollect			; Nein !
	move.l	d0,-(sp)			; store ^Msg
	move.l	d0,a0
	move.l	DTMN_Function(a0),a0		; get CMD
	jsr	(a0)				; Befehl ausführen
	move.l	(sp)+,a1			; restore ^Msg
	move.l	d0,DTMN_Result(a1)		; set Result
	CALLEXEC ReplyMsg			; return to sender
	bra.s	DeliCollect

GenieCollect
	move.l	_GenieWindow,d0			; GenieWindowPort
	beq.s	CollectDone			; Window ist zu !
	move.l	d0,a0
	move.l	wd_UserPort(a0),a0
	CALLGADTOOLS GT_GetIMsg
	move.l	d0,_IntuiMessage		; keine weitere Msg ?
	beq.s	CollectDone			; Ja !
	move.l	d0,a2				; ^IntuiMessage
	move.l	im_Class(a2),d2			; Class bits
	move.w	im_Code(a2),d3			; Code field
	move.w	im_Qualifier(a2),d4		; Qualifier
	move.l	im_Seconds(a2),d5		; Systemzeit secs
	move.l	im_Micros(a2),d6		; Systemzeit micros
	move.l	im_IAddress(a2),a3		; Auslösendes Intuitionobjekt
	move.l	im_IDCMPWindow(a2),a4		; Window dieses IDCMP's
	bsr	GenieWinSelect
	move.l	_IntuiMessage,d0		; Für ReplyMsg
	beq.s	GenieCollect			; wurde schon replyed !
	move.l	d0,a1
	CALLGADTOOLS GT_ReplyIMsg		; Zurück an Sender
	clr.l	_IntuiMessage
	bra.s	GenieCollect

CollectDone
	tst.w	QuitFlag			; schon Ende ?
	bne	MainLoop			; noch nicht !

;--------------------------------------------------------------------------
;
; quit Player

Cleanup
	bsr	CloseGenieWindow

	bsr	StopSnd

	bsr	EndPlay

	IFNE DEBUG_VERSION
	move.l	#ProcEndTxt,-(sp)
	lea	InformationFmt(pc),a0
	bsr	WriteInfoTxt
	addq.w	#4,sp
	ENDC
CloseTime
	lea	TimeRequest,a1
	CALLEXEC CloseDevice			; timer.device schließen
RemTime
	move.l	_TimePort,a0			; Time Port entfernen
	CALLEXEC DeleteMsgPort
FreeSig
	move.b	VBlankSigBit,d0			; free VBlank Signal
	CALLEXEC FreeSignal
OldOutput
	IFNE DEBUG_VERSION

	move.l	_OldOutput,d1
	CALLDOS SelectOutput
	move.l	d0,d1
	CALLDOS Close

	ENDC
RemUtil
	move.l	_UtilityBase,a1			; close utility.library
	CALLEXEC CloseLibrary
RemMTrans
	move.l	_MathTransBase,a1		; close mathtrans.library
	CALLEXEC CloseLibrary
RemMFFP
	move.l	_MathBase,a1			; close mathffp.library
	CALLEXEC CloseLibrary
Quit
	rts					; Playerprozess beenden

;--------------------------------------------------------------------------
;
; End Player

Exit
	clr.w	QuitFlag			; Player beenden
	rts

;--------------------------------------------------------------------------
;
; Write Info Text
; a0:^Text/sp:Daten

	IFNE DEBUG_VERSION

WriteInfoTxt
	move.l	d2,-(sp)
	move.l	a0,d1
	move.l	sp,d2
	addq.l	#8,d2
	CALLDOS VPrintf
	move.l	(sp)+,d2
	rts

	ENDC

*-----------------------------------------------------------------------*

GenieWinSelect
	cmpi.l	#IDCMP_CLOSEWINDOW,d2		; Hide ?
	beq	CloseGenieWindow
	cmpi.l	#IDCMP_CHANGEWINDOW,d2		; Move/Size ?
	beq	GenieWinCoords
	cmpi.l	#IDCMP_SIZEVERIFY,d2		; Resize ?
	beq	ResizeGenieWin
	cmpi.l	#IDCMP_NEWSIZE,d2		; Refresh ?
	beq	UpdateGenieWin
	cmpi.l	#IDCMP_MENUPICK,d2		; Menü ?
	beq	DoMenuPick
	cmpi.l	#IDCMP_MOUSEMOVE,d2		; Slider ?
	beq	DoGadget
	cmpi.l	#IDCMP_GADGETUP,d2		; Gadget ?
	beq	DoGadget
;	cmpi.l	#IDCMP_VANILLAKEY,d2		; Shortcut ?
;	beq	DoShortCut
	rts

*-----------------------------------------------------------------------*

DoGadget
	move.l	gg_UserData(a3),d0		; GadgetUserData ermitteln
	beq.s	DoGadgetEnd			; raus, falls nicht benutzt
	move.l	d0,a0				; Pointer kopieren
	jsr	(a0)				; Routine anspringen
DoGadgetEnd
	rts

*-----------------------------------------------------------------------*

DoMenuPick
	move.w	d3,d0				; menu number
	move.l	wd_MenuStrip(a4),a0		; ^menu
	CALLINT ItemAddress			; get MenuAdress
	tst.l	d0				; ok ?
	beq.s	DMP_End
	move.l	d0,a1
	move.w	mi_NextSelect(a1),d3		; next menunumber
	GTMENUITEM_USERDATA a1,d0		; get UserData
	tst.l	d0
	beq.s	DoMenuPick			; no function
	move.l	d0,a0
	movem.l	d2-d7/a2-a6,-(sp)		; save registers
	jsr	(a0)				; call menu function
	movem.l	(sp)+,d2-d7/a2-a6		; restore registers
	tst.l	_IntuiMessage			; Message noch gültig ?
	bne.s	DoMenuPick			; Ja !
DMP_End	rts

*-----------------------------------------------------------------------*
;
; GenieWindow öffnen bzw. aktivieren

OpenGenieWindow
	move.l	_GenieWindow,d2			; is the window already open ?
	beq.s	OGW_Window			; no, open the window

	move.l	d2,a0				; ^Window
	CALLINT	WindowToFront			; bring the window to the front

	move.l	d2,a0				; ^Window
	CALLINT	ActivateWindow			; activate the window
	bra	OGW_End
OGW_Window
	bsr	LockScreen			; get the screen, on that we open
	move.l	d0,WindowPubScrn+4		; and save for later use
	beq	OGW_End				; no screen for opening available!

	bsr	CalcGenieGads			; Gadgetpositionen etc. berechnen

	lea	GenieWindow,a1			; Window
	suba.l	a0,a0
	CALLINT OpenWindowTagList		; Window sollte aufgehen (WA_AutoAdjust)
	move.l	d0,_GenieWindow			; Window really open ?
	beq	CGW_Reset			; Nein, dann Screen wieder freigeben
	move.l	d0,d2

	move.l	d2,a0				; TmpRas einhängen
	move.l	wd_RPort(a0),a0
	lea	TempRas,a1
	move.l	a1,rp_TmpRas(a0)

	move.l	d2,a0				; ^Window
	suba.l	a1,a1				; should always be NULL
	CALLGADTOOLS GT_RefreshWindow		; refresh all GadTools gadgets

	lea	GenieBevelBoxTable,a0
	move.l	d2,a1
	bsr	CreateBevelBoxes		; draw BevelBoxes

	lea	GenieMenu,a0			; make menus
	sub.l	a1,a1
	CALLGADTOOLS CreateMenusA
	move.l	d0,_GenieMenuStrip
	beq	CGW_RemTmpRas

	move.l	d0,a0				; align menus
	move.l	_VisualInfo,a1
	lea	MenuTags,a2
	CALLGADTOOLS LayoutMenusA
	tst.l	d0
	beq.s	CGW_FreeMenu

	move.l	d2,a0				; Menu anlegen
	move.l	_GenieMenuStrip,a1
	CALLINT SetMenuStrip
	tst.l	d0
	beq.s	CGW_FreeMenu

	bsr	AllocPens			; Scope-Pens allocieren
	tst.l	d0
	beq.s	CGW_ClearMenu

	bsr	AllocChunky			; Scopy-Chunky allocieren
	tst.l	d0
	beq.s	CGW_FreePens

	bsr	AllocBitMap			; Scope-BitMap allocieren
	tst.l	d0
	beq.s	CGW_FreeChunky

	bsr	AllocTempRP			; Temp. RastPort allocieren
	tst.l	d0
	beq.s	CGW_FreeBitMap

	bsr	AllocTunnel			; Tunnel-Tabelle allocieren
	tst.l	d0
	beq.s	CGW_FreeTmpRP

	bsr	TunnelInit			; Tunnel-Tabelle berechnen

	bsr	PixInit				; Picture löschen

	bsr	ClearScope
OGW_End
	rts

*-----------------------------------------------------------------------*
;
; GenieWindow schließen

CloseGenieWindow
	tst.l	_GenieWindow			; Window offen ?
	beq	CGW_End				; Nein !
CGW_FreeTunnel
	bsr	FreeTunnel			; Tunnel-Tabelle freigeben
CGW_FreeTmpRP
	bsr	FreeTempRP			; Temp. RastPort freigeben
CGW_FreeBitMap
	bsr	FreeBitMap			; Scope-BitMap freigeben
CGW_FreeChunky
	bsr	FreeChunky			; Scopy-Chunky freigeben
CGW_FreePens
	bsr	FreePens			; Scope-Pens freigeben
CGW_ClearMenu
	move.l	_GenieWindow,a0			; Menüs aus
	CALLINT ClearMenuStrip
CGW_FreeMenu
	move.l	_GenieMenuStrip,a0		; free menu mem
	CALLGADTOOLS FreeMenus
CGW_RemTmpRas
	CALLGFX WaitBlit			; TmpRas aushängen
	move.l	_GenieWindow,a0
	move.l	wd_RPort(a0),a0
	clr.l	rp_TmpRas(a0)
CGW_ReplyMsg
	move.l	_IntuiMessage,d0		; Für ReplyMsg
	beq.s	CGW_CloseWin			; wurde schon replyed !
	move.l	d0,a1
	CALLGADTOOLS GT_ReplyIMsg		; Zurück an Sender
	clr.l	_IntuiMessage
CGW_CloseWin
	move.l	_GenieWindow,a0
	CALLINT CloseWindow			; Window zu
	clr.l	_GenieWindow
CGW_Reset
	bsr	UnlockScreen			; now it's time to unlock the screen
CGW_End
	rts

*-----------------------------------------------------------------------*
;
; GenieWindow-Koordinaten nach Verschieben/Resize sichern

GenieWinCoords
	move.l	_GenieWindow,d0
	beq.s	GWC_End				; kein Window, also raus !
	move.l	d0,a0
	lea	GenieWindow,a1
	move.w	wd_LeftEdge(a0),6(a1)		; WA_Left
	move.w	wd_TopEdge(a0),14(a1)		; WA_Top
	move.w	wd_Width(a0),d0
	moveq	#0,d1
	move.b	wd_BorderLeft(a0),d1
	sub.w	d1,d0
	move.b	wd_BorderRight(a0),d1
	sub.w	d1,d0
	move.w	d0,22(a1)			; WA_InnerWidth
	move.w	wd_Height(a0),d0
	moveq	#0,d1
	move.b	wd_BorderTop(a0),d1
	sub.w	d1,d0
	move.b	wd_BorderBottom(a0),d1
	sub.w	d1,d0
	move.w	d0,30(a1)			; WA_InnerHeight
GWC_End
	rts

*-----------------------------------------------------------------------*
;
; GenieWindow-Display auf ReSize vorbereiten

ResizeGenieWin
	movem.l	d2-d4/a2-a4,-(sp)

	move.l	_GenieWindow,d0
	beq	RGW_End				; kein Window !
	move.l	d0,a4

	CALLGFX WaitBlit			; TmpRas aushängen
	move.l	wd_RPort(a4),a0
	clr.l	rp_TmpRas(a0)

	bsr	FreeTunnel			; Tunnel-Tabelle freigeben

	bsr	FreeTempRP			; Temp. RastPort freigeben

	bsr	FreeBitMap			; Scope-BitMap freigeben

	bsr	FreeChunky			; Scopy-Chunky freigeben
RGW_End
	movem.l	(sp)+,d2-d4/a2-a4
	rts

*-----------------------------------------------------------------------*
;
; GenieWindow-Display nach Zip/UnZip/ReSize updaten

UpdateGenieWin
	movem.l	d2-d4/a2-a4,-(sp)

	move.l	_GenieWindow,d0
	beq	UGW_End				; kein Window !
	move.l	d0,a4

	bsr	GenieWinCoords			; Windowdimensionen ermitteln

	bsr	CalcGenieGads			; Gadgetpositionen etc. berechnen

	move.l	wd_RPort(a4),a0			; TmpRas einhängen
	lea	TempRas,a1
	move.l	a1,rp_TmpRas(a0)

	bsr	AllocChunky			; Scopy-Chunky allocieren
	tst.l	d0
	beq.s	UGW_CloseWindow

	bsr	AllocBitMap			; Scope-BitMap allocieren
	tst.l	d0
	beq.s	UGW_FreeChunky

	bsr	AllocTempRP			; Temp. RastPort allocieren
	tst.l	d0
	beq.s	UGW_FreeBitMap

	bsr	AllocTunnel			; Tunnel-Tabelle allocieren
	tst.l	d0
	bne.s	UGW_Okay
UGW_FreeTmpRP
	bsr	FreeTempRP			; Temp. RastPort freigeben
UGW_FreeBitMap
	bsr	FreeBitMap			; Scope-BitMap freigeben
UGW_FreeChunky
	bsr	FreeChunky			; Scopy-Chunky freigeben
UGW_CloseWindow
	bsr	CloseGenieWindow		; Geniewindow schließen
	bra	UGW_End
UGW_Okay
	move.l	wd_RPort(a4),a1
	moveq	#0,d0
	move.w	wd_Width(a4),d2
	move.b	wd_BorderRight(a4),d0
	sub.w	d0,d2
	subq.w	#1,d2
	move.b	wd_BorderLeft(a4),d0
	moveq	#0,d1
	move.w	wd_Height(a4),d3
	move.b	wd_BorderBottom(a4),d1
	sub.w	d1,d3
	subq.w	#1,d3
	move.b	wd_BorderTop(a4),d1
	CALLGFX EraseRect			; alten Windowinhalt löschen

	lea	GenieBevelBoxTable,a0
	move.l	a4,a1
	bsr	CreateBevelBoxes		; draw BevelBoxes

	bsr	TunnelInit			; Tunnel-Tabelle berechnen
UGW_End
	movem.l	(sp)+,d2-d4/a2-a4
	rts

*-----------------------------------------------------------------------*
;
; GenieWindow-Gadget&Bevelboxes Koordinaten berechnen

CalcGenieGads
	movem.l	d2-d5/a2-a4,-(sp)

	lea	GenieWindow,a4			; Window

	move.w	22(a4),d2
	move.w	d2,d4
	subi.w	#8+8+2+2,d4
	andi.w	#~15,d4				; Rest-Windowbreite
	sub.w	d4,d2
	lsr.w	#1,d2				; linker Randabstand

	move.w	30(a4),d3
	move.w	d3,d5
	subi.w	#4+4+1+1,d5
	andi.w	#~1,d5				; Rest-Windowhöhe
	sub.w	d5,d3
	lsr.w	#1,d3				; oberer Randabstand

	move.w	d4,ScopeWidth			; Breite der Scope-Bitmap
	move.w	d5,ScopeHeight			; Höhe der Scope-Bitmap

	lea	GenieBBArray1,a0		; obere Bevelbox
	subi.w	#2,d2
	move.w	d2,0(a0)			; X-Coord
	subi.w	#1,d3
	move.w	d3,2(a0)			; Y-Coord
	addi.w	#2+2,d4
	move.w	d4,4(a0)			; Width
	addi.w	#1+1,d5
	move.w	d5,6(a0)			; Height
CGG_End
	movem.l	(sp)+,d2-d5/a2-a4
	rts

*-----------------------------------------------------------------------*
;
; Gadget-Creation Routine
; in: (a0:^WindowTagList/a1:^GadgetTable)
; out: (d0:success)

CreateGadgets
	movem.l	d2-d3/a2-a4,-(sp)
	move.l	a1,a4				; ^Table with gadget definitions

	move.l	#WA_Gadgets,d0
	CALLUTIL FindTagItem
	move.l	d0,d3
	beq	CG_CreateEnd			; error !

	move.l	d0,a0				; create a place for context data
	lea	ti_Data(a0),a0
	CALLGADTOOLS CreateContext
	move.l	d0,d3
	beq	CG_CreateEnd			; error !

	sub.w	#gng_SIZEOF,sp
CG_CreateGadLoop
	move.l	(a4)+,d0			; get arrayptr
	beq	CG_CreateGadEnd			; End of Gadget List reached !
	move.l	d0,a3				; ^GadgetArray
	clr.w	gng_GadgetID(sp)		; gadget ID
	move.l	_GenieScreen,a0
	moveq	#0,d0
	move.b	sc_WBorLeft(a0),d0
	add.w	12(a3),d0
	move.w	d0,gng_LeftEdge(sp)		; x-pos
	move.l	_GenieScreen,a0
	moveq	#0,d0
	move.b	sc_WBorTop(a0),d0
	move.l	sc_Font(a0),a0
	add.w	ta_YSize(a0),d0
	addq.w	#1,d0
	add.w	14(a3),d0
	move.w	d0,gng_TopEdge(sp)		; y-pos
	move.w	16(a3),gng_Width(sp)		; width
	move.w	18(a3),gng_Height(sp)		; height
	move.l	20(a3),gng_GadgetText(sp)	; gadget label
	move.l	#TOPAZ80,gng_TextAttr(sp)	; font for gadget label
	move.l	24(a3),gng_Flags(sp)		; gadget flags
	move.l	_VisualInfo,gng_VisualInfo(sp)	; VisualInfo
	move.l	28(a3),gng_UserData(sp)		; gadget UserData
	move.l	4(a3),d0			; gadget kind
	move.l	d3,a0				; previous
	move.l	sp,a1				; newgad
	move.l	8(a3),a2			; taglist
	CALLGADTOOLS CreateGadgetA		; create the gadget
	move.l	d0,(a3)				; store ^gadget
	move.l	d0,d3
	bne	CG_CreateGadLoop		; Gadget Creation was sucessful !
CG_CreateGadEnd
	add.w	#gng_SIZEOF,sp
CG_CreateEnd
	move.l	d3,d0				; Error -> d0=0 (!)
	movem.l	(sp)+,d2-d3/a2-a4
	rts

*-----------------------------------------------------------------------*
;
; Gadget-Remove Routine
; in: (a0:^WindowTagList/a1:^GadgetTable)

RemoveGadgets
	movem.l	a2-a3,-(sp)
	move.l	a1,a2				; ^Table with gadget definitions

	move.l	#WA_Gadgets,d0
	CALLUTIL FindTagItem
	tst.l	d0
	beq.s	RG_ClearLoop			; error !
	move.l	d0,a0
	move.l	ti_Data(a0),d0
	beq.s	RG_ClearLoop			; error !
	clr.l	ti_Data(a0)
	move.l	d0,a0
	CALLGADTOOLS FreeGadgets		; free linked list of gadgets
RG_ClearLoop
	move.l	(a2)+,d0
	beq.s	RG_RemoveEnd			; end of list !
	move.l	d0,a0
	clr.l	(a0)
	bra.s	RG_ClearLoop			; next gadget
RG_RemoveEnd
	movem.l	(sp)+,a2-a3
	rts

*-----------------------------------------------------------------------*
;
; Gadgetzustand in einem Window setzen
; a0:^GadgetArray/a1:^TagList/a2:^Window

SetGadAttrs
	movem.l	d2-d4/a2-a4,-(sp)
	move.l	a0,a4
	move.l	a1,d3
	move.l	a2,d4
	move.l	8(a4),d2
	beq.s	SGA_SetAttrs
	move.l	d2,a0				; ^TagList
	move.l	#GA_Disabled,d0
	CALLUTIL FindTagItem
	tst.l	d0				; Disable-Tag verwendet ?
	beq.s	SGA_NewAttrs			; Nein !
	move.l	d0,a0
	tst.l	ti_Data(a0)			; Gadget Disabled ?
	beq.s	SGA_NewAttrs			; Nein !
	move.l	d3,a0				; ^TagList
	move.l	#GA_Disabled,d0
	CALLUTIL FindTagItem
	tst.l	d0				; Disable-Tag verwendet ?
	beq.s	SGA_End				; Nein, dann nichts machen !
	move.l	d0,a0
	tst.l	ti_Data(a0)			; Gadget Enablen ?
	bne.s	SGA_End				; Nein, dann nichts machen !
SGA_NewAttrs
	move.l	d3,-(sp)
SGA_Apply
	move.l	sp,a0
	CALLUTIL NextTagItem
	tst.l	d0
	beq.s	SGA_ApplyEnd			; end of taglist
	move.l	d0,a3
	move.l	ti_Tag(a3),d0
	move.l	d2,a0
	CALLUTIL FindTagItem
	tst.l	d0
	beq.s	SGA_Apply			; tag not found
	move.l	d0,a0
	move.l	ti_Data(a3),ti_Data(a0)		; copy value
	bra.s	SGA_Apply
SGA_ApplyEnd
	addq.l	#4,sp
SGA_SetAttrs
	move.l	(a4),d0				; Gadget schon angelegt ?
	beq.s	SGA_End				; Nein !
	move.l	d0,a0				; ^Gadget
	move.l	d4,d0				; Window schon offen ?
	beq.s	SGA_End				; Nein !
	move.l	d0,a1				; ^Window
	suba.l	a2,a2				; reserved (should always be NULL)
	move.l	d3,a3				; ^Tags
	CALLGADTOOLS GT_SetGadgetAttrsA
SGA_End
	movem.l	(sp)+,d2-d4/a2-a4
	rts

*-----------------------------------------------------------------------*
;
; BevelBox-Creation Routine
; in: (a0:^BevelBoxTable/a1:Window)

CreateBevelBoxes
	movem.l	d2-d3/a2-a3,-(sp)
	move.l	a0,a2
	move.l	a1,a3
	move.l	_VisualInfo,BevelBoxTags+4
CBB_DrawBBLoop
	move.l	(a2)+,d0
	beq.s	CBB_DrawBBEnd			; end of list reached
	move.l	d0,a0

	moveq	#0,d0
	move.b	wd_BorderLeft(a3),d0
	add.w	0(a0),d0

	moveq	#0,d1
	move.b	wd_BorderTop(a3),d1
	add.w	2(a0),d1

	move.w	4(a0),d2
	move.w	6(a0),d3

	move.l	wd_RPort(a3),a0			; rastport to draw to
	lea	BevelBoxTags,a1
	CALLGADTOOLS DrawBevelBoxA		; draw BevelBox
	bra.s	CBB_DrawBBLoop
CBB_DrawBBEnd
	movem.l	(sp)+,d2-d3/a2-a3
	rts

*-----------------------------------------------------------------------*
;
; Lock the screen on that we open the next window

LockScreen
	movem.l	d2/a2/a5,-(sp)
	move.l	_GenieScreen,d2			; screen already locked ?
	bne.s	LS_Set
	move.l	delibase,a5			; get DeliBase
	move.l	dtg_LockScreen(a5),a0
	jsr	(a0)				; try to lock the screen
	move.l	d0,d2
	beq.s	LS_End				; couldn't lock the screen
LS_Get	move.l	d2,_GenieScreen
	move.l	d2,a0
	suba.l	a1,a1
	CALLGADTOOLS GetVisualInfoA		; get vi
	move.l	d0,_VisualInfo
	beq.s	US_Free				; couldn't get the vi datas
LS_Set	addq.w	#1,ScreenCnt
LS_End	move.l	d2,d0				; Error -> d0=0 (!)
	movem.l	(sp)+,d2/a2/a5
	rts

*-----------------------------------------------------------------------*
;
; Unlock the current screen if the last window is closed

UnlockScreen
	movem.l	d2/a2/a5,-(sp)
	move.l	_GenieScreen,d2			; screen already unlocked ?
	beq.s	US_End
	subq.w	#1,ScreenCnt
	bne.s	US_End				; there are still some open windows
	move.l	_VisualInfo,a0
	CALLGADTOOLS FreeVisualInfo		; free vi
US_Free	move.l	delibase,a5			; get DeliBase
	move.l	dtg_UnlockScreen(a5),a0
	jsr	(a0)				; now it's time to unlock the screen
	moveq	#0,d2
	move.l	d2,_GenieScreen
US_End	move.l	d2,d0				; Error -> d0=0 (!)
	movem.l	(sp)+,d2/a2/a5
	rts

*-----------------------------------------------------------------------*
;
; RangeCheck for Interger Gadgets
; a0:^GadgetArray/a1:^Window/d0:Min/d1:Max

RangeCheck
	movem.l	d2/a2,-(sp)
	move.l	a1,a2				; copy ^Window
	move.l	(a0),d2
	beq.s	RC_End				; No Gadget !
	move.l	d2,a1
	move.l	gg_SpecialInfo(a1),d2
	beq.s	RC_End				; No SpecialInfo Struct !
	move.l	d2,a1
	move.l	si_LongInt(a1),d2		; get number
RC_MinCheck
	cmp.l	d0,d2
	blt.s	RC_Fence
RC_MaxCheck
	cmp.l	d1,d2
	ble.s	RC_End
	move.l	d1,d0
RC_Fence
	lea	GadgetNumberTag,a1
	move.l	d0,ti_Data(a1)			; set new Value
	bsr	SetGadAttrs
RC_End	movem.l	(sp)+,d2/a2
	rts

;--------------------------------------------------------------------------
;
; About Gesülze

About
	move.l	_GenieWindow,a0			; window is open -> menu
	lea	AboutReqStruct,a1		; EasyStruct
	sub.l	a2,a2
	sub.l	a3,a3
	CALLINT	EasyRequestArgs
	rts

*-----------------------------------------------------------------------*
;
; Genie-Configfile laden

LoadGenieConfig
	movem.l	d2-d4/a2-a3,-(sp)
	sub.w	#4+4+4+4+4+2+2+2+2+2+2+2+2,sp
	move.l	#ConfigEnv,d1			; ENV: Variable einlesen
	move.l	#ConfigPath,d2
	moveq	#120,d3
	moveq	#0,d4
	CALLDOS GetVar
	tst.l	d0
	beq	LGC_End
	move.l	#ConfigPath,d1
	move.l	#ConfigFile,d2
	moveq	#120,d3
	CALLDOS AddPart
	tst.l	d0
	beq	LGC_End
	move.l	#ConfigPath,d1			; Config-File einlesen
	move.l	#MODE_OLDFILE,d2
	CALLDOS Open
	move.l	d0,d4
	beq	LGC_End
	move.l	d4,d1
	move.l	sp,d2
	moveq	#4+4+4+4+4+2+2+2+2+2+2+2+2,d3
	CALLDOS Read
	cmp.l	d0,d3
	bne	LGC_Err
	move.l	0(sp),d0
	cmpi.l	#$08154711+4,d0			; Config-ID correct ?
	bne	LGC_Err
	move.l	4(sp),GenieWindow+4		; window-x
	move.l	8(sp),GenieWindow+12		; window-y
	move.l	12(sp),GenieWindow+20		; window-width
	move.l	16(sp),GenieWindow+28		; window-height
	move.w	ACTFlag,d0
	andi.w	#~CHECKED,d0
	move.w	20(sp),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,ACTFlag			; activate-flag
	move.w	PUPFlag,d0
	andi.w	#~CHECKED,d0
	move.w	22(sp),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,PUPFlag			; popup-flag
	move.w	NBLFlag,d0
	andi.w	#~CHECKED,d0
	move.w	24(sp),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,NBLFlag			; nastyblit-flag
	move.w	C2PFlag,d0
	andi.w	#~CHECKED,d0
	move.w	26(sp),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,C2PFlag			; c2p-flag
	move.w	WPAFlag,d0
	andi.w	#~CHECKED,d0
	move.w	28(sp),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,WPAFlag			; wpa-flag
	move.w	WCPFlag,d0
	andi.w	#~CHECKED,d0
	move.w	30(sp),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,WCPFlag			; wcp-flag
	move.w	C16Flag,d0
	andi.w	#~CHECKED,d0
	move.w	32(sp),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,C16Flag			; 16color-flag
	move.w	C64Flag,d0
	andi.w	#~CHECKED,d0
	move.w	34(sp),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,C64Flag			; 64color-flag
LGC_Err	move.l	d4,d1
	CALLDOS Close
LGC_End	add.w	#4+4+4+4+4+2+2+2+2+2+2+2+2,sp
	movem.l	(sp)+,d2-d4/a2-a3
	rts

*-----------------------------------------------------------------------*
;
; Genie-Configfile abspeichern

SaveGenieConfig
	movem.l	d2-d4/a2-a3,-(sp)
	sub.w	#4+4+4+4+4+2+2+2+2+2+2+2+2,sp
	move.l	#$08154711+4,0(sp)		; Config-ID
	move.l	GenieWindow+4,4(sp)		; window-x
	move.l	GenieWindow+12,8(sp)		; window-y
	move.l	GenieWindow+20,12(sp)		; window-width
	move.l	GenieWindow+28,16(sp)		; window-height
	move.w	ACTFlag,d0
	andi.w	#CHECKED,d0
	move.w	d0,20(sp)			; activate-flag
	move.w	PUPFlag,d0
	andi.w	#CHECKED,d0
	move.w	d0,22(sp)			; popup-flag
	move.w	NBLFlag,d0
	andi.w	#CHECKED,d0
	move.w	d0,24(sp)			; nastyblit-flag
	move.w	C2PFlag,d0
	andi.w	#CHECKED,d0
	move.w	d0,26(sp)			; c2p-flag
	move.w	WPAFlag,d0
	andi.w	#CHECKED,d0
	move.w	d0,28(sp)			; wpa-flag
	move.w	WCPFlag,d0
	andi.w	#CHECKED,d0
	move.w	d0,30(sp)			; wcp-flag
	move.w	C16Flag,d0
	andi.w	#CHECKED,d0
	move.w	d0,32(sp)			; 16color-flag
	move.w	C64Flag,d0
	andi.w	#CHECKED,d0
	move.w	d0,34(sp)			; 64color-flag
	move.l	#ConfigPath,d1			; Config-File abspeichern
	move.l	#MODE_NEWFILE,d2
	CALLDOS Open
	move.l	d0,d4
	beq.s	SGC_End
	move.l	d4,d1
	move.l	sp,d2
	moveq	#4+4+4+4+4+2+2+2+2+2+2+2+2,d3
	CALLDOS Write
	move.l	d4,d1
	CALLDOS Close
SGC_End	add.w	#4+4+4+4+4+2+2+2+2+2+2+2+2,sp
	movem.l	(sp)+,d2-d4/a2-a3
	rts

*-----------------------------------------------------------------------*
;
; Window bei Start aktivieren oder nicht

ActivateWindow
	move.w	ACTFlag,d0
	andi.w	#~CHECKED,d0
	move.w	mi_Flags(a1),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,ACTFlag
	rts

*-----------------------------------------------------------------------*
;
; Window bei Start öffnen oder nicht

PopupWindow
	move.w	PUPFlag,d0
	andi.w	#~CHECKED,d0
	move.w	mi_Flags(a1),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,PUPFlag
	rts

*-----------------------------------------------------------------------*
;
; Nasty-Blit für Besitzer von Dumm-Grafikkarten

NastyBlitter
	move.w	NBLFlag,d0
	andi.w	#~CHECKED,d0
	move.w	mi_Flags(a1),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,NBLFlag
	rts

*-----------------------------------------------------------------------*
;
; Eigene C2P Routine benutzen

OwnC2P
	move.w	C2PFlag,d0
	andi.w	#~CHECKED,d0
	move.w	mi_Flags(a1),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,C2PFlag

	move.w	WPAFlag,d0
	andi.w	#~CHECKED,d0
	move.w	d0,WPAFlag

	move.w	WCPFlag,d0
	andi.w	#~CHECKED,d0
	move.w	d0,WCPFlag
	rts

*-----------------------------------------------------------------------*
;
; WritePixelArray8() benutzen

UseWPA
	move.w	WPAFlag,d0
	andi.w	#~CHECKED,d0
	move.w	mi_Flags(a1),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,WPAFlag

	move.w	C2PFlag,d0
	andi.w	#~CHECKED,d0
	move.w	d0,C2PFlag

	move.w	WCPFlag,d0
	andi.w	#~CHECKED,d0
	move.w	d0,WCPFlag
	rts

*-----------------------------------------------------------------------*
;
; WriteChunkyPixels() benutzen

UseWCP
	move.w	WCPFlag,d0
	andi.w	#~CHECKED,d0
	move.w	mi_Flags(a1),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,WCPFlag

	move.w	C2PFlag,d0
	andi.w	#~CHECKED,d0
	move.w	d0,C2PFlag

	move.w	WPAFlag,d0
	andi.w	#~CHECKED,d0
	move.w	d0,WPAFlag
	rts

*-----------------------------------------------------------------------*
;
; 16Color-Display Mode aktivieren oder nicht

Color16Mode
	move.w	C16Flag,d0
	andi.w	#~CHECKED,d0
	move.w	mi_Flags(a1),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,C16Flag

	move.w	C64Flag,d0
	andi.w	#~CHECKED,d0
	eori.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,C64Flag

	move.w	#16,ScopeColors
	rts

*-----------------------------------------------------------------------*
;
; 64Color-Display Mode aktivieren oder nicht

Color64Mode
	move.w	C64Flag,d0
	andi.w	#~CHECKED,d0
	move.w	mi_Flags(a1),d1
	andi.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,C64Flag

	move.w	C16Flag,d0
	andi.w	#~CHECKED,d0
	eori.w	#CHECKED,d1
	or.w	d1,d0
	move.w	d0,C16Flag

	move.w	#64,ScopeColors
	rts

*-----------------------------------------------------------------------*
;
; 16/64 Color-Display Mode aktivieren

SetColorMode
	move.w	C16Flag,d0
	andi.w	#CHECKED,d0
	beq.s	.No16
	move.w	#16,ScopeColors
.No16
	move.w	C64Flag,d0
	andi.w	#CHECKED,d0
	beq.s	.No64
	move.w	#64,ScopeColors
.No64
	rts

*-----------------------------------------------------------------------*
;
; Open your window, if you can

Appear
	move.l	_GenieWindow,-(sp)
	bsr	OpenGenieWindow
	move.l	(sp)+,d0
	rts

*-----------------------------------------------------------------------*
;
; Go dormant

Disappear
	move.l	_GenieWindow,-(sp)
	bsr	CloseGenieWindow
	move.l	(sp)+,d0
	rts

*-----------------------------------------------------------------------*
;
; Scopes initialisieren

InitPlay
	move.l	NoteInfo,d0			; get NoteStructure
	beq	EndPlay3
	move.l	d0,a4				; copy Ptr

	lea	Scope1Track,a1
	move.l	nst_Channels(a4),d0		; pointer to first channel in list
	moveq	#8,d1				; channel limit
	moveq	#0,d2				; clear channels
.CountLoop
	move.l	d0,a0				; ^NoteChannel struct
	move.w	nch_Stereo(a0),d0		; get stereo field
	cmpi.w	#NCHD_Ignore,d0
	beq.s	.CountNext			; ignore this channel !
.CountChan
	cmp.w	d1,d2				; Channels voll ?
	bcc.s	.CountNext			; ja !
	addq.w	#1,d2				; channels + 1
	move.l	a0,td_Note(a1)
	lea	td_SIZE(a1),a1
.CountNext
	move.l	nch_NextChannel(a0),d0
	bne.s	.CountLoop			; next Channel

	move.l	nst_Flags(a4),d0		; get NotePlayer flags
	btst.l	#NSTB_7Bit,d0
	bne.s	.ScaleFactor
	btst.l	#NSTB_8Bit,d0
	beq	EndPlay2
	lsl.w	#1,d2
.ScaleFactor
	moveq	#16,d0
	divu	d2,d0
	move.w	d0,ScaleFactor			; set ScaleFactor

	move.l	nst_Flags(a4),d0		; get Flags
.Signed
	btst.l	#NSTB_Signed,d0			; signed Samples ?
	beq.s	.Unsigned
	bsr	InitSVolTable
	bra.s	.InitTracks
.Unsigned
	btst.l	#NSTB_Unsigned,d0		; unsigned Samples ?
	beq.s	EndPlay2
	bsr	InitUVolTable
.InitTracks
	bsr	PixInit				; Picture löschen

	moveq	#0,d0				; no error
	rts

*-----------------------------------------------------------------------*
;
; Scopes freigeben

EndPlay
	move.l	NoteInfo,d0			; get NoteStructure
	beq.s	EndPlay3
	move.l	d0,a4				; copy Ptr
EndPlay2
	lea	Scope1Track,a1
	moveq	#8-1,d1				; max. 8 channels are supported
ClearLoop
	clr.l	td_Note(a1)			; clear Ptr
	lea	td_SIZE(a1),a1
	dbra	d1,ClearLoop			; next Channel

	clr.l	NoteInfo			; shutdown complete
EndPlay3
	moveq	#-1,d0				; set error
	rts

*-----------------------------------------------------------------------*
;
; Init Sound

InitSnd
	move.l	NoteInfo,d0			; get NoteStructure
	beq.s	.End
	move.l	d0,a4

	bsr	InitTracksNChannels

	IFNE DEBUG_VERSION
	move.l	#InitSndTxt,-(sp)
	lea	InformationFmt(pc),a0
	bsr	WriteInfoTxt
	addq.w	#4,sp
	ENDC
.End
	rts

*-----------------------------------------------------------------------*
;
; Remove Sound

EndSnd
	move.l	NoteInfo,d0			; get NoteStructure
	beq.s	.End
	move.l	d0,a4

	bsr	InitTracksNChannels

	IFNE DEBUG_VERSION
	move.l	#EndSndTxt,-(sp)
	lea	InformationFmt(pc),a0
	bsr	WriteInfoTxt
	addq.w	#4,sp
	ENDC
.End
	rts

*-----------------------------------------------------------------------*
;
; Display-VBlank starten

StartSnd
	move.l	NoteInfo,d0			; get NoteStructure
	beq.s	.End
	move.l	d0,a4				; copy Ptr

	bset.b	#1,VBlankSigFlag		; Module already playing ?
	bne.s	.End				; yes, exit !

	moveq	#0,d1
	move.b	VBlankSigBit,d0
	bset.l	d0,d1
	moveq	#0,d0
	CALLEXEC SetSignal			; clear Interrupt-Signal

	bsr	ClearScope			; clear Display

	moveq	#INTB_VERTB,d0
	lea	VBlankIRQ,a1
	CALLEXEC AddIntServer			; start Interrupt
.End
	rts

*-----------------------------------------------------------------------*
;
; Display-VBlank stoppen

StopSnd
	move.l	NoteInfo,d0			; get NoteStructure
	beq.s	.End
	move.l	d0,a4				; copy Ptr

	bclr.b	#1,VBlankSigFlag		; Module already paused ?
	beq.s	.End				; yes, exit !

	moveq	#INTB_VERTB,d0
	lea	VBlankIRQ,a1
	CALLEXEC RemIntServer			; stop Interrupt

	bsr	ClearScope			; clear Display

	moveq	#0,d1
	move.b	VBlankSigBit,d0
	bset.l	d0,d1
	moveq	#0,d0
	CALLEXEC SetSignal			; clear Interrupt-Signal
.End
	rts

*-----------------------------------------------------------------------*
;
; dem Genie mitteilen, daß das Display upgedatet werden muss

VBlankInt
	move.l	_GenieWindow,d0			; test Window
	beq.s	.End

	IFEQ RELEASE_VERSION

	addq.b	#1,VBLCount
	move.l	4.w,a6
	move.b	VBlankFrequency(a6),d0
	cmp.b	VBLCount,d0
	bgt.b	.Skip
	clr.b	VBLCount
	move.b	FrameCount,FrameSecond
	clr.b	FrameCount
.Skip
	ENDC

	bclr.b	#0,VBlankSigFlag		; ready to blit a new picture ?
	beq.s	.End				; nope, exit !

	moveq	#0,d0
	move.b	VBlankSigBit,d1
	bset.l	d1,d0
	move.l	VBlankSigTask,a1
	CALLEXEC Signal
.End
	moveq	#0,d0
	rts

*-----------------------------------------------------------------------*
;
; allocate Pens needed for Scope

AllocPens
	movem.l	d2-d6/a2-a5,-(sp)

	move.l	_GenieScreen,d0			; get ^Screen
	beq	.End
	move.l	d0,a0
	move.l	sc_ViewPort+vp_ColorMap(a0),d0
	beq	.End
	move.l	d0,a2				; get ^ColorMap
	move.w	ScopeColors,d6			; benötigte Pens
.Loop
	lea	ColorTable,a3
	lea	WordTable,a4
	move.w	d6,d4
	move.l	#64,d5
	divu	d4,d5
	lsl.w	#4,d5
	subq.w	#1,d4
.Alloc
	move.l	a2,a0				; Pen für Scope allocieren
	lea	PenTags,a1
	move.l	4(a3),d1
	move.l	8(a3),d2
	move.l	12(a3),d3
	CALLGFX ObtainBestPenA
	move.l	d0,(a3)
	bmi.s	.Fail				; keinen Pen mehr gefunden !

	move.b	d0,d1				; Pen für Tabelle vorbereiten
	lsl.w	#8,d1
	move.b	d0,d1

	move.l	#256/2,d0			; Pen in Word-Tabelle eintragen
	divu	d6,d0
	subq.w	#1,d0
.Copy
	move.w	d1,(a4)+
	dbra	d0,.Copy

	add.w	d5,a3
	dbra	d4,.Alloc

	moveq	#-1,d0				; no error
	bra.s	.End
.Fail
	lea	ColorTable,a3
	moveq	#-1,d3
	move.w	#64-1,d4			; Pens freigeben
.Free
	move.l	a2,a0				; Pen von Scope freigeben
	move.l	(a3),d0
	bmi.s	.Skip				; Pen war unbenutzt
	move.l	d3,(a3)
	CALLGFX ReleasePen
.Skip
	lea	16(a3),a3
	dbra	d4,.Free

	lsr.w	#1,d6				; Anzahl der Pens halbieren
	cmpi.w	#16,d6				; schon mit nur 16 Pens probiert ?
	bcc	.Loop				; nein, nochmal versuchen !

	move.l	_GenieWindow,a0			; window is open -> menu
	lea	NoPensReqStruct,a1		; EasyStruct
	sub.l	a2,a2
	sub.l	a3,a3
	CALLINT	EasyRequestArgs

	moveq	#0,d0				; an error occoured
.End
	movem.l	(sp)+,d2-d6/a2-a5
	rts

*-----------------------------------------------------------------------*
;
; free Pens used for Scope

FreePens
	movem.l	d2-d6/a2-a5,-(sp)

	move.l	_GenieScreen,d0			; get ^Screen
	beq	.End
	move.l	d0,a0
	move.l	sc_ViewPort+vp_ColorMap(a0),d0
	beq	.End
	move.l	d0,a2				; get ^ColorMap

	lea	ColorTable,a3
	moveq	#-1,d3
	move.w	#64-1,d4			; Pens freigeben
.Free
	move.l	a2,a0				; Pen von Scope freigeben
	move.l	(a3),d0
	bmi.s	.Skip				; Pen war unbenutzt
	move.l	d3,(a3)
	CALLGFX ReleasePen
.Skip
	lea	16(a3),a3
	dbra	d4,.Free
.End
	movem.l	(sp)+,d2-d6/a2-a5
	rts

*-----------------------------------------------------------------------*
;
; allocate Chunky Data needed for Scope

AllocChunky
	movem.l	d2/a2,-(sp)

	move.w	ScopeWidth,d0
	mulu	ScopeHeight,d0
	move.l	#MEMF_ANY!MEMF_CLEAR,d1
	CALLEXEC AllocVec
	move.l	d0,ChunkyDat
.End
	movem.l	(sp)+,d2/a2
	rts

*-----------------------------------------------------------------------*
;
; free Chunky Data used for Scope

FreeChunky
	movem.l	d2/a2,-(sp)

	move.l	ChunkyDat,d0
	beq.s	.End
	move.l	d0,a1
	CALLEXEC FreeVec
	clr.l	ChunkyDat
.End
	movem.l	(sp)+,d2/a2
	rts

*-----------------------------------------------------------------------*
;
; allocate Bitmap needed for Scope

AllocBitMap
	movem.l	d2-d3/a2-a3,-(sp)

	move.l	_GenieScreen,d0			; get ^Screen
	beq	.End
	move.l	d0,a0
	move.l	sc_RastPort+rp_BitMap(a0),d0
	beq	.End
	move.l	d0,a0				; get ^BitMap

	moveq	#0,d0
	move.w	ScopeWidth,d0
	moveq	#0,d1
	move.w	ScopeHeight,d1
	moveq	#0,d2
	move.b	bm_Depth(a0),d2
	move.l	#BMF_INTERLEAVED,d3
	suba.l	a0,a0				; don't use friend bitmap
	CALLGFX AllocBitMap
	move.l	d0,d2
	beq.s	.Fail				; error allocating bitmap
	move.l	d2,BitMapPtr

	move.l	d0,a0
	move.l	#BMA_FLAGS,d1
	CALLGFX GetBitMapAttr
	btst.l	#BMB_INTERLEAVED,d0
	bne.s	.End				; bitmap is interleaved !

	move.l	d2,a0
	CALLGFX	FreeBitMap
	clr.l	BitMapPtr
.Fail
	move.l	_GenieWindow,a0			; window is open -> menu
	lea	NoBitReqStruct,a1		; EasyStruct
	sub.l	a2,a2
	sub.l	a3,a3
	CALLINT	EasyRequestArgs

	moveq	#0,d0				; an error occoured
.End
	movem.l	(sp)+,d2-d3/a2-a3
	rts

*-----------------------------------------------------------------------*
;
; free Bitmap used for Scope

FreeBitMap
	movem.l	d2-d3/a2-a3,-(sp)

	CALLGFX WaitBlit			; for security

	move.l	BitMapPtr,d0
	beq.s	.End
	move.l	d0,a0
	CALLGFX	FreeBitMap
	clr.l	BitMapPtr
.End
	movem.l	(sp)+,d2-d3/a2-a3
	rts

*-----------------------------------------------------------------------*
;
; allocate temporary RastPort for WritePixelArray8()

AllocTempRP
	movem.l	d2-d3/a2-a3,-(sp)

	move.l	_GenieScreen,d0			; get ^Screen
	beq	.End
	move.l	d0,a0
	move.l	sc_RastPort+rp_BitMap(a0),d0
	beq	.End
	move.l	d0,a0				; get ^BitMap

	lea	TempRPort,a2			; ^RastPort

	moveq	#0,d0				; BitMap allocieren
	move.w	ScopeWidth,d0
	moveq	#1,d1				; Rows set == 1
	moveq	#0,d2
	move.b	bm_Depth(a0),d2
	moveq	#0,d3
	suba.l	a0,a0				; don't use friend bitmap
	CALLGFX AllocBitMap
	move.l	d0,rp_BitMap(a2)
.End
	movem.l	(sp)+,d2-d3/a2-a3
	rts

*-----------------------------------------------------------------------*
;
; free temporary RastPort used for WritePixelArray8()

FreeTempRP
	movem.l	d2-d3/a2-a3,-(sp)

	CALLGFX WaitBlit			; for security

	lea	TempRPort,a2			; ^RastPort

	move.l	rp_BitMap(a2),d0		; BitMap freigeben
	beq.s	.End
	move.l	d0,a0
	CALLGFX	FreeBitMap
	clr.l	rp_BitMap(a2)
.End
	movem.l	(sp)+,d2-d3/a2-a3
	rts

*-----------------------------------------------------------------------*
;
; allocate Tunnel Table needed for Scope

AllocTunnel
	movem.l	d2/a2,-(sp)

	move.w	ScopeWidth,d0
	mulu	ScopeHeight,d0
	move.l	#MEMF_ANY!MEMF_CLEAR,d1
	CALLEXEC AllocVec
	move.l	d0,TunnelTab
.End
	movem.l	(sp)+,d2/a2
	rts

*-----------------------------------------------------------------------*
;
; free Tunnel Table used for Scope

FreeTunnel
	movem.l	d2/a2,-(sp)

	move.l	TunnelTab,d0
	beq.s	.End
	move.l	d0,a1
	CALLEXEC FreeVec
	clr.l	TunnelTab
.End
	movem.l	(sp)+,d2/a2
	rts

*-----------------------------------------------------------------------*
;
; Volume-Tabelle (signed) erzeugen

InitSVolTable
	lea	VTable,a0			; Volume-Tabelle erzeugen

	moveq	#65-1,d2
	moveq	#0,d4
	move.w	ScaleFactor,d5
.Loop1	moveq	#0,d0
	move.w	#256-1,d1
.Loop2	move.w	d0,d3
	ext.w	d3
	muls	d4,d3				; Tabellennummer (0...64) * Samplewert
	asr.w	#1,d3
	move.w	d3,(a0)+
	addq.w	#1,d0
	dbra	d1,.Loop2
	add.w	d5,d4				; > 1 = Oversampling
	dbra	d2,.Loop1
	rts

*-----------------------------------------------------------------------*
;
; Volume-Tabelle (unsigned) erzeugen

InitUVolTable
	lea	VTable,a0			; Volume-Tabelle erzeugen

	moveq	#65-1,d2
	moveq	#0,d4
	move.w	ScaleFactor,d5
.Loop1	moveq	#-128,d0
	move.w	#256-1,d1
.Loop2	move.w	d0,d3
	muls	d4,d3				; Tabellennummer (0...64) * Samplewert
	asr.w	#1,d3
	move.w	d3,(a0)+
	addq.w	#1,d0
	dbra	d1,.Loop2
	add.w	d5,d4				; > 1 = Oversampling
	dbra	d2,.Loop1
	rts

*-----------------------------------------------------------------------*
;
; Alle Track-Data-Structuren initialisieren

InitTracksNChannels
	lea	Scope1Track,a0
	lea	QuietInstr,a1
	moveq	#8-1,d0
	move.w	#NCHD_FarLeft,d1
.Loop	move.l	(a1),td_SPtr(a0)		; Zum Abspielen vorbereiten
	move.l	4(a1),td_SLen(a0)
	move.l	8(a1),td_LPtr(a0)
	move.l	12(a1),td_LLen(a0)
	move.w	#64,td_Vol(a0)			; Volle Lautstärke
	move.l	#8287,td_Fre(a0)		; C 0
	clr.w	td_FreC(a0)
	neg.w	d1
	lea	td_SIZE(a0),a0
	dbra	d0,.Loop
	rts

*-----------------------------------------------------------------------*
;
; Daten für Scope Display updaten

NoteSignal
	movem.l	d2-d3/a2-a6,-(sp)

	move.l	NoteInfo,d0			; get NoteStructure
	beq	.End
	move.l	d0,a4

	lea	EClockValue,a0			; read EClock Value
	CALLTIMER TimeRequest,ReadEClock
	move.l	d0,d2				; EClockFreq (ticks/sec)

	lea	EClockValue,a0			; calc Interrupt Time
	lea	EClockValue2,a1
	move.l	EV_LO(a0),d0
	sub.l	EV_LO(a1),d0
	beq.s	.CopyEClock
	divu	d0,d2				; calc Clock Divisor
.CopyEClock
	move.l	(a0)+,(a1)+			; copy EClock Value
	move.l	(a0)+,(a1)+

	lea	Scope1Track,a3
	moveq	#8-1,d3				; max. 8 channels are supported
.Loop
	move.l	td_Note(a3),d0
	beq	.End
	move.l	d0,a2				; ^NoteChannel struct

	cmpi.w	#NCHD_Ignore,nch_Stereo(a2)	; skip this channel ?
	beq	.Next				; yes !
.Channel
	move.l	td_Fre(a3),d0			; Samples/Interrupt berechnen
	divu	d2,d0
	moveq	#0,d1
	move.w	d0,d1
	add.l	td_SLen(a3),d1
	bmi.s	.Length				; Noch nicht am Ende des Samples angekommen!
	move.l	td_LLen(a3),d1			; ist ein Loop-Sample vorhanden ?
	bpl.s	.Length				; Kein Loopsample da, also raus!
	move.l	td_LPtr(a3),td_SPtr(a3)		; Endadresse des Samples sichern
.Length
	move.l	d1,td_SLen(a3)			; Restbytes des Samples sichern
.Sample
	btst.b	#NCHB_Sample,nch_Changed(a2)
	beq.s	.Repeat				; no new sample !

	move.l	nch_SampleStart(a2),a0
	move.l	nch_SampleLength(a2),d0
	add.l	d0,a0
	move.l	a0,td_SPtr(a3)			; Pointer auf das Sampleende
	neg.l	d0
	move.l	d0,td_SLen(a3)			; negative Sample-Restbytes

	clr.l	td_LLen(a3)			; Kein LoopSample vorhanden

	clr.w	td_FreC(a3)			; -> Kein Überlauf bei erstem Samplebyte!
.Repeat
	btst.b	#NCHB_Repeat,nch_Changed(a2)
	beq.s	.Frequency			; no new repeat !

	move.l	nch_RepeatStart(a2),a0
	move.l	nch_RepeatLength(a2),d0
	moveq	#2,d1
	cmp.l	d0,d1				; Repeat-Length only 1 Word ?
	bne.s	.RepSamp			; No !
	move.l	a0,a1
	move.b	(a1)+,d1
	cmp.b	(a1)+,d1			; Is it a NullSample ?
	bne.s	.RepSamp			; No !
	moveq	#0,d0
.RepSamp
	add.l	d0,a0
	move.l	a0,td_LPtr(a3)			; LoopSample-Endadr.
	neg.l	d0
	move.l	d0,td_LLen(a3)			; negative LoopSample-Länge
.Frequency
	btst.b	#NCHB_Frequency,nch_Changed(a2)
	beq.s	.Volume				; no new freq !

	move.l	nch_Frequency(a2),td_Fre(a3)	; Frequency for this channel
.Volume
	btst.b	#NCHB_Volume,nch_Changed(a2)
	beq.s	.Next				; no new vol !

	moveq	#0,d0
	move.w	nch_Volume(a2),d0
	lsl.l	#6,d0
	divu	nst_MaxVolume(a4),d0
	move.w	d0,td_Vol(a3)			; Volume for this channel
.Next
	lea	td_SIZE(a3),a3
	dbra	d3,.Loop			; next channel
.End
	movem.l	(sp)+,d2-d3/a2-a6
	rts

*-----------------------------------------------------------------------*
;
; Scope Display berechnen

DisplayScope
	tst.l	NoteInfo		; test NoteStructure
	beq	.End

	tst.l	_GenieWindow		; test Window
	beq	.End

	tst.l	BitMapPtr		; test BitMap
	beq	.End

	tst.l	ChunkyDat		; test ChunkyData
	beq	.End

	tst.l	TunnelTab		; test TunnelTable
	beq	.End

	lea	SampleBuffer,a0		; MixBuffer löschen
	move.w	#BlankSampSize/2-1,d0
	moveq	#0,d1
.Clear	move.l	d1,(a0)+
	dbra	d0,.Clear

	lea	Scope1Track,a2
	bsr	ScoUpdate		; Scope berechnen

	lea	Scope2Track,a2
	bsr	ScoUpdate		; Scope berechnen

	lea	Scope3Track,a2
	bsr	ScoUpdate		; Scope berechnen

	lea	Scope4Track,a2
	bsr	ScoUpdate		; Scope berechnen

	lea	Scope5Track,a2
	bsr	ScoUpdate		; Scope berechnen

	lea	Scope6Track,a2
	bsr	ScoUpdate		; Scope berechnen

	lea	Scope7Track,a2
	bsr	ScoUpdate		; Scope berechnen

	lea	Scope8Track,a2
	bsr	ScoUpdate		; Scope berechnen

	bsr	MakeLine
	bsr	MakeLine

	bsr	PixJob			; Picture pinseln

	IFEQ RELEASE_VERSION

	move.l	ChunkyDat,a0
	move.w	ScopeWidth,d0
	move.b	FrameSecond,d1
	bsr	PrintNumber
	addq.b	#1,FrameCount

	ENDC
.DoWPA
	move.w	WPAFlag,d0		; use WritePixelArray8() ?
	andi.w	#CHECKED,d0
	beq	.DoWCP			; no !

	move.l	_GenieWindow,a0
	lea	GenieBBArray1,a1
	moveq	#0,d0
	move.b	wd_BorderLeft(a0),d0
	add.w	0(a1),d0
	addq.l	#2,d0
	moveq	#0,d1
	move.b	wd_BorderTop(a0),d1
	add.w	2(a1),d1
	addq.l	#1,d1
	move.l	d0,d2
	add.w	4(a1),d2
	subq.l	#4+1,d2
	move.l	d1,d3
	add.w	6(a1),d3
	subq.l	#2+1,d3
	move.l	wd_RPort(a0),a0
	lea	TempRPort,a1
	move.l	ChunkyDat,a2
	move.w	NBLFlag,d7		; nasty Blit ?
	andi.w	#CHECKED,d7
	beq.s	.SkipF1
	CALLEXEC Forbid
.SkipF1
	CALLGFX WritePixelArray8	; Scope BitMap anzeigen
	tst.w	d7
	beq.s	.SkipP1
	CALLEXEC Permit
.SkipP1
	bra	.End
.DoWCP
	move.w	WCPFlag,d0		; use WriteChunkyPixels() ?
	andi.w	#CHECKED,d0
	beq	.DoC2P			; no !

	move.l	_GenieWindow,a0
	lea	GenieBBArray1,a1
	moveq	#0,d0
	move.b	wd_BorderLeft(a0),d0
	add.w	0(a1),d0
	addq.l	#2,d0
	moveq	#0,d1
	move.b	wd_BorderTop(a0),d1
	add.w	2(a1),d1
	addq.l	#1,d1
	move.l	d0,d2
	add.w	4(a1),d2
	subq.l	#4+1,d2
	move.l	d1,d3
	add.w	6(a1),d3
	subq.l	#2+1,d3
	moveq	#0,d4
	move.w	ScopeWidth,d4
	move.l	wd_RPort(a0),a0
	move.l	ChunkyDat,a2
	move.w	NBLFlag,d7		; nasty Blit ?
	andi.w	#CHECKED,d7
	beq.s	.SkipF2
	CALLEXEC Forbid
.SkipF2
	CALLGFX WriteChunkyPixels	; Scope BitMap anzeigen
	tst.w	d7
	beq.s	.SkipP2
	CALLEXEC Permit
.SkipP2
	bra	.End
.DoC2P
	CALLGFX WaitBlit		; hmm, mit double-buffering wäre das überflüssig...

	move.l	ChunkyDat,a0
	move.l	BitMapPtr,a1
	bsr	FastC2P

	move.l	BitMapPtr,a0
	move.l	_GenieWindow,a2
	move.l	wd_RPort(a2),a1
	lea	GenieBBArray1,a3
	moveq	#0,d0
	moveq	#0,d1
	moveq	#0,d2
	move.b	wd_BorderLeft(a2),d2
	add.w	0(a3),d2
	addq.w	#2,d2
	moveq	#0,d3
	move.b	wd_BorderTop(a2),d3
	add.w	2(a3),d3
	addq.w	#1,d3
	move.w	4(a3),d4
	subq.w	#4,d4
	move.w	6(a3),d5
	subq.w	#2,d5
	move.w	#$00C0,d6
	move.w	NBLFlag,d7		; nasty Blit ?
	andi.w	#CHECKED,d7
	beq.s	.SkipF3
	CALLEXEC Forbid
.SkipF3
	CALLGFX BltBitMapRastPort	; Scope BitMap anzeigen
	tst.w	d7
	beq.s	.SkipP3
	CALLEXEC Permit
.SkipP3

.End
	rts

*-----------------------------------------------------------------------*
;
; INPUT:	a0 = ChunkyData/d0 = BytesPerRow/d1.b = Value

	IFEQ RELEASE_VERSION

PrintNumber
	moveq	#0,d2
	move.b	d1,d2
	divu	#10,d2
	lea	.Chars(pc,d2.w),a1
	swap	d2
	lea	.Chars(pc,d2.w),a2
	moveq	#6-1,d1
.loop1	move.b	(a1),d2
	lsl.b	#4,d2
	add.b	(a2),d2
	adda.w	#10,a1
	adda.w	#10,a2
	moveq	#8-1,d3
.loop2	add.b	d2,d2
	subx.b	d4,d4
	move.b	d4,(a0)+
	dbra	d3,.loop2
	lea	-8(a0,d0.w),a0
	dbra	d1,.loop1
	rts

.Chars	dc.b	%00001110,%00000100,%00001110,%00001110,%00001000,%00001110,%00001000,%00001110,%00001110,%00001110
	dc.b	%00001010,%00000100,%00000010,%00000010,%00001000,%00001000,%00001000,%00000010,%00001010,%00001010
	dc.b	%00001010,%00000100,%00001110,%00001110,%00001110,%00001110,%00001110,%00000010,%00001110,%00001110
	dc.b	%00001010,%00000100,%00001000,%00000010,%00000010,%00000010,%00001010,%00000010,%00001010,%00000010
	dc.b	%00001110,%00000100,%00001110,%00001110,%00000010,%00001110,%00001110,%00000010,%00001110,%00000010
	dc.b	%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000,%00000000

VBLCount	dc.b 0
FrameSecond	dc.b 0
FrameCount	dc.b 0
	even

	ENDC

*-----------------------------------------------------------------------*
;
; Scope Display berechnen

ScoUpdate
	lea	SampleBuffer,a5		; Buffer für beide Kanäle

* Daten des Samples holen:

ScoInit	move.l	td_SPtr(a2),a3		; Pointer auf das Sampleende
	move.l	td_SLen(a2),d3		; negative Restbytes des Samples
	bmi.s	ScoCalc			; noch nicht am Sampleende angekommen!
	move.l	td_LLen(a2),d3		; ist ein Loop-Sample vorhanden ?
	bpl	ScoEnd			; Kein Loopsample da, also raus!
	move.l	td_LPtr(a2),a3		; Pointer auf das Loopende
ScoCalc	moveq	#0,d2
	move.w	td_Vol(a2),d2		; Volume des Samples
	add.w	d2,d2
	lsl.w	#8,d2
	lea	VTable,a4		; ^Volume-Table
	adda.l	d2,a4
	move.l	td_Fre(a2),d5		; individuelle Sample-Frequency
	divu	MixFreq,d5		; globale Mix-Frequency
	moveq	#0,d4
	move.w	d5,d4			; Period-Vorkommastellen
	clr.w	d5
	divu	MixFreq,d5		; Period-Nachkommastellen
	move.w	td_FreC(a2),d6		; Period-Nachkomma-Zähler

*
* Hauptschleife - Registerbelegung:
* D0.W = Temp.Register für die Samplewords
* D1   =
* D2.W = Zähler für die MixLoop
* D3.L = Restbytes vom Sample
* D4.L = Vorkomma Faktor
* D5.W = Nachkomma Faktor
* D6.W = Nachkomma Zähler
* D7   =
* A0   = Temp.Zeiger
* A1   =
* A2   = Zeiger auf TrackData des Tracks
* A3   = Zeiger auf das Ende des Samples
* A4   = Zeiger auf Volume-Tabelle des Samples
* A5   = Zeiger auf den Mix-Buffer
* A6   =
*

ScoMix	move.w	#BlankSampSize/2-1,d2	; Zähler für die MixLoop

ScoLop1	moveq	#0,d0
	move.b	0(a3,d3.l),d0		; ein Sample zum Buffer dazumixen
	add.w	d0,d0
	move.w	0(a4,d0.w),d1
	add.w	d1,(a5)+
	add.w	d5,d6			; Sample fortschalten
	addx.l	d4,d3
	bmi.s	ScoLop2			; noch nicht am Sampleende angekommen!
	move.l	td_LLen(a2),d3		; ist ein Loop-Sample vorhanden ?
	bpl.s	ScoPerC			; Kein Loopsample da, also raus!
	move.l	td_LPtr(a2),a3		; Pointer auf das Loopende
ScoLop2	moveq	#0,d0
	move.b	0(a3,d3.l),d0		; ein Sample zum Buffer dazumixen
	add.w	d0,d0
	move.w	0(a4,d0.w),d1
	add.w	d1,(a5)+
	add.w	d5,d6			; Sample fortschalten
	addx.l	d4,d3
	bmi.s	ScoLop3			; noch nicht am Sampleende angekommen!
	move.l	td_LLen(a2),d3		; ist ein Loop-Sample vorhanden ?
	bpl.s	ScoPerC			; Kein Loopsample da, also raus!
	move.l	td_LPtr(a2),a3		; Pointer auf das Loopende
ScoLop3	dbra	d2,ScoLop1		; bis MixBuffer voll

ScoPerC	move.w	d6,td_FreC(a2)		; Neuer Stand des Runtersample-Zählers

ScoEnd	rts

*-----------------------------------------------------------------------*
;
; Scope Display löschen

ClearScope
	move.l	NoteInfo,d0			; get NoteStructure
	beq	.End
	move.l	d0,a4

	move.l	_GenieWindow,d0			; ^Window
	beq	.End
	move.l	d0,a2

	lea	GenieBBArray1,a0
	move.l	wd_RPort(a2),a1
	moveq	#0,d0
	move.b	wd_BorderLeft(a2),d0
	add.w	0(a0),d0
	addq.w	#2,d0
	moveq	#0,d1
	move.b	wd_BorderTop(a2),d1
	add.w	2(a0),d1
	addq.w	#1,d1
	move.w	d0,d2
	add.w	4(a0),d2
	subq.w	#4+1,d2
	move.w	d1,d3
	add.w	6(a0),d3
	subq.w	#2+1,d3
	CALLGFX EraseRect			; BitMap löschen
.End
	rts

*-----------------------------------------------------------------------*
;
; Sinus Tabelle erzeugen

QuarterSize	= 2048				; Need to be a multiple of 4

GenSinus
	lea	Sine,a2
	lea	QuarterSize*4(a2),a3
	move.l	#HalfPi/QuarterSize,d2
	moveq	#0,d3
	move.w	#QuarterSize-1,d4
	moveq	#-29+fractionBits+14,d5
.Loop1	move.l	d3,d0
	bsr	Sinus
	lsr.l	d5,d0
	move.w	d0,(a2)+
	move.w	d0,(a3)+
	add.l	d2,d3
	dbra	d4,.Loop1

	movea.l	a2,a1
	move.w	#QuarterSize-1,d2
.Loop2	move.w	-(a1),(a2)+
	dbra	d2,.Loop2

	movea.l	a2,a1
	move.w	#QuarterSize*2-1,d2
.Loop3	move.w	-(a1),d0
	neg.w	d0
	move.w	d0,(a2)+
	dbra	d2,.Loop3
	rts

*-----------------------------------------------------------------------*
;
; INPUT:	d0.l = Angle in radian
;
; OUTPUT:	d0.l = sin(A) 29bit precision
;
; NOTE:		This the CORDIC algorithms with the setting for sin hardcoded.
;		I havent analized the routine for optimal branching setting.

fractionBits	= 16
HalfPi		= 843314856

Sinus	movem.l	d2-d6,-(sp)
	move.l	#$136e9db3>>(29-fractionBits),d4	;X
	move.l	d0,d1			;Z
	moveq	#0,d0			;Y
	moveq	#0,d3			;i
	lea	.atan(pc),a0
	moveq	#fractionBits-1,d2
.Loop0	move.l	d4,d5
	move.l	d0,d6			;
	asr.l	d3,d5			;x = X>>i
	asr.l	d3,d6			;y = Y>>i
	addq.l	#1,d3			;i++
	sub.l	d6,d4			;X-=y
	add.l	d5,d0			;Y+=x
	sub.l	(a0)+,d1		;Z-=atan[i]
	blt.b	1$
0$	dbra	d2,.Loop0
	movem.l	(sp)+,d2-d6
	rts
.Loop1	move.l	d4,d5
	move.l	d0,d6
	asr.l	d3,d5			;x = X>>i
	asr.l	d3,d6			;y = Y>>i
	addq.l	#1,d3			;i++
	add.l	d6,d4			;X+=y
	sub.l	d5,d0			;Y-=x
	add.l	(a0)+,d1		;Z+=atan[i]
	bge.b	0$
1$	dbra	d2,.Loop1
	movem.l	(sp)+,d2-d6
	rts

.atan	dc.l	$1921fb54,$0ed63382,$07d6dd7e,$03fab753,$01ff55bb,$00ffeaad,$007ffd55,$003fffaa
	dc.l	$001ffff5,$000ffffe,$0007ffff,$00040000,$00020000,$00010000,$00008000,$00004000
	dc.l	$00002000,$00001000,$00000800,$00000400,$00000200,$00000100,$00000080,$00000040
	dc.l	$00000020,$00000010,$00000008,$00000004,$00000002,$00000001

*-----------------------------------------------------------------------*
;
; ArcusSinus Tabelle erzeugen (benötigt leider die mathffp/mathtrans libs...)

ASinSize	= 4096				; Need to be a multiple of 2

GenArcSinus
	lea	ArcSinus+(ASinSize+1)*2,a2	; Ende der ArcusSinus Tabelle

	moveq	#1,d0
	CALLFFP SPFlt
	move.l	d0,d3				; 1
	CALLMTRANS SPAsin
	move.l	d0,d1
	CALLFFP SPAdd
	move.l	d0,d4				; Pi

	moveq	#0,d0
	move.w	PixWidth,d0
	add.w	d0,d0				; always even
	CALLFFP SPFlt
	move.l	d0,d5

	moveq	#1,d0
	CALLFFP SPFlt
	move.l	d0,d2
	moveq	#2,d0
	CALLFFP SPFlt
	move.l	d0,d1
	move.l	d2,d0
	CALLFFP SPDiv
	move.l	d0,d6				; 0.5

	move.l	#ASinSize,d0
	CALLFFP SPFlt
	move.l	d0,d7

	move.l	#ASinSize,d2
.Loop
	move.l	d2,d0
	CALLFFP SPFlt
	move.l	d7,d1
	CALLFFP SPDiv

	CALLMTRANS SPAsin

	move.l	d4,d1
	CALLFFP SPDiv

	move.l	d5,d1
	CALLFFP SPMul

	move.l	d6,d1
	CALLFFP SPAdd

	CALLFFP SPFix

	move.w	d0,-(a2)

	subq.l	#1,d2
	bpl.s	.Loop				; next value
	rts

*-----------------------------------------------------------------------*
;
; Quadratwurzel berechnen

Sqrt	movem.l	d2-d3,-(sp)
	moveq	#$00,d1
	move.l	#$40000000,d2			; erster Schätzwert
.loop	move.l	d2,d3
	add.l	d1,d3
	lsr.l	#1,d1
	cmp.l	d0,d3
	bhi.s	.skip
	sub.l	d3,d0
	add.l	d2,d1
.skip	lsr.l	#2,d2
	bne.s	.loop
	cmp.l	d0,d1
	bcc.s	.done
	addq.l	#1,d1
.done	move.l	d1,d0
	movem.l	(sp)+,d2-d3
	rts

*-----------------------------------------------------------------------*
;
; Sinen vorbereiten

SineInit
	lea	Sine,a0
	lea	Sine2,a1
	lea	Sine2+$4000,a2
	lea	Sine2+$8000,a3
	lea	Sine2+$c000,a4
	move.w	#$2000-1,d0
.loop	move.w	(a0)+,d1
	rol.w	#7,d1
	add.w	#$40,d1
	and.w	#$7c,d1
	move.b	d1,(a1)+
	move.b	d1,(a1)+
	move.b	d1,(a2)+
	move.b	d1,(a2)+
	move.b	d1,(a3)+
	move.b	d1,(a3)+
	move.b	d1,(a4)+
	move.b	d1,(a4)+
	dbf	d0,.loop
	rts

*-----------------------------------------------------------------------*
;
; Bild initialisieren

PixInit	lea	PixData1,a0			; Data mit Pen0 füllen
	move.w	#$20000/4-1,d0
	lea	WordTable,a1
	move.w	128(a1),d1
	swap	d1
	move.w	128(a1),d1
.clr	move.l	d1,(a0)+
	dbf	d0,.clr

	lea	WaveSine,a0			; Sinen löschen
	moveq	#0,d0
	move.w	d0,(a0)+
	move.w	d0,(a0)+
	move.w	d0,(a0)+
	move.w	d0,(a0)+
	move.w	d0,(a0)+
	move.w	d0,(a0)+
	move.w	d0,(a0)+
	move.w	d0,(a0)+

	move.w	#$0,WaveAngl
	move.w	#$200,WaveSize
	move.w	#$0,WavePosX
	move.w	#$0,WavePosY

	move.w	#$0,LinePtr

	move.w	#$0,SineAPtr
	move.w	#$0,SineBPtr
	move.w	#$0,SineCPtr

	rts

*-----------------------------------------------------------------------*
;
; Tunnel Tabelle berechnen
;
; Mit folgendem BASIC:-) Programm kamm man die Table auch berechnen
; (der Absolut->Relativ Schritt ist nicht mehr nötig, man kann die
;  Tabelle direkt benutzen)
;
;' OPEN "TMP:Basic/drwho128.new" FOR OUTPUT AS #1
;
;pi=3.141593		' sollte klar sein...
;
;xm=64			' Scope-Breite/2
;ym=64			' Scope-Höhe/2
;xy=SQR(xm*xm+ym*ym)	' max. Radius
;pw=128			' Picture Breite (fixed)
;ph=256			' Picture Höhe (fixed)
;
;zz=0
;
;FOR y=ym TO 1 STEP -1
;FOR x=-xm TO xm STEP 1
;
;IF x=0 THEN x=1	' urks, kein besonders guter Programmier-Stil:-)
;
;REM - Abstand von der Tunnelmitte
;q=SQR(x*x+y*y)
;
;REM - 'Tiefe' des Punktes berechnen (mit den Quadraten
;REM - kommt etwas Perspektive in das Bild)
;z=pw*INT(ph*((xy-q)*(xy-q)*(xy-q))/(xy*xy*xy)+.5)
;
;' PRINT x,y,z
;
;REM - Abstand des Punktes vom linken Picture-Rand berechnen
;REM - (mittels der Formel für rechtwinklige Dreiecke: sin alpha = a/c)
;REM - leider brauche ich dafür den ArcusSinus:(((
;w=ATN((x/q)/SQR(1-(x/q)*(x/q)))
;z=z+INT(pw*(w+pi/2)/pi+.5)
;
;' PRINT x,y,w,z
;' PSET(300+x*2,200-y*2),3*z/fl
;
;REM - Differenz mit 2 multiplizieren, da die Tabelle immer gerade
;REM - sein muß
;' PRINT#1,MKL$(2*INT(z-zz+.5));
;
;REM - für Relativ-Berechnung den Wert merken
;zz=z
;
;NEXT
;NEXT
;
;' CLOSE#1

TunnelInit
	move.w	ScopeWidth,d0
	lsr.w	#1,d0
	mulu	d0,d0
	move.w	ScopeHeight,d1
	lsr.w	#1,d1
	mulu	d1,d1
	add.l	d1,d0
	lsl.l	#8,d0
	bsr	Sqrt
	move.w	d0,d4				; max. Radius

	move.l	TunnelTab,a2
	move.w	ScopeWidth,d0
	lsl.w	#1,d0
	lea	0(a2,d0.w),a3

	lea	ArcSinus,a4			; ArcusSinus Tabelle

	move.w	ScopeHeight,d3
	lsr.w	#1,d3

.loop1	move.w	ScopeWidth,d2
	lsr.w	#1,d2

.loop2	move.w	d2,d0
	mulu	d0,d0
	move.w	d3,d1
	mulu	d1,d1
	add.l	d1,d0
	lsl.l	#8,d0
	bsr	Sqrt
	move.w	d0,d5				; q

	move.w	d4,d0
	sub.w	d5,d0				; xy-q

	moveq	#0,d6
	move.w	d0,d6
	swap	d6
	divu	d4,d6

	move.w	d6,d0				; ^3
	mulu	d0,d6
	swap	d6
	mulu	d0,d6
	swap	d6				; shit, da fallen verdammt viele Bits raus:(

	move.w	PixHeight,d0
	mulu	d0,d6
	swap	d6

	move.w	PixWidth,d0
	move.w	d0,d1
	add.w	d1,d1
	mulu	d1,d6
	add.w	d0,d6				; z

	moveq	#0,d0
	move.w	d2,d0
	swap	d0
	divu	d5,d0

	add.w	d0,d0
	move.w	0(a4,d0.w),d1			; w

	move.w	d6,d0
	sub.w	d1,d0

	move.w	d0,(a2)+			; WORDs sollten gerade noch reichen...

	move.w	d6,d0
	add.w	d1,d0

	move.w	d0,-(a3)			; Symmetrie ausnutzen

	subq.w	#1,d2
	bne	.loop2

	move.w	ScopeWidth,d0
	lea	0(a2,d0.w),a2
	lsl.w	#1,d0
	lea	0(a2,d0.w),a3

	subq.w	#1,d3
	bne	.loop1


	move.l	TunnelTab,a0
	move.w	ScopeHeight,d0
	lsr.w	#1,d0				; der shift hat bei dir gefehlt (bug?)
	subq.w	#1,d0
	moveq	#~1,d3
	moveq	#0,d4
	moveq	#0,d5

.loop3	move.w	ScopeWidth,d1
	lsr.w	#1,d1
	subq.w	#1,d1

.loop4	move.w	(a0),d6
	and.w	d3,d6				; always even
	move.w	d6,d5
	sub.w	d4,d6
	move.w	d6,(a0)+

	move.w	(a0),d6
	and.w	d3,d6
	move.w	d6,d4
	sub.w	d5,d6
	move.w	d6,(a0)+

	dbf	d1,.loop4

	dbf	d0,.loop3

	rts

*-----------------------------------------------------------------------*
;
; Erstelle Linie

MakeLine
	lea	SampleBuffer,a1
	moveq	#0,d1
	move.w	(a1)+,d2
	moveq	#0,d3
	move.w	#BlankSampSize/2-1-1,d0
.make	move.w	(a1)+,d3
	move.w	d3,d4
	sub.w	d2,d3
	bcc.s	.skip1
	neg.w	d3
.skip1	add.l	d3,d1
	move.w	(a1)+,d3
	move.w	d3,d2
	sub.w	d4,d3
	bcc.s	.skip2
	neg.w	d3
.skip2	add.l	d3,d1
	dbra	d0,.make

	lea	Sine,a3
	move.w	#$3ffe,d7

	divu	#BlankSampSize-1,d1
	lsr.w	#6,d1
	move.w	SineCPtr,d0
	add.w	d0,d1
	move.w	d1,SineCPtr

	and.w	d7,d1
	move.w	0(a3,d1.w),d2
	lsr.w	#7,d2
	move.w	d2,SineAPtr

	and.w	d7,d1
	move.w	0(a3,d1.w),d3
	add.w	#$8000,d3
	asr.w	#8,d3
	asr.w	#3,d3
	add.w	d2,d3
	move.w	d3,SineBPtr

	IFNE DEBUG_VERSION
	move.w	SineCPtr,-(sp)
	lea	MakeLineFmt(pc),a0
	bsr	WriteInfoTxt
	addq.w	#2,sp
	ENDC

	moveq	#0,d0				; Hole Pointer
	move.w	LinePtr,d0
	add.w	#$100,LinePtr
	lea	PixData1,a0
	adda.l	d0,a0
	move.l	a0,a1
	adda.l	#$10000,a1
	lea	WordTable,a2			; Word Table
	lea	Sine2+$8000,a3

	moveq	#0,d1
	move.w	LinePtr,d1
	lsr.w	#2,d1
	move.w	SineAPtr,d2
	move.w	d2,d5
	lsl.w	#6,d5
	sub.w	d5,d1
	moveq	#0,d3
	move.w	SineBPtr,d4
	move.w	d4,d5
	lsl.w	#6,d5
	sub.w	d5,d3

	moveq	#0,d5
	moveq	#128-1,d0			; Counter
.loop	add.w	d2,d1
	add.w	d4,d3
	move.b	0(a3,d1.w),d5
	add.b	0(a3,d3.w),d5
;	move.w	LinePtr,d5
;	lsr.w	#8,d5
;	lsr.w	#1,d5
;	lsl.w	#1,d5
	move.w	0(a2,d5),d6
	move.w	d6,(a0)+
	move.w	d6,(a1)+
	dbf	d0,.loop
	rts

*-----------------------------------------------------------------------*
;
; Picture auf Tunnel mappen

PixJob
	lea	WaveSine,a0			; Sinen weiterschalten
	add.w	#$50/4/2,(a0)+
	add.w	#$20/4/2,(a0)+
	add.w	#$120/2/2,(a0)+
	add.w	#$148/2/2,(a0)+
	add.w	#$18/2/2,(a0)+
	add.w	#$26/2/2,(a0)+
	add.w	#$15/2/2,(a0)+
	add.w	#$10/2/2,(a0)+

	lea	Sine,a0				; Do Sines
	lea	WaveSine,a1
	move.w	#$3ffe,d2

	move.w	(a1)+,d0			; Angle
	and.w	d2,d0
	move.w	0(a0,d0.w),d0
	muls	#$500/8,d0
	swap	d0
	move.w	(a1)+,d1
	and.w	d2,d1
	move.w	0(a0,d1.w),d1
	muls	#$200/4,d1
	swap	d1
	add.w	d1,d0
	add.w	#$10,d0
	add.w	d0,WaveAngl

	move.w	(a1)+,d0			; Size
	and.w	d2,d0
	move.w	0(a0,d0.w),d0
	muls.w	#$1800,d0
	swap	d0
	move.w	(a1)+,d1
	and.w	d2,d1
	move.w	0(a0,d1.w),d1
	muls.w	#$6000,d1
	swap	d1
	move.w	d1,d0
	add.w	#$7800/2+$200,d0
	move.w	d0,WaveSize

	move.w	(a1)+,d0			; XPos
	and.w	d2,d0
	move.w	0(a0,d0.w),d0
	muls.w	#$100,d0
	swap	d0
	move.w	(a1)+,d1
	and.w	d2,d1
	move.w	0(a0,d1.w),d1
	muls.w	#$400,d1
	swap	d1
	add.w	d1,d0
	add.w	d0,WavePosX

	move.w	#$200,d0			; YPos
	add.w	d0,WavePosY

	moveq	#0,d1
	move.w	WavePosX,d5
	lsl.l	#8,d5
	swap	d5
	move.w	WavePosY,d1
	move.b	d5,d1
	add.b	d1,d1

	move.l	TunnelTab,a0			; Startadresses
	lea	PixData1,a1
	adda.l	d1,a1
	move.l	ChunkyDat,a2
	move.w	ScopeWidth,d0
	mulu	ScopeHeight,d0
	lea	0(a2,d0.l),a3

	move.w	ScopeHeight,d2			; Now for the real one.....
	lsr.w	#1,d2
	subq.w	#1,d2

.loop1	move.w	ScopeWidth,d3
	lsr.w	#4,d3
	subq.w	#1,d3

.loop2	add.w	(a0)+,a1
	move.w	(a1),d0
	add.w	(a0)+,a1
	move.b	(a1),d0
	swap	d0
	add.w	(a0)+,a1
	move.w	(a1),d0
	add.w	(a0)+,a1
	move.b	(a1),d0

	move.l	d0,(a2)+
	rol.w	#8,d0
	swap	d0
	rol.w	#8,d0
	move.l	d0,-(a3)

	add.w	(a0)+,a1
	move.w	(a1),d0
	add.w	(a0)+,a1
	move.b	(a1),d0
	swap	d0
	add.w	(a0)+,a1
	move.w	(a1),d0
	add.w	(a0)+,a1
	move.b	(a1),d0

	move.l	d0,(a2)+
	rol.w	#8,d0
	swap	d0
	rol.w	#8,d0
	move.l	d0,-(a3)

	add.w	(a0)+,a1
	move.w	(a1),d0
	add.w	(a0)+,a1
	move.b	(a1),d0
	swap	d0
	add.w	(a0)+,a1
	move.w	(a1),d0
	add.w	(a0)+,a1
	move.b	(a1),d0

	move.l	d0,(a2)+
	rol.w	#8,d0
	swap	d0
	rol.w	#8,d0
	move.l	d0,-(a3)

	add.w	(a0)+,a1
	move.w	(a1),d0
	add.w	(a0)+,a1
	move.b	(a1),d0
	swap	d0
	add.w	(a0)+,a1
	move.w	(a1),d0
	add.w	(a0)+,a1
	move.b	(a1),d0

	move.l	d0,(a2)+
	rol.w	#8,d0
	swap	d0
	rol.w	#8,d0
	move.l	d0,-(a3)

	dbf	d3,.loop2

	dbf	d2,.loop1

	rts

*-----------------------------------------------------------------------*
;
; Chunky2Planar Conversion Routine

FastC2P
	move.l	#$00ff00ff,a3
	move.l	#$0f0f0f0f,a4
	move.l	#$33333333,a5
	move.l	#$55555555,a6

	moveq	#0,d0
	move.w	bm_BytesPerRow(a1),d0
	moveq	#0,d1
	move.b	bm_Depth(a1),d1
	add.w	d1,d1
	divu	d1,d0
	add.w	d0,d0
	move.w	d0,a2
	move.w	bm_Rows(a1),d0
	subq.w	#1,d0
	add.w	d1,d1
	jmp	FastC2PTab-3*4(pc,d1.w)

FastC2PTab				; 1 & 2 planes are not supported
	bra	FastC2P3
	bra	FastC2P4
	bra	FastC2P5
	bra	FastC2P6
	bra	FastC2P7
	bra	FastC2P8


FastC2P3:
	move.l	bm_Planes(a1),a1
.loop1
	move.w	a2,d1
	lsr.w	#1,d1
	subq.w	#1,d1
.loop2
	movem.l	(a0)+,d4-d7

	move.l	a3,d2
	move.l	a3,d3
	and.l	d4,d2
	and.l	d6,d3
	eor.l	d2,d4
	eor.l	d3,d6
	lsl.l	#8,d2
	lsr.l	#8,d6
	or.l	d6,d4
	or.l	d3,d2

	move.l	a3,d3
	move.l	a3,d6
	and.l	d5,d3
	and.l	d7,d6
	eor.l	d3,d5
	eor.l	d6,d7
	lsl.l	#8,d3
	lsr.l	#8,d7
	or.l	d7,d5
	or.l	d6,d3

	move.l	a4,d6
	move.l	a4,d7
	and.l	d4,d6
	and.l	d5,d7
	eor.l	d6,d4
	eor.l	d7,d5
	lsl.l	#4,d6
	lsr.l	#4,d5
	or.l	d5,d4
	or.l	d7,d6

	move.l	a4,d7
	move.l	a4,d5
	and.l	d2,d7
	and.l	d3,d5
	eor.l	d7,d2
	eor.l	d5,d3
	lsl.l	#4,d7
	lsr.l	#4,d3
	or.l	d3,d2
	or.l	d5,d7

	swap	d6
	move.w	d6,d3
	move.w	d4,d6
	move.w	d3,d4
	swap	d6

	swap	d7
	move.w	d7,d3
	move.w	d2,d7
	move.w	d3,d2
	swap	d7

	move.l	a5,d3
	move.l	a5,d5
	and.l	d4,d3
	and.l	d6,d5
	eor.l	d3,d4
	eor.l	d5,d6
	lsl.l	#2,d3
	lsr.l	#2,d6
	or.l	d6,d4
	or.l	d5,d3

	move.l	a5,d5
	move.l	a5,d6
	and.l	d2,d5
	and.l	d7,d6
	eor.l	d5,d2
	eor.l	d6,d7
	lsl.l	#2,d5
	lsr.l	#2,d7
	or.l	d7,d2
	or.l	d6,d5

	move.l	a6,d6
	move.l	a6,d7
	and.l	d4,d6
	and.l	d2,d7
	eor.l	d6,d4
	eor.l	d7,d2
	lsr.l	#1,d2
	or.l	d2,d4
	add.l	d6,d6
	or.l	d7,d6

	move.l	a6,d7
	move.l	a6,d2
	and.l	d3,d7
	and.l	d5,d2
	eor.l	d7,d3
	eor.l	d2,d5
	lsr.l	#1,d5
	or.l	d5,d3
	add.l	d7,d7
	or.l	d2,d7

	move.w	d7,(a1)+		; bit 0
	move.w	a2,d2
	move.w	d3,-2(a1,d2.w)		; bit 1
	add.w	a2,d2
	move.w	d6,-2(a1,d2.w)		; bit 2

	dbra	d1,.loop2

	adda.w	d2,a1

	dbra	d0,.loop1
	rts


FastC2P4:
	move.l	bm_Planes(a1),a1
.loop1
	move.w	a2,d1
	lsr.w	#1,d1
	subq.w	#1,d1
.loop2
	movem.l	(a0)+,d4-d7

	move.l	a3,d2
	move.l	a3,d3
	and.l	d4,d2
	and.l	d6,d3
	eor.l	d2,d4
	eor.l	d3,d6
	lsl.l	#8,d2
	lsr.l	#8,d6
	or.l	d6,d4
	or.l	d3,d2

	move.l	a3,d3
	move.l	a3,d6
	and.l	d5,d3
	and.l	d7,d6
	eor.l	d3,d5
	eor.l	d6,d7
	lsl.l	#8,d3
	lsr.l	#8,d7
	or.l	d7,d5
	or.l	d6,d3

	move.l	a4,d6
	move.l	a4,d7
	and.l	d4,d6
	and.l	d5,d7
	eor.l	d6,d4
	eor.l	d7,d5
	lsl.l	#4,d6
	lsr.l	#4,d5
	or.l	d5,d4
	or.l	d7,d6

	move.l	a4,d7
	move.l	a4,d5
	and.l	d2,d7
	and.l	d3,d5
	eor.l	d7,d2
	eor.l	d5,d3
	lsl.l	#4,d7
	lsr.l	#4,d3
	or.l	d3,d2
	or.l	d5,d7

	swap	d6
	move.w	d6,d3
	move.w	d4,d6
	move.w	d3,d4
	swap	d6

	swap	d7
	move.w	d7,d3
	move.w	d2,d7
	move.w	d3,d2
	swap	d7

	move.l	a5,d3
	move.l	a5,d5
	and.l	d4,d3
	and.l	d6,d5
	eor.l	d3,d4
	eor.l	d5,d6
	lsl.l	#2,d3
	lsr.l	#2,d6
	or.l	d6,d4
	or.l	d5,d3

	move.l	a5,d5
	move.l	a5,d6
	and.l	d2,d5
	and.l	d7,d6
	eor.l	d5,d2
	eor.l	d6,d7
	lsl.l	#2,d5
	lsr.l	#2,d7
	or.l	d7,d2
	or.l	d6,d5

	move.l	a6,d6
	move.l	a6,d7
	and.l	d4,d6
	and.l	d2,d7
	eor.l	d6,d4
	eor.l	d7,d2
	lsr.l	#1,d2
	or.l	d2,d4
	add.l	d6,d6
	or.l	d7,d6

	move.l	a6,d7
	move.l	a6,d2
	and.l	d3,d7
	and.l	d5,d2
	eor.l	d7,d3
	eor.l	d2,d5
	lsr.l	#1,d5
	or.l	d5,d3
	add.l	d7,d7
	or.l	d2,d7

	move.w	d7,(a1)+		; bit 0
	move.w	a2,d2
	move.w	d3,-2(a1,d2.w)		; bit 1
	add.w	a2,d2
	move.w	d6,-2(a1,d2.w)		; bit 2
	add.w	a2,d2
	move.w	d4,-2(a1,d2.w)		; bit 3

	dbra	d1,.loop2

	adda.w	d2,a1

	dbra	d0,.loop1
	rts


FastC2P5:
	move.l	bm_Planes(a1),a1
.loop1
	move.w	a2,d1
	lsr.w	#1,d1
	subq.w	#1,d1
.loop2
	movem.l	(a0)+,d4-d7

	move.l	a3,d2
	move.l	a3,d3
	and.l	d4,d2
	and.l	d6,d3
	eor.l	d2,d4
	eor.l	d3,d6
	lsl.l	#8,d2
	lsr.l	#8,d6
	or.l	d6,d4
	or.l	d3,d2

	move.l	a3,d3
	move.l	a3,d6
	and.l	d5,d3
	and.l	d7,d6
	eor.l	d3,d5
	eor.l	d6,d7
	lsl.l	#8,d3
	lsr.l	#8,d7
	or.l	d7,d5
	or.l	d6,d3

	move.l	a4,d6
	move.l	a4,d7
	and.l	d4,d6
	and.l	d5,d7
	eor.l	d6,d4
	eor.l	d7,d5
	lsl.l	#4,d6
	lsr.l	#4,d5
	or.l	d5,d4
	or.l	d7,d6

	move.l	a4,d7
	move.l	a4,d5
	and.l	d2,d7
	and.l	d3,d5
	eor.l	d7,d2
	eor.l	d5,d3
	lsl.l	#4,d7
	lsr.l	#4,d3
	or.l	d3,d2
	or.l	d5,d7

	swap	d6
	move.w	d6,d3
	move.w	d4,d6
	move.w	d3,d4
	swap	d6

	swap	d7
	move.w	d7,d3
	move.w	d2,d7
	move.w	d3,d2
	swap	d7

	move.l	a5,d3
	move.l	a5,d5
	and.l	d4,d3
	and.l	d6,d5
	eor.l	d3,d4
	eor.l	d5,d6
	lsl.l	#2,d3
	lsr.l	#2,d6
	or.l	d6,d4
	or.l	d5,d3

	move.l	a5,d5
	move.l	a5,d6
	and.l	d2,d5
	and.l	d7,d6
	eor.l	d5,d2
	eor.l	d6,d7
	lsl.l	#2,d5
	lsr.l	#2,d7
	or.l	d7,d2
	or.l	d6,d5

	move.l	a6,d6
	move.l	a6,d7
	and.l	d4,d6
	and.l	d2,d7
	eor.l	d6,d4
	eor.l	d7,d2
	lsr.l	#1,d2
	or.l	d2,d4
	add.l	d6,d6
	or.l	d7,d6

	move.l	a6,d7
	move.l	a6,d2
	and.l	d3,d7
	and.l	d5,d2
	eor.l	d7,d3
	eor.l	d2,d5
	lsr.l	#1,d5
	or.l	d5,d3
	add.l	d7,d7
	or.l	d2,d7

	move.w	d7,(a1)+		; bit 0
	move.w	a2,d2
	move.w	d3,-2(a1,d2.w)		; bit 1
	add.w	a2,d2
	move.w	d6,-2(a1,d2.w)		; bit 2
	add.w	a2,d2
	move.w	d4,-2(a1,d2.w)		; bit 3
	swap	d7
	add.w	a2,d2
	move.w	d7,-2(a1,d2.w)		; bit 4

	dbra	d1,.loop2

	adda.w	d2,a1

	dbra	d0,.loop1
	rts


FastC2P6:
	move.l	bm_Planes(a1),a1
.loop1
	move.w	a2,d1
	lsr.w	#1,d1
	subq.w	#1,d1
.loop2
	movem.l	(a0)+,d4-d7

	move.l	a3,d2
	move.l	a3,d3
	and.l	d4,d2
	and.l	d6,d3
	eor.l	d2,d4
	eor.l	d3,d6
	lsl.l	#8,d2
	lsr.l	#8,d6
	or.l	d6,d4
	or.l	d3,d2

	move.l	a3,d3
	move.l	a3,d6
	and.l	d5,d3
	and.l	d7,d6
	eor.l	d3,d5
	eor.l	d6,d7
	lsl.l	#8,d3
	lsr.l	#8,d7
	or.l	d7,d5
	or.l	d6,d3

	move.l	a4,d6
	move.l	a4,d7
	and.l	d4,d6
	and.l	d5,d7
	eor.l	d6,d4
	eor.l	d7,d5
	lsl.l	#4,d6
	lsr.l	#4,d5
	or.l	d5,d4
	or.l	d7,d6

	move.l	a4,d7
	move.l	a4,d5
	and.l	d2,d7
	and.l	d3,d5
	eor.l	d7,d2
	eor.l	d5,d3
	lsl.l	#4,d7
	lsr.l	#4,d3
	or.l	d3,d2
	or.l	d5,d7

	swap	d6
	move.w	d6,d3
	move.w	d4,d6
	move.w	d3,d4
	swap	d6

	swap	d7
	move.w	d7,d3
	move.w	d2,d7
	move.w	d3,d2
	swap	d7

	move.l	a5,d3
	move.l	a5,d5
	and.l	d4,d3
	and.l	d6,d5
	eor.l	d3,d4
	eor.l	d5,d6
	lsl.l	#2,d3
	lsr.l	#2,d6
	or.l	d6,d4
	or.l	d5,d3

	move.l	a5,d5
	move.l	a5,d6
	and.l	d2,d5
	and.l	d7,d6
	eor.l	d5,d2
	eor.l	d6,d7
	lsl.l	#2,d5
	lsr.l	#2,d7
	or.l	d7,d2
	or.l	d6,d5

	move.l	a6,d6
	move.l	a6,d7
	and.l	d4,d6
	and.l	d2,d7
	eor.l	d6,d4
	eor.l	d7,d2
	lsr.l	#1,d2
	or.l	d2,d4
	add.l	d6,d6
	or.l	d7,d6

	move.l	a6,d7
	move.l	a6,d2
	and.l	d3,d7
	and.l	d5,d2
	eor.l	d7,d3
	eor.l	d2,d5
	lsr.l	#1,d5
	or.l	d5,d3
	add.l	d7,d7
	or.l	d2,d7

	move.w	d7,(a1)+		; bit 0
	move.w	a2,d2
	move.w	d3,-2(a1,d2.w)		; bit 1
	add.w	a2,d2
	move.w	d6,-2(a1,d2.w)		; bit 2
	add.w	a2,d2
	move.w	d4,-2(a1,d2.w)		; bit 3
	swap	d7
	add.w	a2,d2
	move.w	d7,-2(a1,d2.w)		; bit 4
	swap	d3
	add.w	a2,d2
	move.w	d3,-2(a1,d2.w)		; bit 5

	dbra	d1,.loop2

	adda.w	d2,a1

	dbra	d0,.loop1
	rts


FastC2P7:
	move.l	bm_Planes(a1),a1
.loop1
	move.w	a2,d1
	lsr.w	#1,d1
	subq.w	#1,d1
.loop2
	movem.l	(a0)+,d4-d7

	move.l	a3,d2
	move.l	a3,d3
	and.l	d4,d2
	and.l	d6,d3
	eor.l	d2,d4
	eor.l	d3,d6
	lsl.l	#8,d2
	lsr.l	#8,d6
	or.l	d6,d4
	or.l	d3,d2

	move.l	a3,d3
	move.l	a3,d6
	and.l	d5,d3
	and.l	d7,d6
	eor.l	d3,d5
	eor.l	d6,d7
	lsl.l	#8,d3
	lsr.l	#8,d7
	or.l	d7,d5
	or.l	d6,d3

	move.l	a4,d6
	move.l	a4,d7
	and.l	d4,d6
	and.l	d5,d7
	eor.l	d6,d4
	eor.l	d7,d5
	lsl.l	#4,d6
	lsr.l	#4,d5
	or.l	d5,d4
	or.l	d7,d6

	move.l	a4,d7
	move.l	a4,d5
	and.l	d2,d7
	and.l	d3,d5
	eor.l	d7,d2
	eor.l	d5,d3
	lsl.l	#4,d7
	lsr.l	#4,d3
	or.l	d3,d2
	or.l	d5,d7

	swap	d6
	move.w	d6,d3
	move.w	d4,d6
	move.w	d3,d4
	swap	d6

	swap	d7
	move.w	d7,d3
	move.w	d2,d7
	move.w	d3,d2
	swap	d7

	move.l	a5,d3
	move.l	a5,d5
	and.l	d4,d3
	and.l	d6,d5
	eor.l	d3,d4
	eor.l	d5,d6
	lsl.l	#2,d3
	lsr.l	#2,d6
	or.l	d6,d4
	or.l	d5,d3

	move.l	a5,d5
	move.l	a5,d6
	and.l	d2,d5
	and.l	d7,d6
	eor.l	d5,d2
	eor.l	d6,d7
	lsl.l	#2,d5
	lsr.l	#2,d7
	or.l	d7,d2
	or.l	d6,d5

	move.l	a6,d6
	move.l	a6,d7
	and.l	d4,d6
	and.l	d2,d7
	eor.l	d6,d4
	eor.l	d7,d2
	lsr.l	#1,d2
	or.l	d2,d4
	add.l	d6,d6
	or.l	d7,d6

	move.l	a6,d7
	move.l	a6,d2
	and.l	d3,d7
	and.l	d5,d2
	eor.l	d7,d3
	eor.l	d2,d5
	lsr.l	#1,d5
	or.l	d5,d3
	add.l	d7,d7
	or.l	d2,d7

	move.w	d7,(a1)+		; bit 0
	move.w	a2,d2
	move.w	d3,-2(a1,d2.w)		; bit 1
	add.w	a2,d2
	move.w	d6,-2(a1,d2.w)		; bit 2
	add.w	a2,d2
	move.w	d4,-2(a1,d2.w)		; bit 3
	swap	d7
	add.w	a2,d2
	move.w	d7,-2(a1,d2.w)		; bit 4
	swap	d3
	add.w	a2,d2
	move.w	d3,-2(a1,d2.w)		; bit 5
	swap	d6
	add.w	a2,d2
	move.w	d6,-2(a1,d2.w)		; bit 6

	dbra	d1,.loop2

	adda.w	d2,a1

	dbra	d0,.loop1
	rts


FastC2P8:
	move.l	bm_Planes(a1),a1
.loop1
	move.w	a2,d1
	lsr.w	#1,d1
	subq.w	#1,d1
.loop2
	movem.l	(a0)+,d4-d7

	move.l	a3,d2
	move.l	a3,d3
	and.l	d4,d2
	and.l	d6,d3
	eor.l	d2,d4
	eor.l	d3,d6
	lsl.l	#8,d2
	lsr.l	#8,d6
	or.l	d6,d4
	or.l	d3,d2

	move.l	a3,d3
	move.l	a3,d6
	and.l	d5,d3
	and.l	d7,d6
	eor.l	d3,d5
	eor.l	d6,d7
	lsl.l	#8,d3
	lsr.l	#8,d7
	or.l	d7,d5
	or.l	d6,d3

	move.l	a4,d6
	move.l	a4,d7
	and.l	d4,d6
	and.l	d5,d7
	eor.l	d6,d4
	eor.l	d7,d5
	lsl.l	#4,d6
	lsr.l	#4,d5
	or.l	d5,d4
	or.l	d7,d6

	move.l	a4,d7
	move.l	a4,d5
	and.l	d2,d7
	and.l	d3,d5
	eor.l	d7,d2
	eor.l	d5,d3
	lsl.l	#4,d7
	lsr.l	#4,d3
	or.l	d3,d2
	or.l	d5,d7

	swap	d6
	move.w	d6,d3
	move.w	d4,d6
	move.w	d3,d4
	swap	d6

	swap	d7
	move.w	d7,d3
	move.w	d2,d7
	move.w	d3,d2
	swap	d7

	move.l	a5,d3
	move.l	a5,d5
	and.l	d4,d3
	and.l	d6,d5
	eor.l	d3,d4
	eor.l	d5,d6
	lsl.l	#2,d3
	lsr.l	#2,d6
	or.l	d6,d4
	or.l	d5,d3

	move.l	a5,d5
	move.l	a5,d6
	and.l	d2,d5
	and.l	d7,d6
	eor.l	d5,d2
	eor.l	d6,d7
	lsl.l	#2,d5
	lsr.l	#2,d7
	or.l	d7,d2
	or.l	d6,d5

	move.l	a6,d6
	move.l	a6,d7
	and.l	d4,d6
	and.l	d2,d7
	eor.l	d6,d4
	eor.l	d7,d2
	lsr.l	#1,d2
	or.l	d2,d4
	add.l	d6,d6
	or.l	d7,d6

	move.l	a6,d7
	move.l	a6,d2
	and.l	d3,d7
	and.l	d5,d2
	eor.l	d7,d3
	eor.l	d2,d5
	lsr.l	#1,d5
	or.l	d5,d3
	add.l	d7,d7
	or.l	d2,d7

	move.w	d7,(a1)+		; bit 0
	move.w	a2,d2
	move.w	d3,-2(a1,d2.w)		; bit 1
	add.w	a2,d2
	move.w	d6,-2(a1,d2.w)		; bit 2
	add.w	a2,d2
	move.w	d4,-2(a1,d2.w)		; bit 3
	swap	d7
	add.w	a2,d2
	move.w	d7,-2(a1,d2.w)		; bit 4
	swap	d3
	add.w	a2,d2
	move.w	d3,-2(a1,d2.w)		; bit 5
	swap	d6
	add.w	a2,d2
	move.w	d6,-2(a1,d2.w)		; bit 6
	swap	d4
	add.w	a2,d2
	move.w	d4,-2(a1,d2.w)		; bit 7

	dbra	d1,.loop2

	adda.w	d2,a1

	dbra	d0,.loop1
	rts

*-----------------------------------------------------------------------*

;
;
	SECTION GenieDatas,Data
;
;

delibase:	dc.l 0
DeliPort:	dc.l 0
NoteInfo:	dc.l 0

QuitFlag:	dc.w -1				; kein Ende (default)
ScreenCnt:	dc.w 0
ScaleFactor:	dc.w 0

_GenieScreen:	dc.l 0
_VisualInfo:	dc.l 0
_IntuiMessage:	dc.l 0
_TimePort:	dc.l 0

_DOSBase:	dc.l 0
_GfxBase:	dc.l 0
_GadToolsBase:	dc.l 0
_IntuitionBase:	dc.l 0
_MathBase:	dc.l 0
_MathTransBase:	dc.l 0
_UtilityBase:	dc.l 0

VBlankSigBit:	dc.b 0
VBlankSigFlag:	dc.b 0
	even
VBlankSigTask:	dc.l 0

ScopeWidth:	dc.w 128
ScopeHeight:	dc.w 128

ScopeColors:	dc.w 16

PixWidth:	dc.w 128	; (fixed)
PixHeight:	dc.w 256	; (fixed)

MixFreq:	dc.w 28867/4

ChunkyDat:	dc.l 0
BitMapPtr:	dc.l 0
TunnelTab:	dc.l 0

WaveAngl:	dc.w 0		; Winkel
WaveSize:	dc.w 0		; Size

WavePosX:	dc.w 0		; Wave Offset
WavePosY:	dc.w 0		; "

WaveSine:			; Zeiger auf WaveSines
WaveSAD1:	dc.w 0		; Sinusposition Angle Delta 1
WaveSAD2:	dc.w 0		; Sinusposition Angle Delta 2

WaveSS1:	dc.w 0		; Sinusposition Size 1
WaveSS2:	dc.w 0		; Sinusposition Size 2

WaveSX1:	dc.w 0		; Sinusposition XPos 1
WaveSX2:	dc.w 0		; Sinusposition XPos 2

WaveSY1:	dc.w 0		; Sinusposition YPos 1
WaveSY2:	dc.w 0		; Sinusposition YPos 2

LinePtr:	dc.w 0		; Zeilenzähler für MakeLine

SineAPtr:	dc.w 0
SineBPtr:	dc.w 0
SineCPtr:	dc.w 0


**********************************************************************
*                            Window-Tags                             *
**********************************************************************

WindowPubScrn:
		dc.l WA_PubScreen,0
		dc.l WA_AutoAdjust,1
		dc.l TAG_DONE


**********************************************************************
*                            Gadget-Tags                             *
**********************************************************************

GadgetOnOffTag:	dc.l GA_Disabled,0
		dc.l TAG_DONE

GadgetCheckTag:	dc.l GTCB_Checked,0
		dc.l TAG_DONE

GadgetTextTag:	dc.l GTTX_Text,0
		dc.l TAG_DONE

GadgetStringTag:dc.l GTST_String,0
		dc.l TAG_DONE

GadgetNumberTag:dc.l GTIN_Number,0
		dc.l TAG_DONE

GadgetRadioTag:	dc.l GTMX_Active,0
		dc.l TAG_DONE

GadgetLabelsTag:dc.l GTLV_Labels,0
		dc.l TAG_DONE

GadgetTopTag:	dc.l GTLV_Top,0
		dc.l TAG_DONE


**********************************************************************
*                             Menu-Tags                              *
**********************************************************************

MenuTags:
	dc.l	GTMN_NewLookMenus,1
	dc.l	TAG_DONE


**********************************************************************
*                           BevelBox-Tags                            *
**********************************************************************

BevelBoxTags:
	dc.l	GT_VisualInfo,0
	dc.l	GTBB_Recessed,1
	dc.l	TAG_DONE


**********************************************************************
*                               Window                               *
**********************************************************************

_GenieWindow:	dc.l 0


GenieWindow:	dc.l WA_Left,0
		dc.l WA_Top,1
		dc.l WA_InnerWidth,148
		dc.l WA_InnerHeight,138
		dc.l WA_MinWidth,92
		dc.l WA_MaxWidth,1024
		dc.l WA_MinHeight,98
		dc.l WA_MaxHeight,1024
		dc.l WA_Gadgets,0
		dc.l WA_Title,GenieWindowName
		dc.l WA_IDCMP,IDCMP_CLOSEWINDOW!IDCMP_SIZEVERIFY!IDCMP_CHANGEWINDOW!IDCMP_NEWSIZE!IDCMP_GADGETUP!IDCMP_GADGETDOWN!IDCMP_MOUSEMOVE!IDCMP_MENUPICK
GenieWinFlags:	dc.l WA_Flags,WFLG_ACTIVATE!WFLG_DRAGBAR!WFLG_DEPTHGADGET!WFLG_CLOSEGADGET!WFLG_SIZEGADGET!WFLG_SIZEBBOTTOM!WFLG_NEWLOOKMENUS
		dc.l TAG_MORE,WindowPubScrn


**********************************************************************
*                              Gadgets                               *
**********************************************************************


**********************************************************************
*                               Menu                                 *
**********************************************************************

_GenieMenuStrip:	dc.l 0


GenieMenu:
	dc.b	NM_TITLE,0		; gnm_Type, gnm_Pad	; PROJECT
	dc.l	GenieMenu1Name		; gnm_Label
	dc.l	0			; gnm_CommKey
	dc.w	0			; gnm_Flags (MENUENABLED by default)
	dc.l	0			; gnm_MutualExclude
	dc.l	0			; gnm_UserData

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText1
	dc.l	GenieShortCut1
	dc.w	ITEMTEXT+HIGHCOMP
	dc.l	0
	dc.l	About			; About

	dc.b	NM_ITEM,0
	dc.l	NM_BARLABEL
	dcb.w	7,0			; ======

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText2
	dc.l	GenieShortCut2
	dc.w	ITEMTEXT+HIGHCOMP
	dc.l	0
	dc.l	SaveGenieConfig		; Save Genie-Prefs

	dc.b	NM_ITEM,0
	dc.l	NM_BARLABEL
	dcb.w	7,0			; ======

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText3
	dc.l	GenieShortCut3
	dc.w	ITEMTEXT+HIGHCOMP
	dc.l	0
	dc.l	CloseGenieWindow	; Close Window

	dc.b	NM_ITEM,0
	dc.l	NM_BARLABEL
	dcb.w	7,0			; ======

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText4
	dc.l	GenieShortCut4
	dc.w	ITEMTEXT+HIGHCOMP
	dc.l	0
	dc.l	Exit			; Quit Genie

	dc.b	NM_TITLE,0		; gnm_Type, gnm_Pad	; SETTINGS
	dc.l	GenieMenu2Name		; gnm_Label
	dc.l	0			; gnm_CommKey
	dc.w	0			; gnm_Flags (MENUENABLED by default)
	dc.l	0			; gnm_MutualExclude
	dc.l	0			; gnm_UserData

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText5
	dc.l	GenieShortCut5
ACTFlag	dc.w	ITEMTEXT+HIGHCOMP+CHECKIT+CHECKED+MENUTOGGLE
	dc.l	0
	dc.l	ActivateWindow		; Activate

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText6
	dc.l	GenieShortCut6
PUPFlag	dc.w	ITEMTEXT+HIGHCOMP+CHECKIT+MENUTOGGLE
	dc.l	0
	dc.l	PopupWindow		; Popup

	dc.b	NM_ITEM,0
	dc.l	NM_BARLABEL
	dcb.w	7,0			; ======

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText7
	dc.l	GenieShortCut7
NBLFlag	dc.w	ITEMTEXT+HIGHCOMP+CHECKIT+MENUTOGGLE
	dc.l	0
	dc.l	NastyBlitter		; NastyBlit

	dc.b	NM_ITEM,0
	dc.l	NM_BARLABEL
	dcb.w	7,0			; ======

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText8
	dc.l	GenieShortCut8
C2PFlag	dc.w	ITEMTEXT+HIGHCOMP+CHECKIT+CHECKED
	dc.l	(1<<6)|(1<<7)
	dc.l	OwnC2P			; Custom C2P

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText9
	dc.l	GenieShortCut9
WPAFlag	dc.w	ITEMTEXT+HIGHCOMP+CHECKIT
	dc.l	(1<<5)|(1<<7)
	dc.l	UseWPA			; WritePixelArray

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText10
	dc.l	GenieShortCut10
WCPFlag	dc.w	ITEMTEXT+HIGHCOMP+CHECKIT+NM_ITEMDISABLED
	dc.l	(1<<5)|(1<<6)
	dc.l	UseWCP			; WriteChunkyPixels

	dc.b	NM_ITEM,0
	dc.l	NM_BARLABEL
	dcb.w	7,0			; ======

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText11
	dc.l	GenieShortCut11
C16Flag	dc.w	ITEMTEXT+HIGHCOMP+CHECKIT+CHECKED
	dc.l	(1<<10)
	dc.l	Color16Mode		; 16Color-Mode

	dc.b	NM_ITEM,0
	dc.l	GenieMTextText12
	dc.l	GenieShortCut12
C64Flag	dc.w	ITEMTEXT+HIGHCOMP+CHECKIT
	dc.l	(1<<9)
	dc.l	Color64Mode		; 64Color-Mode

	dc.b	NM_END,0		; END OF MENU
	dcb.w	9,0


**********************************************************************
*                            BevelBoxes                              *
**********************************************************************

GenieBevelBoxTable:	;list of bevelboxes that will be rendered into the window
		dc.l GenieBBArray1
		dc.l 0	;terminator


GenieBBArray1:
		dc.w 8,4,260,130


**********************************************************************
*                            Window-Texte                            *
**********************************************************************

GenieWindowName		dc.b 'DrWhoGenie V1.2',0


GenieMenu1Name		dc.b 'Project',0

GenieMTextText1		dc.b 'About...',0
GenieMTextText2		dc.b 'Save Prefs',0
GenieMTextText3		dc.b 'Hide',0
GenieMTextText4		dc.b 'Quit',0

GenieMenu2Name		dc.b 'Settings',0

GenieMTextText5		dc.b 'Activate',0
GenieMTextText6		dc.b 'Popup',0
GenieMTextText7		dc.b 'Nasty Blit',0
GenieMTextText8		dc.b 'Own C2P',0
GenieMTextText9		dc.b 'Use WPA',0
GenieMTextText10	dc.b 'Use WCP',0
GenieMTextText11	dc.b '16 Colors',0
GenieMTextText12	dc.b '64 Colors',0

GenieShortCut1		dc.b '?',0
GenieShortCut2		dc.b 'S',0
GenieShortCut3		dc.b 'H',0
GenieShortCut4		dc.b 'Q',0

GenieShortCut5		dc.b 'A',0
GenieShortCut6		dc.b 'P',0
GenieShortCut7		dc.b 'B',0
GenieShortCut8		dc.b '2',0
GenieShortCut9		dc.b 'W',0
GenieShortCut10		dc.b 'C',0
GenieShortCut11		dc.b 'I',0
GenieShortCut12		dc.b 'O',0

	even


**********************************************************************
*                           TextRequester                            *
**********************************************************************

AboutReqStruct:
		dc.l	EasyStruct_SIZEOF	; size
		dc.l	0			; Flags
		dc.l	GenieWindowName		; Title
		dc.l	AboutText		; TextFormat
		dc.l	OkText			; GadgetFormat

NoPensReqStruct:
		dc.l	EasyStruct_SIZEOF	; size
		dc.l	0			; Flags
		dc.l	GenieWindowName		; Title
		dc.l	NoPensText		; TextFormat
		dc.l	OkText			; GadgetFormat

NoBitReqStruct:
		dc.l	EasyStruct_SIZEOF	; size
		dc.l	0			; Flags
		dc.l	GenieWindowName		; Title
		dc.l	NoBitText		; TextFormat
		dc.l	OkText			; GadgetFormat


**********************************************************************
*                               Font                                 *
**********************************************************************

TOPAZ80:
	dc.l	TOPAZname
	dc.w	TOPAZ_EIGHTY
	dc.b	$00,$01


**********************************************************************
*                             TimeRequest                            *
**********************************************************************

TimeRequest:
		dc.l 0				; LN_SUCC
		dc.l 0				; LN_PRED
		dc.b 0				; LN_TYPE
		dc.b 0				; LN_PRI
		dc.l 0				; LN_NAME

		dc.l 0				; message reply port
		dc.w 0				; message len in bytes

		dc.l 0				; device node pointer
		dc.l 0				; unit (driver private)
		dc.w 0				; device command
		dc.b 0				; special flags
		dc.b 0				; error or warning code

		dc.l 0				; TV_SECS
		dc.l 0				; TV_MICRO


**********************************************************************
*                        TimeValue Structures                        *
**********************************************************************

EClockValue:	dc.l 0				; EV_HI
		dc.l 0				; EV_LO

EClockValue2:	dc.l 0				; EV_HI
		dc.l 0				; EV_LO


**********************************************************************
*                        Stummes Instrument                          *
**********************************************************************

QuietInstr:
	dc.l	QuietInstr	; Endadresse
	dc.l	0		; Restlänge
	dc.l	QuietInstr	; Ende LoopSample
	dc.l	0		; Länge LoopSample


**********************************************************************
*                             Interrupt                              *
**********************************************************************

VBlankIRQ:
	dc.l 0					; Succ
	dc.l 0					; Pred
	dc.b NT_INTERRUPT			; Type
	dc.b 0					; Pri
	dc.l VBlankIRQname			; Name
	dc.l 0					; Data
	dc.l VBlankInt				; Code (IRQ)


**********************************************************************
*                            Colortable                              *
**********************************************************************

; Original 'ARTE' colors
;
;	dc.w	$0000
;	dc.w	$0110
;	dc.w	$0330
;	dc.w	$0630
;	dc.w	$0830
;	dc.w	$0B20
;	dc.w	$0B40
;	dc.w	$0C60
;	dc.w	$0D90
;	dc.w	$0DB0
;	dc.w	$0DE0
;	dc.w	$06E0
;	dc.w	$00E0
;	dc.w	$00F7
;	dc.w	$00FE
;	dc.w	$008F

ColorTable:
	dc.l -1,(256<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(240<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(224<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(208<<24)-1,(0<<24),(256<<24)-1

	dc.l -1,(192<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(176<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(160<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(144<<24)-1,(0<<24),(256<<24)-1

	dc.l -1,(128<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(112<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(96<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(80<<24)-1,(0<<24),(256<<24)-1

	dc.l -1,(64<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(48<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(32<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(16<<24)-1,(0<<24),(256<<24)-1

	dc.l -1,(0<<24),(0<<24),(256<<24)-1
	dc.l -1,(0<<24),(16<<24),(256<<24)-1
	dc.l -1,(0<<24),(32<<24),(256<<24)-1
	dc.l -1,(0<<24),(48<<24),(256<<24)-1

	dc.l -1,(0<<24),(64<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(80<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(96<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(112<<24)-1,(256<<24)-1

	dc.l -1,(0<<24),(128<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(144<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(160<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(176<<24)-1,(256<<24)-1

	dc.l -1,(0<<24),(192<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(208<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(224<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(240<<24)-1,(256<<24)-1


	dc.l -1,(0<<24),(256<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(240<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(224<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(208<<24)-1,(256<<24)-1

	dc.l -1,(0<<24),(192<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(176<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(160<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(144<<24)-1,(256<<24)-1

	dc.l -1,(0<<24),(128<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(112<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(96<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(80<<24)-1,(256<<24)-1

	dc.l -1,(0<<24),(64<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(48<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(32<<24)-1,(256<<24)-1
	dc.l -1,(0<<24),(16<<24)-1,(256<<24)-1

	dc.l -1,(0<<24),(0<<24),(256<<24)-1
	dc.l -1,(16<<24),(0<<24),(256<<24)-1
	dc.l -1,(32<<24),(0<<24),(256<<24)-1
	dc.l -1,(48<<24),(0<<24),(256<<24)-1

	dc.l -1,(64<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(80<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(96<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(112<<24)-1,(0<<24),(256<<24)-1

	dc.l -1,(128<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(144<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(160<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(176<<24)-1,(0<<24),(256<<24)-1

	dc.l -1,(192<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(208<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(224<<24)-1,(0<<24),(256<<24)-1
	dc.l -1,(240<<24)-1,(0<<24),(256<<24)-1


**********************************************************************
*                              Pentags                               *
**********************************************************************

PenTags:
	dc.l OBP_Precision,PRECISION_EXACT
	dc.l OBP_FailIfBad,1
	dc.l TAG_DONE


**********************************************************************
*                               TmpRas                               *
**********************************************************************

TempRas:
	dcb.b tr_SIZEOF,0


**********************************************************************
*                            TempRastport                            *
**********************************************************************

TempRPort:
	dcb.b rp_SIZEOF,0


**********************************************************************
*                        verschiedene Texte                          *
**********************************************************************

	IFEQ	RELEASE_VERSION

AboutText	dc.b "           DrWho Genie",10
		dc.b "© 1994-95 by Delirium Softdesign",10
		dc.b 10
		dc.b " Special thanks to Chaos/Sanity",10
		dc.b "     for his cool routines!",10
		dc.b 10
		dc.b " THIS PIECE OF SOFTWARE IS BETA",10
		dc.b "  DON'T SPREAD, IT'S BUGGY !!!",0

	ELSE

AboutText	dc.b "           DrWho Genie",10
		dc.b "© 1994-95 by Delirium Softdesign",10
		dc.b "(Peter Kunath and Frank Riffel)",10
		dc.b "      All rights reserved.",10
		dc.b " Special thanks to Chaos/Sanity",10
		dc.b "     for his cool routines!",10
		dc.b " Thanks must also go to",10
		dc.b "  James McCoull, Peter McGavin",10
		dc.b "  and Conrad Sanderson for the",10
		dc.b "  'FastC2P' source",10
		dc.b " and to Stephan Schaem for the",10
		dc.b " source of 'WindowFX'",10
		dc.b "DeliMix sample-mixing technology",10
		dc.b "copyright by Delirium Softdesign.",10
		dc.b 10
		dc.b "This piece of software belongs",10
		dc.b "to the DeliTracker distribution.",0

	ENDC

NoPensText	dc.b "Not enough free pens available!",0

NoBitText	dc.b "Not enough contiguous graphics memory",10
		dc.b "for an interleaved bitmap available!",0

OkText		dc.b "  Ok  ",0

ConfigEnv		dc.b 'DeliConfig',0
ConfigPath		dc.b 'PROGDIR:DeliConfig',0
			dcb.b 120+1,0
ConfigFile		dc.b 'DrWhoGenie.prefs',0

TOPAZname		dc.b 'topaz.font',0

timername		dc.b 'timer.device',0

mathffpname		dc.b 'mathffp.library',0
mathtransname		dc.b 'mathtrans.library',0
utilityname		dc.b 'utility.library',0

VBlankIRQname		dc.b 'DrWhoGenie-VBlank',0


*-----------------------------------------------------------------------*

;
;
	SECTION GenieTabBuff,BSS
;
;

VTable:	ds.w	256*65			;  Umrechnungs-Tabelle für versch. Lautstärken


*-----------------------------------------------------------------------*

;
;
	SECTION GenieBSS,BSS
;
;

**********************************************************************
*                        Track-Data-Strukturen                       *
**********************************************************************

	rsreset
td_Note	rs.l	1	; Zeiger auf die NoteChannel Struct
td_SPtr	rs.l	1	; Zeiger auf das Sampleende
td_SLen	rs.l	1	; negative Sample-Restbytes
td_LPtr	rs.l	1	; Endadr. des Loopteils
td_LLen	rs.l	1	; negative Länge des Loopteils
td_Vol	rs.w	1	; Volume-Wert 0...64
td_Fre	rs.l	1	; Frequenz-Wert
td_FreC	rs.w	1	; Frequenz-Nachkomma-Zähler
td_SIZE	rs.l	0


Scope1Track:	ds.b td_SIZE

Scope2Track:	ds.b td_SIZE

Scope3Track:	ds.b td_SIZE

Scope4Track:	ds.b td_SIZE

Scope5Track:	ds.b td_SIZE

Scope6Track:	ds.b td_SIZE

Scope7Track:	ds.b td_SIZE

Scope8Track:	ds.b td_SIZE


**********************************************************************
*                           NullSamples                              *
**********************************************************************

BlankSampSize	EQU 256

SampleBuffer:	ds.w	BlankSampSize		; Buffer für beide Kanäle


**********************************************************************
*                         Sinus-Tabellen                             *
**********************************************************************

Sine:		ds.b	$4000
Sine2:		ds.b	$10000


**********************************************************************
*                       ArcusSinus-Tabelle                           *
**********************************************************************

ArcSinus:	ds.w	ASinSize+1


**********************************************************************
*                         Conversion Table                           *
**********************************************************************

WordTable:	ds.w	128


**********************************************************************
*                            Pix-Daten                               *
**********************************************************************

PixData1:	ds.b	$10000
PixData2:	ds.b	$10000


*-----------------------------------------------------------------------*

;
;
	SECTION GenieChip,BSS_C
;
;

**********************************************************************
*                            TmpRas Buffer                           *
**********************************************************************


TmpRasBuffer:	ds.b	4096


*-----------------------------------------------------------------------*

