;
; "PSMP"  Play Sample
; -------------------
; by Smack/Infect
;
;
; REQUIRES: OS V37+
;
;
; V0.1 (Wednesday 17-Jul-96)
;   -first version
;       play uncompressed IFF-8SVX on all 4 channels
;       audio.device for allocating channels
;       hardware hits: level 4 irq, filter, audio
;
; V0.2 (Tue 01-Oct-96)
;   -support compressed samples (1=Fibonacci Delta, 2=Exponential Delta)
;   -"PLAYBACKRATE" option
;   -exec interrupt handler (INTB_AUD0)
;
; V0.3 (Sat 05-Oct-96)
;   -support XPK compressed samples (using XpkOpen(), XpkRead() etc.)
;   -runtime controls:
;     CTRL-F = toggle filter
;     CTRL-E = repeat mode off
;     CTRL-D = repeat mode on
;     CTRL-C = exit immediately
;
; V0.4 (Thu 10-Oct-96)
;   -replaced 68020+ instructions (MUL/DIV) by utility.library calls
;
; V0.5 (Fri 25-Oct-96)
;   -support stereo samples
;   -better handling of "loading not ready in time"-situations
;    (now there is a silent gap instead of playing "trash")
;   -major internal cleanups
;
; V0.6 (Wed 06-Nov-96)
;   -added Workbench startup
;   -fixed Signal()/Wait() calls (use signalmask instead of signalnumber!)
;   -fixed handling of odd chunksizes
;
; V0.7 (Sat 16-Nov-96)
;   -added "SMALLWINDOW" and "LOADALL" options/tooltypes



buffersize=63*1024	;must be below 64K
	incdir	includes:
	include	libraries/xpk.i
	include	os_macros.is
	include	hardware-registers.is
	include	dos/dos.i
	include	dos/dosextens.i


	STRUCTURE myFH,0
	ULONG	mfh_fh		;(must be the first item!!)
	UWORD	mfh_is_xpk	;if non-zero then XPK
	ULONG	mfh_filepos	;XPK only - position in file
	APTR	mfh_xbuff	;XPK only - address of decrunch buffer
	ULONG	mfh_xbuffsize	;XPK only - size of decrunch buffer (=XPK chunksize)
	APTR	mfh_buffpos	;XPK only - current position in decrunch buffer
	ULONG	mfh_buffcontent	;XPK only - current content of decrunch buffer
	APTR	mfh_filename	;(must be the last item!!)
	LABEL	mfh_SIZEOF

	section	aaaa,code
first_
	basereg	first_,a4
	lea	(first_,pc),a4
;--------------------------------------
; open libs
	move.l	(4.w),a6
	move.l	(378,a6),a0	;LibList
	lea	(dosnam,pc),a1
	CALL	FindName		;DOS
	move.l	d0,(dosbase,a4)
	move.l	(378,a6),a0	;LibList
	lea	(intuinam,pc),a1
	CALL	FindName		;INTUITION
	move.l	d0,(intuitionbase,a4)
	lea	(utilnam,pc),a1
	moveq	#37,d0
	CALL	OpenLibrary		;UTILITY
	move.l	d0,(utilitybase,a4)
	beq.w	err_ende
	lea	(iconnam,pc),a1
	moveq	#37,d0
	CALL	OpenLibrary		;ICON
	move.l	d0,(iconbase,a4)
	beq.w	err_ende


;--------------------------------------
; handle arguments
	sub.l	a1,a1
	CALL	FindTask
	move.l	d0,a5
	tst.l	(172,a5)	;pr_CLI
	bne.b	.from_cli
	lea	(92,a5),a0	;pr_MsgPort
	CALL	WaitPort
	lea	(92,a5),a0	;pr_MsgPort
	CALL	GetMsg			;workbench msg
	move.l	d0,(wbmsg,a4)
	bra.b	.not_cli
.from_cli
	lea	(template,pc),a0
	move.l	a0,d1
	lea	(filenamept,pc),a0
	move.l	a0,d2
	moveq	#0,d3
	CALLDOS	ReadArgs		;read command line args
	move.l	d0,(rdargs,a4)
.not_cli

	move.l	(wbmsg,pc),d0
	beq.w	.not_wb
	move.l	d0,a5			;a5=wbmsg
	move.l	(36,a5),a3	;sm_ArgList
	move.l	(a3),d1		;wa_Lock
	CALLDOS	CurrentDir
	move.l	d0,(oldcurrdir,a4)
	move.l	(4,a3),a0	;wa_Name
	CALLICON GetDiskObject		;read program's icon
	move.l	d0,d7
	beq.b	.no_icon1
	bsr.b	.read_tooltypes
	move.l	d7,a0
	CALL	FreeDiskObject
.no_icon1
	move.l	(28,a5),d0	;sm_NumArgs
	subq.l	#1,d0
	beq.b	.no_icon2
	move.l	(36,a5),a3	;sm_ArgList
	move.l	(8,a3),d1	;wa_sizeof+wa_Lock
	CALLDOS	CurrentDir
	move.l	(12,a3),a1	;wa_sizeof+wa_Name
	move.l	a1,a0
	move.l	(filenamebuffpt,pc),a2
	move.l	a2,(filenamept,a4)
.cloo	move.b	(a1)+,(a2)+
	bne.b	.cloo
	CALLICON GetDiskObject		;read sample's icon
	move.l	d0,d7
	beq.b	.no_icon2
	bsr.b	.read_tooltypes
	move.l	d7,a0
	CALL	FreeDiskObject
.no_icon2
	bra.b	.not_wb
.read_tooltypes
	move.l	d7,a0
	move.l	($36,a0),a3	;a3=do_ToolTypes
	move.l	a3,a0		;PLAYBACKRATE
	lea	(tt_rate,pc),a1
	CALL	FindToolType
	move.l	d0,d1
	lea	(rate_arg,pc),a0
	move.l	a0,d2
	move.l	a0,(playbackrate,a4)
	CALLDOS	StrToLong
	move.l	a3,a0		;FILTER
	lea	(tt_filter,pc),a1
	CALLICON FindToolType
	move.l	d0,(filter,a4)
	move.l	a3,a0		;REPEAT
	lea	(tt_repeat,pc),a1
	CALL	FindToolType
	move.l	d0,(repeat,a4)
	move.l	a3,a0		;INFO
	lea	(tt_info,pc),a1
	CALL	FindToolType
	move.l	d0,(info,a4)
	move.l	a3,a0		;SMALLWINDOW
	lea	(tt_smallwin,pc),a1
	CALL	FindToolType
	move.l	d0,(smallwindow,a4)
	move.l	a3,a0		;LOADALL
	lea	(tt_loadall,pc),a1
	CALL	FindToolType
	move.l	d0,(loadall,a4)
	rts
.not_wb

	move.l	(smallwindow,pc),d0
	bne.b	.smallwin
	CALLDOS	Output
	move.l	d0,(output,a4)		;output
	bne.b	.output_ok
	lea	(connam,pc),a0
	move.l	a0,d1
	move.l	#MODE_OLDFILE,d2
	CALL	Open			;open own window
	move.l	d0,(output,a4)
	move.l	d0,(conwindow,a4)
.output_ok
	move.l	(output,pc),d1
	lea	(maintxt,pc),a0
	move.l	a0,d2
	CALLDOS	FPutS			;print title string
	bra.b	.nosmallwin
.smallwin
	clr.l	(info,a4)
.nosmallwin
	move.l	(playbackrate,pc),d0
	beq.b	.norate_arg
	move.l	d0,a0
	move.l	(a0),d0
	ble.b	.norate_arg
	move.l	d0,(rate_arg,a4)
.norate_arg

	tst.l	(filenamept,a4)
	bne.w	skipfilerequester
dofilerequester
	moveq	#38,d0
	lea	(rtnam,pc),a1
	CALLEXEC OpenLibrary		;V38 reqtools.library
	tst.l	d0
	beq.w	ende
	move.l	d0,a6
	moveq	#0,d0		;RT_FILEREQ
	sub.l	a0,a0
	CALL	rtAllocRequestA
	tst.l	d0
	beq.w	err_ende
	move.l	d0,a5
	lea	(filereqtags,pc),a0
	move.l	a5,a1
	move.l	(lbuffpt,pc),a2
	lea	(filereqtitle,pc),a3
	CALL	rtFileRequestA
	move.l	(16,a5),a0	;filereq->dir
	move.l	(filenamebuffpt,pc),a1
	clr.l	(a1)
.dircop	move.b	(a0)+,(a1)+
	bne.b	.dircop
	move.l	a6,d7
	move.l	(filenamebuffpt,pc),d1
	move.l	(lbuffpt,pc),d2
	move.l	#1024,d3
	CALLDOS	AddPart
	move.l	d7,a6
	move.l	(filenamebuffpt,pc),(filenamept,a4)
	move.l	a5,a1
	CALL	rtFreeRequest
	move.l	a6,a1
	CALLEXEC CloseLibrary
	move.l	(filenamebuffpt,pc),a0
	tst.l	(a0)
	beq.w	ende
skipfilerequester

;--------------------------------------
; init file
	move.l	(output,pc),d1
	lea	(filetxt,pc),a0
	move.l	a0,d2
	lea	(filenamept,pc),a0
	move.l	a0,d3
	CALLDOS	VFPrintf

	move.l	#"FORM",d6		;!!!!!
	move.l	#"8SVX",d7		;!!!!!

	move.l	(loadall,pc),d0
	beq.w	.notloadall

	;----LOADALL
	move.l	(filenamept,pc),d1
	move.l	#MODE_OLDFILE,d2
	CALL	Open
	move.l	d0,d5
	beq.w	openerr
	move.l	d5,d1
	move.l	(buff1pt,pc),d2
	move.l	d2,a5
	moveq	#32,d3
	CALL	Read
	move.l	d0,d4		;read error
	move.l	d5,d1
	move.l	(buff2pt,pc),d2
	CALL	ExamineFH
	move.l	d5,d1
	move.l	d0,d5		;examine error
	CALL	Close
	tst.l	d4
	bmi	ifferr		;ENDSTREAMCH
	tst.l	d5
	beq.w	ifferr		;DOSFALSE

	move.l	(buff1pt,pc),a0
	cmp.l	#"XPKF",(a0)
	bne.b	.notxpk
	add	#16,a0
.notxpk	cmp.l	(a0),d6
	bne.w	ifferr
	cmp.l	(8,a0),d7	;FORM 8SVX ?
	bne.w	ifferr

	move.l	(buff2pt,pc),a0
	move.l	(108+16,a0),d5	;fib.Size
	ble.w	ifferr
	move.l	d5,d0
	moveq	#0,d1
	CALLEXEC AllocVec
	move.l	d0,(loadallvec,a4)
	bne.b	.memok
	clr.l	(loadall,a4)
	bra.b	.notloadall

.memok	move.l	(filenamept,pc),d1
	move.l	#MODE_OLDFILE,d2
	CALLDOS	Open
	move.l	d0,d4
	beq.w	openerr
	move.l	d0,d1
	move.l	(loadallvec,pc),d2
	move.l	d5,d3
	CALL	Read
	move.l	d4,d1
	move.l	d0,d4		;read error
	CALL	Close
	cmp.l	d4,d5
	bne.w	readerr
	move.l	#XPK_InBuf,(xpkopentags,a4)
	move.l	(loadallvec,pc),(xpkopentags+4,a4)
	move.l	#XPK_InLen,(xot_inlen,a4)
	move.l	d5,(xot_inlen+4,a4)
.notloadall

	;----not LOADALL
xopen_again
	lea	(smpfh1,pc),a0
	move.l	(filenamept,pc),(mfh_filename,a0)
	bsr	_XOpen
	tst.l	d0
	beq.b	openok
handle_xopen_error
	addq.l	#1,d0
	bne.b	not___1
openerr	lea	(fileerrtxt,pc),a0	;-1
putstr	move.l	a0,d2
	move.l	(output,pc),d1
	CALLDOS	FPutS
	bra.w	err_ende
not___1
	addq.l	#1,d0
	bne.b	not___2
	lea	(xpknam,pc),a1		;-2
	moveq	#2,d0
	CALLEXEC OpenLibrary
	move.l	d0,(xpkbase,a4)
	bne.b	xopen_again
	lea	(xpkliberrtxt,pc),a0
	bra.b	putstr
not___2
	addq.l	#1,d0
	bne.b	not___3
xpkerr	lea	(xpkerrtxt,pc),a0	;-3,  global "print xpk error"
	move.l	a0,d2
	lea	(xpkerrtxtargs,pc),a0
	move.l	a0,d3
	move.l	(output,pc),d1
	CALLDOS	VFPrintf
	bra.w	err_ende
not___3
	addq.l	#1,d0
	bne.w	err_ende
memerr	lea	(memerrtxt,pc),a0	;-4,  global "print mem error"
	bra.b	putstr
openok
	;---check IFF-8SVX
	lea	(smpfh1,pc),a0
	move.l	(buff1pt,pc),d2
	moveq	#12,d3
	bsr	_XRead
	cmp.l	d0,d3
	bne.b	ifferr
	move.l	(buff1pt,pc),a0
	cmp.l	(a0),d6			;!!!!!
	bne.b	ifferr
	cmp.l	(8,a0),d7		;!!!!!
	beq.b	form_ok
ifferr	lea	(ifferrtxt,pc),a0
	bra.w	putstr
form_ok
	;---read VHDR, CHAN, move to beginning of BODY
chunkloop
	lea	(smpfh1,pc),a0
	move.l	(buff1pt,pc),d2
	moveq	#8,d3
	bsr	_XRead
	cmp.l	d0,d3
	bne.b	ifferr
	move.l	(buff1pt,pc),a0

	cmp.l	#"VHDR",(a0)		;---VHDR
	bne.b	.not_vhdr
	move.l	a0,d2
	move.l	(4,a0),d3
	lea	(smpfh1,pc),a0
	bsr	_XRead			;len should be 20
	cmp.l	d0,d3
	bne.b	ifferr
	move.l	(buff1pt,pc),a0
	move	(12,a0),(rate+2,a4)		;vh_SamplesPerSec
	move.b	(15,a0),(compression+1,a4)	;vh_Compression
	bra.b	chunkloop
.not_vhdr
	cmp.l	#"CHAN",(a0)		;---CHAN
	bne.b	.not_chan
	move.l	a0,d2
	move.l	(4,a0),d3
	lea	(smpfh1,pc),a0
	bsr	_XRead			;len should be 4
	cmp.l	d0,d3
	bne.b	ifferr
	move.l	(buff1pt,pc),a0
	cmp.l	#6,(a0)
	bne.b	.not_st
	st	(is_stereo,a4)
.not_st	bra.w	chunkloop
.not_chan
	cmp.l	#"BODY",(a0)		;---BODY
	beq.b	.is_body

	move.l	(4,a0),d2		;---skip other chunks
	addq.l	#1,d2
	lsr.l	#1,d2
	add.l	d2,d2			;round up to even length!!
	moveq	#OFFSET_CURRENT,d3
	lea	(smpfh1,pc),a0
	bsr	_XSeek
	bra.w	chunkloop

.is_body
	move.l	(4,a0),d0
	move.l	d0,(bodyend,a4)
	move.l	d0,(bodylen,a4)
	lea	(smpfh1,pc),a0
	moveq	#0,d2
	moveq	#OFFSET_CURRENT,d3
	bsr	_XSeek
	move.l	d0,(bodystart,a4)
	move.l	d0,(currpos,a4)
	add.l	d0,(bodyend,a4)

;--------------------------------------
; calc some things and print info text
	tst.l	(rate_arg,a4)	;option PLAYBACKRATE?
	bne.b	.pbrate_arg
	move.l	(rate,pc),(rate_arg,a4)
.pbrate_arg
	move.l	(4.w),a1
	move.l	(568,a1),d7	;ex_EClockFrequency
	move.l	d7,d0
	lsl.l	#2,d7
	add.l	d0,d7		;ex_EClockFrequency*5
	move.l	(rate_arg,pc),d6
	move.l	d7,d0
	move.l	d6,d1
	CALLUTIL UDivMod32
	lsr.l	#1,d6
	cmp.l	d6,d1		;remainder
	ble.b	.no_r_u
	addq	#1,d0		;round result up
.no_r_u	move	d0,(rate_amiga,a4)
	move.l	d0,d1
	move.l	d7,d0
	CALL	UDivMod32
	move.l	d0,(rate_play,a4)

	move.l	(bodylen,pc),d0
	tst	(compression,a4)
	beq.b	.nocomp
	add.l	d0,d0
.nocomp	tst	(is_stereo,a4)
	beq.b	.noster
	lsr.l	#1,d0
.noster	move.l	(rate_play,pc),d7
	move.l	d7,d1
	CALL	UDivMod32
	divu	#60,d0
	move	d0,(minutes,a4)
	swap	d0
	move	d0,(seconds,a4)
	move.l	#1000,d0
	CALL	UMult32
	move.l	d7,d1
	CALL	UDivMod32
	move	d0,(millisec,a4)

	lea	(comp0txt,pc),a0	;none
	move	(compression,pc),d0
	beq.b	.cstr
	lea	(comp1txt,pc),a0	;Fibonacci Delta
	subq	#1,d0
	beq.b	.cstr
	lea	(comp2txt,pc),a0	;Exponential Delta
	subq	#1,d0
	beq.b	.cstr
	lea	(comperrtxt,pc),a0	;unknown compression
	bra.w	putstr
.cstr	move.l	a0,(compstr,a4)

	lea	(monotxt,pc),a0
	tst	(is_stereo,a4)
	beq.b	.ststr
	lea	(stereotxt,pc),a0
.ststr	move.l	a0,(stereostr,a4)

	move.l	(bodylen,pc),d0
	moveq	#10,d1
	lsr.l	d1,d0
	move.l	d0,(bodylenKB,a4)

	tst	(smpfh1+mfh_is_xpk,a4)
	beq.b	.not_xpk
	move.l	(smpfh1+mfh_fh,pc),a0
	move.l	(xf_Packer,a0),(packername,a4)
	move.l	(xf_Ratio,a0),(packerratio,a4)
	move.l	(xf_NLen,a0),d0
	moveq	#10,d1
	lsr.l	d1,d0
	move.l	d0,(packerchszKB,a4)
	lea	(xpktxt,pc),a0
	move.l	a0,d2
	lea	(xpktxt_args,pc),a0
	move.l	a0,d3
	move.l	(output,pc),d1
	CALLDOS	VFPrintf
.not_xpk
	lea	(infotxt,pc),a0
	move.l	a0,d2
	lea	(infotxt_args,pc),a0
	move.l	a0,d3
	move.l	(output,pc),d1
	CALLDOS	VFPrintf

	tst.l	(info,a4)
	bne.w	ende

;--------------------------------------
; setup audio
	CALLEXEC CreateMsgPort
	move.l	d0,(msgport,a4)
	beq.b	.audioerr

	move.l	d0,a0		;msg port
	moveq	#62,d0		;ioa_sizeof
	CALL	CreateIORequest
	move.l	d0,(ioreq,a4)
	beq.b	.audioerr

	move.l	d0,a1
	move.b	#127,(9,a1)	;channel pri
	lea	(channelmap,pc),a0
	move.l	a0,(34,a1)	;ioa_data
	moveq	#2,d0
	move.l	d0,(38,a1)	;ioa_length
	lea	(audionam,pc),a0
	moveq	#0,d0		;unit
	moveq	#0,d1		;flags
	CALL	OpenDevice
	tst.l	d0
	bne.b	.audioerr
	st	(audioopen,a4)
	bra.b	.audiook
.audioerr
	lea	(audioerrtxt,pc),a0
	bra.w	putstr
.audiook
qqq1

;--------------------------------------
; fill buffer the first time
	move.l	(bodyend,pc),d0
	sub.l	(bodystart,pc),d0
	move.l	#buffersize*2,d3
	move	(compression,pc),d7
	beq.b	.nocom1
	lsr.l	#1,d3		;half loading size
.nocom1
	tst	(is_stereo,a4)
	beq.w	.noster
	lsr.l	#1,d0
.noster
	cmp.l	d3,d0
	bge.b	.large

	st	(playmode,a4)		;small
	move.l	d0,d3
	tst	d7
	beq.b	.nocom2
	add.l	d0,d0		;double playing size
.nocom2	move.l	d0,(buff1size,a4)
	move.l	d0,(buff2size,a4)
	move.l	(buff1pt,pc),(buff2pt,a4)
	bra.b	.readit
.large	lsr.l	#1,d3			;large
.readit
	lea	(smpfh1,pc),a0
	move.l	(buff1pt,pc),d2
	tst	d7
	beq.b	.nocom3
	move.l	(lbuffpt,pc),d2
.nocom3	bsr	_XRead
	cmp.l	d0,d3
	bne.b	readerr
	add.l	d0,(currpos,a4)
	bra.b	qqq2
readerr
	tst.l	(xpk_error,a4)
	bne.w	xpkerr
	lea	(readerrtxt,pc),a0
	bra.w	putstr
qqq2
	move	d7,d1			;comp_type
	beq.b	.nocom4
	move.l	(lbuffpt,pc),a0		;inbuf
	move.l	(buff1pt,pc),a1		;outbuf
	move	(a0)+,d2		;initial value
	move	d2,(a1)+
	subq.l	#2,d0			;inlen
	bsr	decompress_4bit_delta
	move.b	d0,(initial_value,a4)
.nocom4

;--------------------------------------
; prepare stereo
	tst	(is_stereo,a4)
	beq.w	.no_stereo

	lea	(smpfh2,pc),a0
	move.l	(filenamept,pc),(mfh_filename,a0)
	bsr	_XOpen			;open file a second time
	tst.l	d0
	bne.w	handle_xopen_error

	move.l	#buffersize*2,d0
	moveq	#2,d1			;MEMF_CHIP
	CALLEXEC AllocVec		;alloc second chip buffer
	move.l	d0,(buffspt,a4)
	beq.w	memerr
	move.l	d0,(buffs1pt,a4)
	add.l	#buffersize,d0
	move.l	d0,(buffs2pt,a4)

	lea	(smpfh2,pc),a0
	move.l	(bodylen,pc),d2
	lsr.l	#1,d2
	add.l	(bodystart,pc),d2
	move.l	d2,(stereostart,a4)
	moveq	#OFFSET_CURRENT,d3
	bsr	_XSeek			;seek to half of BODY

	move.l	(buff1size,pc),(buffs1size,a4)
	move.l	(buff2size,pc),(buffs2size,a4)
	tst	(playmode,a4)
	beq.b	.large
	move.l	(buffs1pt,pc),(buffs2pt,a4)
.large
	move.l	(buffs1size,pc),d3
	move.l	(buffs1pt,pc),d2
	move	(compression,pc),d7
	beq.b	.nocom1
	lsr.l	#1,d3		;half loading size
	move.l	(lbuffpt,pc),d2
.nocom1
	lea	(smpfh2,pc),a0
	bsr	_XRead
	cmp.l	d0,d3
	bne.w	readerr

	move	d7,d1			;comp_type
	beq.b	.nocom3
	move.l	(lbuffpt,pc),a0		;inbuf
	move.l	(buffs1pt,pc),a1	;outbuf
	move	(a0)+,d2		;initial value
	move	d2,(a1)+
	subq.l	#2,d0			;inlen
	bsr	decompress_4bit_delta
	move.b	d0,(initial_value2,a4)
.nocom3
.no_stereo
	
;--------------------------------------
; setup timing

	move.l	(smallwindow,pc),d0
	beq.b	.nosmallwin
	sub.l	a0,a0
	CALLINT	LockPubScreen		;lock default public screen
	move.l	d0,(pubscreen,a4)
	beq.w	err_ende
	move.l	d0,a0
	moveq	#0,d0
	move.b	(35,a0),d0	;screen.sc_WBorTop
	move.l	(40,a0),a0	;screen.sc_Font
	moveq	#0,d1
	move	(4,a0),d1	;screen.sc_Font->ta_YSize
	add.l	d1,d0
	addq.l	#1,d0
	move.l	d0,(owt_height+4,a4)
	move.l	(filenamept,pc),(owt_title+4,a4)
	move.l	(pubscreen,pc),(owt_pubscr+4,a4)
	sub.l	a0,a0
	lea	(openwindow_tags,pc),a1
	CALL	OpenWindowTagList
	move.l	d0,(intuiwindow,a4)
	beq.w	err_ende
	move.l	d0,a5
	CALLEXEC Disable
	move.l	(86,a5),a5	;window.wd_UserPort
	move.b	#1,(14,a5)	;window.wd_UserPort->mp_Flags=PA_SOFTINT
	lea	(idcmp_softint,pc),a1
	move.l	a1,(16,a5)	;window.wd_UserPort->mp_SigTask/mp_SoftInt
	CALL	Enable
.nosmallwin

	moveq	#-1,d0
	CALLEXEC AllocSignal
	move.l	d0,(signal,a4)		;own signal
	moveq	#-1,d1
	cmp.l	d0,d1
	beq.w	err_ende

	sub.l	a1,a1
	CALL	FindTask
	move.l	d0,(mytask,a4)		;own task
	move.l	d0,a1
	moveq	#10,d0
	CALL	SetTaskPri
	move.l	d0,(oldpri,a4)

	lea	($dff000),a5
	move	#$780,d0
	move	d0,(intena,a5)
	move	d0,(intreq,a5)		;audio irqs off

	moveq	#7,d0		;INTB_AUD0
	lea	(int_struct,pc),a1
	CALL	SetIntVector
	move.l	d0,(oldlevel4,a4)

	move	#$8080,d0
	move	d0,(intena,a5)
	move	d0,(intreq,a5)		;audio irq 0 on


;--------------------------------------
mainloop
	clr	(read_busy,a4)
	move.l	#$0000f000,d7	;break signals
	move.l	(signal,pc),d1	;signalnumber
	moveq	#1,d0
	lsl.l	d1,d0
	or.l	d7,d0		;signalmask
	CALLEXEC Wait
	move.l	d0,d6
	and.l	d7,d0
	beq.b	.nobreak

	rol	#4,d0		;lsr #12
	moveq	#8,d1		;CTRL-F
	and	d0,d1
	beq.b	.no_ctrlf
	lea	($bfe001),a0
	lea	(filter,pc),a1
	tst.l	(a1)
	bne.b	.filter_is_on
	st	(a1)
	bclr	#1,(a0)		;filter on
	bra.b	.no_ctrlf
.filter_is_on
	clr.l	(a1)
	bset	#1,(a0)		;filter off
.no_ctrlf
	moveq	#4,d1		;CTRL-E
	and	d0,d1
	beq.b	.no_ctrle
	clr.l	(repeat,a4)	;repeat mode off
.no_ctrle
	moveq	#2,d1		;CTRL-D
	and	d0,d1
	beq.b	.no_ctrld
	st	(repeat,a4)	;repeat mode on
.no_ctrld
	moveq	#1,d1		;CTRL-C
	and	d0,d1
	bne.w	ende
	not.l	d7
	and.l	d7,d6
	beq.b	mainloop	;no other signal (for loading)
.nobreak
	tst	(playmode,a4)
	bne.b	mainloop	;small sample

	moveq	#0,d7		;!!!!
	st	(read_busy,a4)

	move.l	(bodyend,pc),d0
	tst	(is_stereo,a4)
	beq.b	.noste1
	lsr.l	#1,d0
.noste1
	sub.l	(currpos,pc),d0
	bmi.w	readerr
	bgt.b	.noseek

	;---seek to start
	lea	(oneshot_last,pc),a0
	st	(a0)
	tst.l	(repeat,a4)
	beq.w	mainloop
	clr	(a0)

	lea	(smpfh1,pc),a0
	move.l	(bodystart,pc),d2
	move.l	d2,(currpos,a4)
	moveq	#OFFSET_BEGINNING,d3
	bsr	_XSeek			;seek to start of BODY
	tst.l	d0
	bmi.w	readerr

	tst	(is_stereo,a4)
	beq.b	.nost
	lea	(smpfh2,pc),a0
	move.l	(stereostart,pc),d2
	moveq	#OFFSET_BEGINNING,d3
	bsr	_XSeek			;seek to half of BODY
	tst.l	d0
	bmi.w	readerr
.nost
	move.l	#buffersize,d0
	moveq	#1,d7		;!!!!

	;---read and decompress
.noseek	move.l	#buffersize,d3
	move.l	(buff1pt,pc),d2
	tst	(compression,a4)
	beq.b	.nocom1
	lsr.l	#1,d3
	move.l	(lbuffpt,pc),d2
.nocom1
	cmp.l	d0,d3
	ble.b	.read
	move.l	d0,d3
.read	lea	(smpfh1,pc),a0
	bsr	_XRead
	cmp.l	d0,d3
	bne.w	readerr
	add.l	d0,(currpos,a4)
	move.l	d0,(buff1size,a4)
	move	(compression,pc),d1	;comp_type
	beq.b	.check_stereo
	add.l	d0,(buff1size,a4)
	move.l	(lbuffpt,pc),a0		;inbuf
	move.l	(buff1pt,pc),a1		;outbuf
	move.b	(initial_value,pc),d2
	tst.l	d7		;!!!!
	beq.b	.not_start
	move	(a0)+,d2		;initial value
	move	d2,(a1)+
	subq.l	#2,d0			;inlen
.not_start
	bsr	decompress_4bit_delta
	move.b	d0,(initial_value,a4)

.check_stereo
	tst	(is_stereo,a4)
	beq.w	mainloop
	lea	(smpfh2,pc),a0
	move.l	(buff1size,pc),d3	;len from other side
	move.l	(buffs1pt,pc),d2
	tst	(compression,a4)
	beq.b	.nocom2
	lsr.l	#1,d3
	move.l	(lbuffpt,pc),d2
.nocom2	bsr	_XRead
	cmp.l	d0,d3
	bne.w	readerr
	move.l	d0,(buffs1size,a4)
	move	(compression,pc),d1	;comp_type
	beq.w	mainloop
	add.l	d0,(buffs1size,a4)
	move.l	(lbuffpt,pc),a0		;inbuf
	move.l	(buffs1pt,pc),a1	;outbuf
	move.b	(initial_value2,pc),d2
	tst.l	d7		;!!!!
	beq.b	.not_start2
	move	(a0)+,d2		;initial value
	move	d2,(a1)+
	subq.l	#2,d0			;inlen
.not_start2
	bsr	decompress_4bit_delta
	move.b	d0,(initial_value2,a4)
	bra	mainloop






;--------------------------------------
; some global routines


check_idcmp	;(called from MsgPort-SoftInt)
	movem.l	d1-a6,-(a7)
	move.l	(intuiwindow,pc),a0
	move.l	(86,a0),a0	;window.wd_UserPort
	CALLEXEC GetMsg
	tst.l	d0
	beq.b	.exit
	move.l	d0,a5
	move.l	(20,a5),d0	;msg.Class
	move	#$200,d1
	and	d0,d1
	beq.b	.notclosegadget
	moveq	#1,d0
	ror	#4,d0			;Ctrl-C
	move.l	(mytask,pc),a1
	CALL	Signal
.notclosegadget
	move.l	a5,a1
	CALL	ReplyMsg
.exit	movem.l	(a7)+,d1-a6
	moveq	#0,d0
	rts




wait_hsync
; d0=number_of_syncs   a5=$dff000
.outer	move.b	(6,a5),d1
.inner	cmp.b	(6,a5),d1
	beq.b	.inner
	subq	#1,d0
	bgt.b	.outer
	rts




mylevel4	;-----------
	movem.l	d1-a6,-(a7)
	lea	($dff000),a5
	lea	(first_,pc),a4

	lea	($bfe001),a0
	tst.l	(filter,a4)
	beq.b	.filteroff
	bclr	#1,(a0)		;filter on
	bra.b	.skipfilter
.filteroff
	bset	#1,(a0)		;filter off
.skipfilter
	move	#$00ff,(adkcon,a5)
	move	(rate_amiga,pc),d0
	move	d0,(aud0per,a5)
	move	d0,(aud1per,a5)
	move	d0,(aud2per,a5)
	move	d0,(aud3per,a5)

	moveq	#64,d0
	tst	(read_busy,a4)
	beq.b	.volume
	moveq	#0,d0
.volume	move	d0,(aud0vol,a5)
	move	d0,(aud1vol,a5)
	move	d0,(aud2vol,a5)
	move	d0,(aud3vol,a5)
	tst	d0
	beq.w	.end

	move	#$000f,(dmacon,a5)	;dma off
	move.l	(buff1pt,pc),d0
	move.l	d0,d1
	move.l	(buff1size,pc),d2
	move.l	d2,d3
	lsr.l	#1,d2
	tst	(is_stereo,a4)
	beq.b	.noster
	move.l	(buffs1pt,pc),d1
	move.l	(buffs1size,pc),d3
.noster	lsr.l	#1,d3
	move.l	d0,(aud0lch,a5)	
	move.l	d1,(aud1lch,a5)
	move.l	d1,(aud2lch,a5)
	move.l	d0,(aud3lch,a5)
	move	d2,(aud0len,a5)
	move	d3,(aud1len,a5)
	move	d3,(aud2len,a5)
	move	d2,(aud3len,a5)

	moveq	#8,d0
	bsr.w	wait_hsync
	move	#$800f,(dmacon,a5)	;dma on
	moveq	#8,d0
	bsr.w	wait_hsync

	move.l	(buff1pt,pc),d0
	move.l	(buff2pt,pc),(buff1pt,a4)
	move.l	d0,(buff2pt,a4)
	move.l	(buff1size,pc),d0
	move.l	(buff2size,pc),(buff1size,a4)
	move.l	d0,(buff2size,a4)

	move.l	(buffs1pt,pc),d0
	move.l	(buffs2pt,pc),(buffs1pt,a4)
	move.l	d0,(buffs2pt,a4)
	move.l	(buffs1size,pc),d0
	move.l	(buffs2size,pc),(buffs1size,a4)
	move.l	d0,(buffs2size,a4)

	move.l	(repeat,pc),d7		;loop
	tst	(playmode,a4)
	beq.b	.large

	tst	(firstirq,a4)
	bne.b	.notfirst
	st	(firstirq,a4)
	bra.b	.end
.notfirst
	moveq	#1,d0
	ror	#4,d0
	tst.l	d7			;loop?
	beq.b	.do_signal		;no -> break
	bra.b	.end			;yes -> no signal
.large
	move.l	(signal,pc),d1
	moveq	#1,d0
	lsl.l	d1,d0
	tst	(oneshot_last,a4)
	beq.b	.do_signal
	tst.l	d7
	bne.b	.do_signal
	moveq	#1,d0
	ror	#4,d0			;break signals

.do_signal
	move.l	(mytask,pc),a1
	CALLEXEC Signal
.end
	move	#$780,(intreq,a5)
	movem.l	(a7)+,d1-a6
	moveq	#0,d0
	nop
	rts



;***Decompress_4bit_Delta*******************************************
; parameters:
;  d0 - inlen (must be EVEN)
;  d1 - comp_type (1 or 2)
;  d2 - initial value
;  a0 - inbuff
;  a1 - outbuff
; result:
;  d0 - last value (initial value for next call)
decompress_4bit_delta
	movem.l	d1-a6,-(a7)
	lea	(fib_tab,pc),a2
	subq.b	#1,d1
	beq.b	.fib
	lea	(exp_tab,pc),a2
.fib	moveq	#0,d1
	moveq	#$0f,d5
.loop	move.b	(a0)+,d1
	move.l	d1,d3
	lsr	#4,d1
	add.b	(a2,d1.l),d2
	move.b	d2,d4
	lsl	#8,d4
	and	d5,d3
	add.b	(a2,d3.l),d2
	move.b	d2,d4
	swap	d4
	move.b	(a0)+,d1
	move.l	d1,d3
	lsr	#4,d1
	add.b	(a2,d1.l),d2
	move.b	d2,d4
	lsl	#8,d4
	and	d5,d3
	add.b	(a2,d3.l),d2
	move.b	d2,d4
	move.l	d4,(a1)+	;LONG writes to the fucking slow ChipRAM
	subq.l	#2,d0		;inlen is EVEN
	bgt.b	.loop
	move.l	d2,d0
	movem.l	(a7)+,d1-a6
	rts
fib_tab	dc.b	-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21
exp_tab	dc.b	-128,-64,-32,-16,-8,-4,-2,-1,0,1,2,4,8,16,32,64




;***_XOpen**********************************************************
; parameters:
;  a0 - myFH (mfh_filename must have been initialized!)
; result:
;  d0 - 0=OK, other=ERROR
; 
; -DOSBase must be valid
; -if file starts with "XPKF" and XPKBase=NULL
;    -> result=-2 -> call _XOpen again when xpkmaster.library was opened
_xopen
	movem.l	d1-a6,-(a7)
	move.l	a0,a5

	moveq	#mfh_SIZEOF-5,d0	;don't clear mfh_filename !!
.clrloo	clr.b	(a0)+
	dbf	d0,.clrloo

	move.l	(loadall,pc),d0
	beq.b	.notloadall
	move.l	(loadallvec,pc),a0
	cmp.l	#"XPKF",(a0)
	beq.b	.xla
	bra.w	.end_ok
.notloadall

	move.l	(mfh_filename,a5),d1
	move.l	#MODE_OLDFILE,d2
	CALLDOS	Open
	move.l	d0,(a5)
	bne.b	.open_ok
	moveq	#-1,d0			;-1=DOS_OPEN_ERROR
	bra.w	.exit
.open_ok
	move.l	d0,d1
	lea	(.xpkf_test,pc),a0
	move.l	a0,d2
	moveq	#4,d3
	CALL	Read

	move.l	(.xpkf_test,pc),d0
	cmp.l	#"XPKF",d0
	beq.b	.is_xpk
	move.l	(a5),d1
	moveq	#0,d2
	moveq	#OFFSET_BEGINNING,d3
	CALL	Seek
	bra.b	.end_ok

.is_xpk
	move.l	(a5),d1
	CALL	Close
	clr.l	(a5)
.xla	move.l	(xpkbase,pc),d0
	bne.b	.xpklib_ok
	moveq	#-2,d0			;-2=XPKMASTER_NOT_OPEN
	bra.b	.exit
.xpklib_ok
	move.l	d0,a6
	move.l	a5,a0
	lea	(xpkopentags,pc),a1
	tst.l	(loadall,a4)
	bne.b	.la
	move.l	(mfh_filename,a5),(4,a1)
.la	CALL	XpkOpen
	move.l	d0,(xpk_error,a4)
	beq.b	.xpkopen_ok
	moveq	#-3,d0			;-3=XPK_ERROR
	bra.b	.exit
.xpkopen_ok
	st	(mfh_is_xpk,a5)
	move.l	(a5),a0
	move.l	(xf_NLen,a0),d0
	move.l	d0,(mfh_xbuffsize,a5)
	add.l	#XPK_MARGIN,d0
	moveq	#0,d1
	CALLEXEC AllocVec
	move.l	d0,(mfh_xbuff,a5)
	bne.b	.end_ok
	moveq	#-4,d0			;-4=MEM_ERROR
	bra.b	.exit

.end_ok	moveq	#0,d0
.exit	movem.l	(a7)+,d1-a6
	rts

.xpkf_test	dc.l	0
xpkopentags	dc.l	XPK_InName,0	;to be patched!
		dc.l	XPK_GetError,xpkerrormsg
		dc.l	XPK_ShortError,-1
xot_inlen	dc.l	0,0,0




;***_XRead**********************************************************
; parameters:
;  a0 - myFH
;  d2 - buffer
;  d3 - len
; result:
;  d0 - bytes read (0=EOF, <0=ERROR)
_xread
	movem.l	d1-a6,-(a7)
	move.l	a0,a5		;myFH
	tst	(mfh_is_xpk,a5)
	bne.b	.is_xpk
	move.l	(loadall,pc),d0
	beq.b	.nla
	move.l	(mfh_filepos,a5),a0
	add.l	(loadallvec,pc),a0
	move.l	d2,a1
	move.l	d3,d0
	add.l	d0,(mfh_filepos,a5)
	CALLEXEC CopyMem
	move.l	d3,d0
	bra.b	.exit
.nla	move.l	(a0),d1		;mfh_fh
	CALLDOS	Read
.exit	movem.l	(a7)+,d1-a6
	rts
.is_xpk	move.l	d2,d6	;buf
	move.l	d3,d7	;len
	moveq	#0,d5	;already read
.xloop	tst.l	d7
	bgt.b	.go_on
.eof	move.l	d5,d0
	add.l	d0,(mfh_filepos,a5)
	bra.b	.exit
.go_on	move.l	(mfh_buffcontent,a5),d0
	ble.b	.read
	sub.l	d0,d7
	bge.b	.copy
	add.l	d0,d7
	move.l	d7,d0
	moveq	#0,d7
.copy	move.l	(mfh_buffpos,a5),a0
	move.l	d6,a1
	add.l	d0,d5
	add.l	d0,(mfh_buffpos,a5)
	add.l	d0,d6
	sub.l	d0,(mfh_buffcontent,a5)
	CALLEXEC CopyMem
	bra.b	.xloop
.read	move.l	(a5),a0		;mfh_fh
	move.l	(mfh_xbuff,a5),a1
	move.l	a1,(mfh_buffpos,a5)
	move.l	(mfh_xbuffsize,a5),d0
	CALLXPK	XpkRead
	move.l	d0,(mfh_buffcontent,a5)
	beq.b	.eof
	bgt.b	.xloop
	move.l	d0,(xpk_error,a4)
	bra.b	.exit


;***_XSeek**********************************************************
; parameters:
;  a0 - myFH
;  d2 - newpos (only positive numbers (forward seeking) supported)
;  d3 - offset (only OFFSET_BEGINNING and OFFSET_CURRENT supported)
; result:
;  d0 - oldpos (<0=ERROR)
_xseek
	movem.l	d1-a6,-(a7)
	move.l	a0,a5			;myFH
	tst	(mfh_is_xpk,a5)
	bne.b	.is_xpk
	move.l	(loadall,pc),d0
	beq.b	.nla
	move.l	(mfh_filepos,a5),d0	;oldpos
	tst.l	d3
	beq.b	.offcur
	clr.l	(mfh_filepos,a5)
.offcur	add.l	d2,(mfh_filepos,a5)
	bra.b	.exit
.nla	move.l	(a5),d1
	CALLDOS	Seek
.exit	movem.l	(a7)+,d1-a6
	rts
.is_xpk	move.l	d2,d6			;newpos
	move.l	(mfh_filepos,a5),d7	;oldpos
	tst.l	d3			;offset
	beq.b	.seek_loop		;OFFSET_CURRENT

	move.l	(a5),a0
	CALLXPK	XpkClose
	clr.l	(a5)
	clr.l	(mfh_filepos,a5)
	clr.l	(mfh_buffcontent,a5)
	move.l	a5,a0
	lea	(xpkopentags,pc),a1
	tst.l	(loadall,a4)
	bne.b	.la
	move.l	(mfh_filename,a5),(4,a1)
.la	CALL	XpkOpen			;"seek" to beginning
	move.l	d0,(xpk_error,a4)
	beq.b	.seek_loop
	moveq	#-1,d0			;ERROR
	bra.b	.exit
.seek_loop
	tst.l	d6			;newpos
	bgt.b	.do_seek
	move.l	d7,d0			;return old position
	bra.b	.exit
.do_seek
	move.l	(mfh_buffcontent,a5),d0
	ble.b	.read
	cmp.l	d6,d0
	bmi.b	.not_enough
	sub.l	d6,(mfh_buffcontent,a5)
	add.l	d6,(mfh_buffpos,a5)
	add.l	d6,(mfh_filepos,a5)
	moveq	#0,d6
	bra.b	.seek_loop
.not_enough
	sub.l	d0,d6
	add.l	d0,(mfh_filepos,a5)
.read
	move.l	(a5),a0
	move.l	(mfh_xbuff,a5),a1
	move.l	a1,(mfh_buffpos,a5)
	move.l	(mfh_xbuffsize,a5),d0
	CALLXPK	XpkRead
	move.l	d0,(mfh_buffcontent,a5)
	beq.b	.eof
	bgt.b	.seek_loop
	move.l	d0,(xpk_error,a4)
	bra.w	.exit
.eof	moveq	#-1,d0			;ERROR (EOF)
	bra.w	.exit



;***_XClose*********************************************************
; parameters:
;  a0 - myFH (should be safe to call several times unlike DOS/Close()!!)
_xclose
	movem.l	d1-a6,-(a7)
	move.l	a0,a5

	move.l	(a5),d1
	beq.b	.no_fh
	clr.l	(a5)
	tst	(mfh_is_xpk,a5)
	bne.b	.is_xpk
	CALLDOS	Close
	bra.b	.no_fh
.is_xpk	move.l	(xpkbase,pc),d0
	beq.b	.no_fh
	move.l	d0,a6
	move.l	d1,a0
	CALL	XpkClose
.no_fh
	lea	(mfh_xbuff,a5),a0
	move.l	(a0),d0
	beq.b	.no_xbuff
	clr.l	(a0)
	move.l	d0,a1
	CALLEXEC FreeVec
.no_xbuff
	movem.l	(a7)+,d1-a6
	rts




;--------------------------------------
; exit
ende
	tst	(audioopen,a4)
	beq.b	.noaudio
	lea	($dff000),a5
	move	#$780,d0
	move	d0,(intena,a5)
	moveq	#0,d0
	move	d0,(aud0vol,a5)
	move	d0,(aud1vol,a5)
	move	d0,(aud2vol,a5)
	move	d0,(aud3vol,a5)
	move	#$000f,(dmacon,a5)
	move.l	(4.w),a6
	move.l	(oldlevel4,pc),d0
	beq.b	.noint
	moveq	#7,d0		;INTB_AUD0
	move.l	(oldlevel4,pc),a1
	CALL	SetIntVector
.noint	move.l	(ioreq,pc),a1
	CALL	CloseDevice
.noaudio
	move.l	(mytask,pc),d0
	beq.b	.nopri
	move.l	d0,a1
	move.l	(oldpri,pc),d0
	CALLEXEC SetTaskPri
.nopri
	move.l	(ioreq,pc),d0
	beq.b	.noioreq
	move.l	d0,a0
	CALLEXEC DeleteIORequest
.noioreq
	move.l	(msgport,pc),d0
	beq.b	.nomsgport
	move.l	d0,a0
	CALLEXEC DeleteMsgPort
.nomsgport

	move.l	(signal,pc),d0
	moveq	#-1,d1
	cmp.l	d0,d1
	beq.b	.nosignal
	CALLEXEC FreeSignal
.nosignal
	move.l	(rdargs,pc),d1
	beq.b	.noargs
	CALLDOS	FreeArgs
.noargs

	lea	(smpfh1,pc),a0
	bsr	_XClose
	lea	(smpfh2,pc),a0
	bsr	_XClose

	move.l	(xpkbase,pc),d0
	beq.b	.noxpklib
	move.l	d0,a1
	CALLEXEC CloseLibrary
.noxpklib
	move.l	(utilitybase,pc),d0
	beq.b	.noutillib
	move.l	d0,a1
	CALLEXEC CloseLibrary
.noutillib
	move.l	(iconbase,pc),d0
	beq.b	.noiconlib
	move.l	d0,a1
	CALLEXEC CloseLibrary
.noiconlib
	move.l	(buffspt,pc),d0
	beq.b	.nostereobuff
	move.l	d0,a1
	CALLEXEC FreeVec
.nostereobuff
	move.l	(loadallvec,pc),d0
	beq.b	.notloadall
	move.l	d0,a1
	CALLEXEC FreeVec
.notloadall
	move.l	(oldcurrdir,pc),d1
	beq.b	.nocurrdir
	CALLDOS	CurrentDir
.nocurrdir
	move.l	(conwindow,pc),d7
	beq.b	.nocon
	move.l	d7,d1
	lea	(anykeytxt,pc),a0
	move.l	a0,d2
	CALLDOS	FPutS
	move.l	d7,d1
	CALL	FGetC
	move.l	d7,d1
	CALL	Close
.nocon
	move.l	(intuiwindow,pc),d0
	beq.b	.nowin
	move.l	d0,a0
	CALLINT	CloseWindow
.nowin
	move.l	(pubscreen,pc),d0
	beq.b	.nopubscr
	sub.l	a0,a0
	move.l	d0,a1
	CALLINT	UnlockPubScreen
.nopubscr
	move.l	(wbmsg,pc),d0
	beq.b	.nowbmsg
	move.l	d0,a1
	CALLEXEC ReplyMsg
.nowbmsg
	move.l	(error,pc),d0
	rts
err_ende
	lea	(error+2,pc),a0
	move	#10,(a0)
	bra.w	ende



;--------------------------------------
; data area

dosnam		dc.b	"dos.library",0
utilnam		dc.b	"utility.library",0
iconnam		dc.b	"icon.library",0
xpknam		dc.b	"xpkmaster.library",0
rtnam		dc.b	"reqtools.library",0
intuinam	dc.b	"intuition.library",0
audionam	dc.b	"audio.device",0
connam		dc.b	"CON:15/15/600/150/ PSMP window",0
filereqtitle	dc.b	"PSMP: select IFF-8SVX file",0,0
filereqtags	dc.l	0
dosbase		dc.l	0
utilitybase	dc.l	0
iconbase	dc.l	0
xpkbase		dc.l	0
intuitionbase	dc.l	0
read_busy	dc	0
is_stereo	dc	0
smpfh1		blk.b	mfh_SIZEOF,0
smpfh2		blk.b	mfh_SIZEOF,0
oldlevel4	dc.l	0
wbmsg		dc.l	0
output		dc.l	0
conwindow	dc.l	0
oldcurrdir	dc.l	0
pubscreen	dc.l	0
intuiwindow	dc.l	0
loadallvec	dc.l	0

tt_rate		dc.b	"PLAYBACKRATE",0
tt_filter	dc.b	"FILTER",0
tt_repeat	dc.b	"REPEAT",0
tt_info		dc.b	"INFO",0
tt_smallwin	dc.b	"SMALLWINDOW",0
tt_loadall	dc.b	"LOADALL",0
rdargs		dc.l	0
template	dc.b	"FILE,P=PLAYBACKRATE/K/N,F=FILTER/S,R=REPEAT/S,I=INFO/S,S=SMALLWINDOW/S,L=LOADALL/S",0,0
filenamept	dc.l	0
playbackrate	dc.l	0
filter		dc.l	0
repeat		dc.l	0
info		dc.l	0
smallwindow	dc.l	0
loadall		dc.l	0

idcmp_softint	dc.l	0,0		;is_Node ln_Succ, ln_Pred
		dc.b	2,0		;is_Node ln_Type, ln_Pri
		dc.l	0		;is_Node ln_Name
		dc.l	0,check_idcmp	;is_Data, is_Code

int_name	dc.b	"PSMP_AUDIO",0,0
int_struct	dc.l	0,0		;is_Node ln_Succ, ln_Pred
		dc.b	2,0		;is_Node ln_Type, ln_Pri
		dc.l	int_name	;is_Node ln_Name
		dc.l	0,mylevel4	;is_Data, is_Code

openwindow_tags	dc.l	$80000064,0	;WA_Left
		dc.l	$80000065,15	;WA_Top
		dc.l	$80000066,1024	;WA_Width
owt_height	dc.l	$80000067,0	;WA_Height (to be patched)
		dc.l	$8000006a,$200	;WA_IDCMP: IDCMP_CloseWindow
		dc.l	$8000006b	;WA_Flags:
			;CLOSEGADGET+DRAGBAR+DEPTHGADET+NOCAREREFRESH+RMBTRAP+SMARTREFRESH
		dc.l	8+2+4+$20000+$10000+0
owt_title	dc.l	$8000006e,0	;WA_Title (to be patched)
		dc.l	$8000006f,vstr+6;WA_ScreenTitle
owt_pubscr	dc.l	$80000079,0	;WA_PubScreen (to be patched)
		dc.l	$80000090,-1	;WA_AutoAdjust
		dc.l	TAG_DONE



packername	dc.b	0,0,0,0,0
xpkerrormsg	ds.b	XPKERRMSGSIZE+1

xpkerrtxtargs
xpk_error	dc.l	0
		dc.l	xpkerrormsg

xpktxt_args
packernamept	dc.l	packername
packerratio	dc.l	0
packerchszKB	dc.l	0

infotxt_args
bodylenKB	dc.l	0
rate		dc.l	0
stereostr	dc.l	0
compression	dc	0
compstr		dc.l	0
rate_arg	dc.l	0
rate_amiga	dc	0
rate_play	dc.l	0
minutes		dc	0
seconds		dc	0
millisec	dc	0

stereostart	dc.l	0
bodystart	dc.l	0
currpos		dc.l	0
bodylen		dc.l	0
bodyend		dc.l	0

error		dc.l	0
buff1pt		dc.l	buff1
buff2pt		dc.l	buff2
buff1size	dc.l	buffersize
buff2size	dc.l	buffersize
buffspt		dc.l	0
buffs1pt	dc.l	0
buffs2pt	dc.l	0
buffs1size	dc.l	buffersize
buffs2size	dc.l	buffersize
lbuffpt		dc.l	lbuff
filenamebuffpt	dc.l	filenam

oldpri		dc.l	0
mytask		dc.l	0
signal		dc.l	-1
msgport		dc.l	0
ioreq		dc.l	0
channelmap	dc	$0f0f
audioopen	dc	0
oneshot_last	dc	0
firstirq	dc	0
playmode	dc	0	;0=large ( > buffersize*2 )
				;else small ( < buffersize*2 )
initial_value	dc.b	0
initial_value2	dc.b	0


vstr		dc.b	"$VER: PSMP 0.7 (Sat 16-Nov-96)",0
maintxt		dc.b	27,"[1mPSMP 0.7 (Sat 16-Nov-96) by Smack/Infect",27,"[0m",10,0
filetxt		dc.b	" file......%s",10,0
xpktxt		dc.b	" XPK.......%s, %ld%% gain, chunksize %ld KB",10,0
infotxt		dc.b	" features..%ld KB, %ld Hz, %s, compression %d (%s)",10
		dc.b	" rate......%ld Hz -> period %d -> %ld Hz",10
		dc.b	" duration..%d min %02d.%03d sec",10,0
comp0txt	dc.b	"none",0
comp1txt	dc.b	"Fibonacci Delta",0
comp2txt	dc.b	"Exponential Delta",0
monotxt		dc.b	"mono",0
stereotxt	dc.b	"stereo",0
fileerrtxt	dc.b	"** can't open file.",10,0
ifferrtxt	dc.b	"** not an IFF-8SVX sample.",10,0
audioerrtxt	dc.b	"** can't allocate audio channels.",10,0
readerrtxt	dc.b	"** read error.",10,0
comperrtxt	dc.b	"** unknown compression.",10,0
xpkerrtxt	dc.b	"** XPK error %ld: %s",10,0
xpkliberrtxt	dc.b	"** can't open xpkmaster.library.",10,0
memerrtxt	dc.b	"** not enough memory.",10,0
anykeytxt	dc.b	10,"press return to continue.",0

	section	bbbb,bss_c
buff1	ds.b	buffersize
buff2	ds.b	buffersize


	section	cccc,bss
filenam	ds.b	1024
lbuff	ds.b	buffersize
