; SNDH Parx module
; Guillaume Tello
; guillaume.tello@orange.fr
; january 2023
;
; from the original work of :
;
; SNDH testprogram
; 
; January 4, 2000
; Anders Eriksson / Odd Skancke
; ae@dhs.nu         ozk@atari.org

MAX_HEADER:	equ	200

GEMDOS MACRO    ; fn,pile
   move #\1,-(sp)
   trap #1
   if \2<=8
      addq.l #\2,sp
   else
      add.w #\2,sp
   endif
   ENDM

		section	text
		
	dc.b "READ_SND"	; identifiant module de lecture de son
	dc.b "SNDH"			; type de son support
	dc.w $0400			; type (4 pour ncessit de vider le cache aprs MODPAL) et 0 pour "chargement total"
	dc.b "SNDH_ICE"	; nom court
	dc.w 100				; version 1.00
	dc.b "SNDH (un/packed) sound player ",0,0	; long name
	bra modinfo
	bra modpal
	bra modexe

; sur la pile RTS/4:sndb.l
; en entre seul le handle est fourni
; en sortie remplit taille et taille dcompresse
; ainsi que le type de fichier
; renvoie 0,1 ou 2.

modinfo:
	move.l 4(sp),d0	; le sndb
	movem.l d1-d3/a0-a4,-(sp)
	move.l d0,a4
	move.l 12(a4),d0	; handle
	bsr fseek1			; va  la fin !
	move.l d0,4(a4)	; stocke la taille
	move.l 12(a4),d0	; reprend le handle
	bsr fseek0			; ramne au dbut
	lea buffer(pc),a3	; zone
	moveq #16,d3		; taille  lire
	move.l	a3,-(sp)
	move.l	d3,-(sp)
	move.w	d0,-(sp)
	GEMDOS 63,12
	cmp.l d3,d0
	bne.s .inconnu
	cmp.l #'ICE!',(a3)
	beq.s .packed
	cmp.l #'SNDH',12(a3)
	bne.s .inconnu
	move.l 12(a3),(a4)	; le type SNDH
	move.l 4(a4),8(a4)	; renvoie la taille originale comme taille dcompresse
	moveq #2,d0				; son nom compress
	bra.s .exit
.packed:
	move.l 8(a3),8(a4)	; taille dcompresse
	move.l (a3),(a4)		; le type ICE!
	moveq #1,d0				; compress
	bra.s .exit
.inconnu:
	moveq #0,d0
	move.l d0,(a4)			; type zro, inconnu
.exit:
	movem.l (sp)+,d1-d3/a0-a4
	rts	

; d0 = handle, ramne au dbut
fseek0:
	movem.l d0-d2/a0-a2,-(sp)
	moveq #0,d1
	move d1,-(sp)
	move d0,-(sp)
	move.l d1,-(sp)
	GEMDOS 66,10
	movem.l (sp)+,d0-d2/a0-a2
	rts	

; d0 = handle, va  la fin
fseek1:
	movem.l d1-d2/a0-a2,-(sp)
	moveq #0,d1
	move #2,-(sp)
	move d0,-(sp)
	move.l d1,-(sp)
	GEMDOS 66,10
	movem.l (sp)+,d1-d2/a0-a2
	rts	

cherche_long:	movea.l	a4,a2
		swap d0
		move.w	#MAX_HEADER-1,d0
		move.l	(a2)+,d1
.search_sndh:	cmp.l	d2,d1
		beq.s	.wow
		lsl.l	#8,d1
		move.b	(a2)+,d1
		dbra	d0,.search_sndh
		lea .vide(pc),a2
.wow:
		clr d0
		swap d0
		rts
.vide: dc.b 0,0

cherche_mot:	movea.l	a4,a2
		swap d0
		move.w	#MAX_HEADER-1,d0
		move.w	(a2)+,d1
.search_sndh:	cmp.w	d2,d1
		beq.s	.wow
		lsl.w	#8,d1
		move.b	(a2)+,d1
		dbra	d0,.search_sndh
		moveq	#0,d2
		bra.s .exit
.wow:	moveq #0,d2	
		move.b	(a2)+,d2
		lsl.w	#8,d2
		move.b	(a2)+,d2
.exit:
		clr d0
		swap d0
		tst.l d2
		rts

; pile RTS/4:sndb/8:adrsource/12:adrdest	
modpal:
	movem.l d1-d2/a0-a4,-(sp)	; 28 octets de dcalage
	move.l 4+28(sp),a3
	move.l 12(a3),d0			; handle
	bsr fseek0					; revient au dbut
	move.l 8+28(sp),a4
	move.l a4,-(sp)			; adresse source
	move.l 4(a3),-(sp)		; taille source
	move.w d0,-(sp)			; handle
	GEMDOS 63,12				; lire tout le fichier
	moveq #2,d0					; par dfaut, retour OK non compress
	cmp.l #'ICE!',(a4)		; compress?
	bne.s .unpacked
	move.l a4,a0				; source
	move.l 12+28(sp),a1		; dest
	move.l a1,a4				; pour la suite
	bsr ice_decrunch
	moveq #1,d0					; a t dcompress
.unpacked:
	move.l a4,16(a3)			; dans le mfdb (adresse donnes dcomp)
	cmp.l #'SNDH',12(a4)		; au final on doit avoir un SNDH
	bne.s .erreur
	move.l #'TITL',d2
	bsr cherche_long
	lea 60(a3),a0
	bsr.s .copystring			; met le titre
	move.l #'COMM',d2		
	bsr cherche_long
	lea 92(a3),a0
	bsr.s .copystring			; puis l'auteur
	move.w #'##',d2
	bsr cherche_mot
	bne.s .ok
	move #'01',d2
.ok:
	sub #'00',d2
	move d2,d1
	lsr #8,d1
	muls #10,d1
	and #$ff,d2
	add.l d1,d2
	move.l d2,20(a3)			; stocke le nombre de morceaux, 1 par dfaut
	bra.s .out
.erreur:
	moveq #0,d0					; si ce n'est pas le cas, erreur.
.out:
	movem.l (sp)+,d1-d2/a0-a4
	rts
.copystring:
	moveq #30,d2
.cs0:
	move.b (a2)+,(a0)+
	dbeq d2,.cs0
	clr.b (a0)
	rts

; pile RTS/4:sndb/8:code commande
modexe:	
	movem.l d1/a0/a3,-(sp)	; dcalage 12
	move.l 4+12(sp),a3		; sndb
	move.l 16(a3),a0			; adresse morceau
	moveq #-2,d0
	cmp.l #'SNDH',12(a0)
	bne.s .exit
	bsr set_super
	move.l	#'_SND',d1
	bsr	find_cookie
	bsr set_user
	tst.l	d0
	bmi.s	.ok					; par dfaut, pas de cookie, on suppose que a marche
	moveq #-1,d0
	btst #0,7(a0)				; le bit 0 pour le Yamaha
	beq.s .exit					; non prsent !
.ok:
	move.l 8+12(sp),d0		; commande !
	beq.s .stop
	bmi.s .status
	move.l d0,24(a3)			; morceau en cours
	lea sndb(pc),a0
	move.l a3,(a0)+			; sauve ma structure
	move.l 16(a3),(a0)+		; song_address
	move 22(a3),(a0)+			; songs
	move d0,(a0)+				; current_sng
	bsr get_songinfo
	bsr start_play
	bra.s .status
.stop:	
	tst.l 24(a3)
	beq.s .status				; dj zro, renvoie zro
	bsr stop_play				; sinon, arrte le son
	clr.l 24(a3)				; et annule le marqueur
.status:
	move.l 24(a3),d0			; lit l'tat en cours
	beq.s .exit
	lea playing(pc),a0		; si ce n'est pas zro, on vrifie...
	tst.b (a0)					; si le son est physiquement fini
	bne.s .exit
	moveq #0,d0					; si oui, on annule l'tat
	move.l d0,24(a3)			; dans sndb
.exit:
	movem.l (sp)+,d1/a0/a3
	rts
		
;********************************************* unpacking routine of PACK-ICE
; a0 = Pointer to packed data
; a1 = Address to which the data is unpacked
; "bsr" of "jsr" to ice_decrunch with registers a0 and a1 prepared.
ice_decrunch:
	movem.l	d0-a6,-(sp)
	bsr.s	getinfo
	cmpi.l	#'ICE!',d0
	bne	not_packed
	bsr.s	getinfo	
	lea.l	-8(a0,d0.l),a5
	bsr.s	getinfo
	move.l	d0,(sp)
	move.l	a1,a4
	move.l	a1,a6
	adda.l	d0,a6
	move.l	a6,a3
	move.b	-(a5),d7
	bsr	normal_bytes
	move.l	a3,a6
	bsr	get_1_bit
	bcc.s	not_packed
	move.w	#$0f9f,d7
	bsr	get_1_bit
	bcc.s	ice_00
	moveq	#15,d0	
	bsr	get_d0_bits
	move.w	d1,d7
ice_00:	moveq	#3,d6
ice_01:	move.w	-(a3),d4
	moveq	#3,d5
ice_02:	add.w	d4,d4
	addx.w	d0,d0
	add.w	d4,d4
	addx.w	d1,d1
	add.w	d4,d4
	addx.w	d2,d2
	add.w	d4,d4
	addx.w	d3,d3
	dbra	d5,ice_02
	dbra	d6,ice_01
	movem.w	d0-d3,(a3)
	dbra	d7,ice_00

not_packed:
	movem.l	(sp)+,d0-a6
	rts

getinfo:	moveq	#3,d1
getbytes: lsl.l	#8,d0
	move.b	(a0)+,d0
	dbf	d1,getbytes
	rts

normal_bytes:	
	bsr.s	get_1_bit
	bcc.s	test_if_end
	moveq.l	#0,d1
	bsr.s	get_1_bit
	bcc.s	copy_direkt
	lea.l	direkt_tab+20(pc),a1
	moveq.l	#4,d3
nextgb:	move.l	-(a1),d0
	bsr.s	get_d0_bits
	swap.w	d0
	cmp.w	d0,d1
	dbne	d3,nextgb
no_more:	add.l	20(a1),d1
copy_direkt:	
	move.b	-(a5),-(a6)
	dbf	d1,copy_direkt
test_if_end:	
	cmpa.l	a4,a6
	bgt.s	strings
	rts	


get_1_bit: add.b	d7,d7
	bne.s	bitfound
	move.b	-(a5),d7
	addx.b	d7,d7
bitfound:	rts	

get_d0_bits:	
	moveq.l	#0,d1
hole_bit_loop:	
	add.b	d7,d7
	bne.s	on_d0
	move.b	-(a5),d7
	addx.b	d7,d7
on_d0:	addx.w	d1,d1
	dbf	d0,hole_bit_loop
	rts	



strings:	lea.l	length_tab(pc),a1
	moveq.l	#3,d2
get_length_bit:	
	bsr.s	get_1_bit
	dbcc	d2,get_length_bit
no_length_bit:	
	moveq.l	#0,d4
	moveq.l	#0,d1
	move.b	1(a1,d2.w),d0
	ext.w	d0
	bmi.s	no_uber
get_uber: bsr.s	get_d0_bits
no_uber:	move.b	6(a1,d2.w),d4
	add.w	d1,d4
	beq.s	get_offset_2


	lea.l	more_offset(pc),a1
	moveq.l	#1,d2
getoffs:	bsr.s	get_1_bit
	dbcc	d2,getoffs
	moveq.l	#0,d1
	move.b	1(a1,d2.w),d0
	ext.w	d0
	bsr.s	get_d0_bits
	add.w	d2,d2
	add.w	6(a1,d2.w),d1
	bpl.s	depack_bytes
	sub.w	d4,d1
	bra.s	depack_bytes


get_offset_2:	
	moveq.l	#0,d1
	moveq.l	#5,d0
	moveq.l	#-1,d2
	bsr.s	get_1_bit
	bcc.s	less_40
	moveq.l	#8,d0
	moveq.l	#$3f,d2
less_40:	bsr.s	get_d0_bits
	add.w	d2,d1

depack_bytes:
	lea.l	2(a6,d4.w),a1
	adda.w	d1,a1
	move.b	-(a1),-(a6)
dep_b:	move.b	-(a1),-(a6)
	dbf	d4,dep_b
	bra	normal_bytes


direkt_tab:
	dc.l $7fff000e,$00ff0007,$00070002,$00030001,$00030001
	dc.l     270-1,	15-1,	 8-1,	 5-1,	 2-1

length_tab:
	dc.b 9,1,0,-1,-1
	dc.b 8,4,2,1,0

more_offset:
	dc.b	  11,   4,   7,  0
	dc.w	$11f,  -1, $1f

;************************************************* end of unpacking routine


;**********************************
gsinfo:		reg d0-a6
get_songinfo:	movem.l	gsinfo,-(sp)

	;Make sure the timer-setup structure is cleared
		lea	timer_setup(pc),a0
		movea.l	a0,a2
		moveq	#(TimFreq_ssize/2)-1,d0
.clr_tf:	clr.w	(a0)+
		dbra	d0,.clr_tf

		move.w	#'TA',d2
		bsr.s	.get_timerval
		bcc.s	.ntA
		move.w	d0,timerA_freq(a2)
		move.b	d1,timerA_div(a2)
		move.b	d2,timerA_data(a2)
		moveq	#'A',d0
		bra	.done_timers
.ntA:		move.w	#'TB',d2
		bsr.s	.get_timerval
		bcc.s	.ntB
		move.w	d0,timerB_freq(a2)
		move.b	d1,timerB_div(a2)
		move.b	d2,timerB_data(a2)
		moveq	#'B',d0
		bra	.done_timers
.ntB:		move.w	#'TC',d2
		bsr.s	.get_timerval
		bcc.s	.ntC
		move.w	d0,timerC_freq(a2)
		move.b	d1,timerC_div(a2)
		move.b	d2,timerC_data(a2)
		moveq	#'C',d0
		bra	.done_timers
.ntC:		move.w	#'TD',d2
		bsr.s	.get_timerval
		bcc.s	.use_deftimer
		move.w	d0,timerD_freq(a2)
		move.b	d1,timerD_div(a2)
		move.b	d2,timerD_data(a2)
		moveq	#'D',d0
		bra.s	.done_timers

.get_timerval:	bsr	search_sndh_wp
		beq.s	.no_TV_found
		lea	-20(sp),sp
		movea.l	sp,a0
		move.l	d2,a1
		moveq	#9,d0
.cpy_TV:	move.b	(a1)+,(a0)+
		beq.s	.got_asciTV
		dbra	d0,.cpy_TV
.got_asciTV:	movea.l	sp,a0
		move.l	d2,a1
		bsr	ascidectobin
		bcc.s	.asciconv_error
		lea	20(sp),sp
		move.l	#12288,d2
		divu.w	d0,d2
		moveq	#7,d1
		and.l	#$ffff,d2
		or.b	#1,ccr
		rts
.asciconv_error:lea	20(sp),sp
.no_TV_found:	and.b	#$fe,ccr
		rts
		
.use_deftimer:	move.w	#50,timerC_freq(a2)
		move.b	#246,timerC_data(a2)
		move.b	#7,timerC_div(a2)
		moveq	#'C',d0
		bset	#31,d0
		lea	-4(sp),a1
		move.w	#'50',(a1)
		clr.b	2(a1)
		
.done_timers:	lea	t_method(pc),a2
		tst.l	d0
		bpl.s	.no_t_def
		move.b	#'*',(a2)+
.no_t_def:	lea	t_timer(pc),a0
.cpy_ts:	move.b	(a0)+,(a2)+
		bne.s	.cpy_ts
		move.b	d0,-1(a2)
		move.b	#',',(a2)+
		move.b	#' ',(a2)+
.cpy_speed:	move.b	(a1)+,(a2)+
		bne.s	.cpy_speed
		move.b	#'H',-1(a2)
		move.b	#'z',(a2)+
		clr.b	(a2)

	;Check for !V tag (!V = play off VBI)
		lea use_vbl(pc),a0
		clr.b	(a0)
		move.w	#'!V',d2
		bsr	search_sndh_w
		beq.s	.no_vblmode

	;Make user select use of VBI or Timer C
	
	; par defaut vbi utilise le timer C pour moi !
	; on saute donc a vbi_use_c

			
;		lea	vbi_or_tc(pc),a0
;		bsr	print_text
;.sel_vort:	bsr	get_key
;		cmp.b	#'t',d0
;		beq.s	.vbi_use_c
;		cmp.b	#'v',d0
;		bne.s	.sel_vort

;		lea	timer_setup(pc),a2
;		clr.w	timerA_freq(a2)
;		clr.w	timerB_freq(a2)
;		clr.w	timerC_freq(a2)
;		clr.w	timerD_freq(a2)
;		lea	t_vblon(pc),a2
;		st	use_vbl
;		bra.s	.set_method_inf
				
.vbi_use_c:	lea	t_method(pc),a2
.vget_end:	tst.b	(a2)+
		bne.s	.vget_end
		subq.l	#1,a2
		move.l	a0,-(sp)
		lea	t_vbiovr(pc),a0
.cpy_vbiovr:	move.b	(a0)+,(a2)+
		bne.s	.cpy_vbiovr
		move.l	(sp)+,a0
.no_vblmode:	lea	t_method(pc),a2
.set_method_inf: 
		lea method_txt(pc),a0
		move.l	a2,(a0)
;..................................................................................
	;Check for MuMo tag (music mon)
		lea musicmon(pc),a0
		sf (a0)
		move.l	#'MuMo',d2
		bsr	search_sndh
		beq.s	.mumon_checked
		lea musicmon(pc),a0
		st (a0)
.mumon_checked:
		movem.l	(sp)+,gsinfo
		rts
;..................................................................................
;vbi_or_tc:	dc.b "Found !V tag!! Actually use VBI",13,10
;		dc.b "or use default timer (Timer C)?",13,10
;		dc.b "T = timer, V = VBI",0
;		even
;..................................................................................
search_sndh:	movea.l	song_address(pc),a3
		move.w	#MAX_HEADER-1,d7
		move.l	(a3)+,d1
.search_sndh:	cmp.l	d2,d1
		beq.s	.wow
		lsl.l	#8,d1
		move.b	(a3)+,d1
		dbra	d7,.search_sndh
		moveq	#0,d2
		rts
.wow:		move.l	a3,d2
		rts
;..................................................................................
search_sndh_w:	movea.l	song_address(pc),a3
		move.w	#MAX_HEADER-1,d7
		move.w	(a3)+,d1
.search_sndh:	cmp.w	d2,d1
		beq.s	.wow
		lsl.w	#8,d1
		move.b	(a3)+,d1
		dbra	d7,.search_sndh
		moveq	#0,d2
		rts
.wow:		move.b	(a3)+,d2
		lsl.w	#8,d2
		move.b	(a3)+,d2
		rts
;..................................................................................
search_sndh_wp:	movea.l	song_address(pc),a3
		move.w	#MAX_HEADER-1,d7
		move.w	(a3)+,d1
.search_sndh:	cmp.w	d2,d1
		beq.s	.wow
		lsl.w	#8,d1
		move.b	(a3)+,d1
		dbra	d7,.search_sndh
		moveq	#0,d2
		rts
.wow:		move.l	a3,d2
		rts
;..................................................................................
ascidectobin:	movem.l	d1-d3/a0-a1,-(sp)
		moveq	#0,d0
		movea.l	a0,a1
.adecbin1:	tst.b	(a1)+
		bne.s	.adecbin1
		subq.l	#1,a1
		move.l	a1,d1
		sub.l	a0,d1
		subq.l	#1,d1
		blt.s	.ok
		moveq	#0,d2
		moveq	#0,d3
		bra.s	.adecbin3
.adecbin2:	move.l	d0,d2
		lsl.l	#2,d0
		add.l	d2,d0
		lsl.l	#1,d0
.adecbin3:	move.b	(a0)+,d3
		cmp.b	#48,d3
		blo.s	.error
		cmp.b	#57,d3
		bhi.s	.error
		sub.b	#48,d3
		add.l	d3,d0
		dbra	d1,.adecbin2
.ok:		or.b	#1,ccr
		bra.s	.exit
.error:		and.b	#$fe,ccr
.exit:		movem.l	(sp)+,d1-d3/a0-a1
		rts

hw_mfp		=	$fffffa00
hw_mfpgpip	=	$fffffa01
hw_mfpaer	=	$fffffa03
hw_mfpddr	=	$fffffa05
hw_mfpiera	=	$fffffa07
hw_mfpierb	=	$fffffa09
hw_mfpipra	=	$fffffa0b
hw_mfpiprb	=	$fffffa0d
hw_mfpisra	=	$fffffa0f
hw_mfpisrb	=	$fffffa11
hw_mfpimra	=	$fffffa13
hw_mfpimrb	=	$fffffa15
hw_mfpvr		=	$fffffa17
hw_mfptacr	=	$fffffa19
hw_mfptbcr	=	$fffffa1b
hw_mfptcdcr	=	$fffffa1d
hw_mfptadr	=	$fffffa1f
hw_mfptbdr	=	$fffffa21
hw_mfptcdr	=	$fffffa23
hw_mfptddr	=	$fffffa25
hw_mfpscr	=	$fffffa27
hw_mfpucr	=	$fffffa29
hw_mfprsr	=	$fffffa2b
hw_mfptsr	=	$fffffa2d
hw_mfpudr	=	$fffffa2f

iera		=	$7
ierb		=	$9
imra		=	$13
imrb		=	$15
vr			=	$17
tacr		=	$19
tbcr		=	$1b
tcdcr		=	$1d
tadr		=	$1f
tbdr		=	$21
tcdr		=	$23
tddr		=	$25

vec_buserr		=	$8
vec_div0			=	$14
vec_privilege	=	$20
vec_spurious	=	$60

vec_VBI		=	$70		;Vblank
vec_timer_d	=	$110		;Bit 4 in IERB. Timer D interrupt vector (RS232 baud rate generator, not used in Falcon030)
vec_timer_c	=	$114		;Bit 5 in IERB. Timer C interrupt vector (200Hz system clock)
vec_timer_b	=	$120		;bit 0 in IERA. Timer B (Horizontal blank counter)
vec_timer_a	=	$134		;bit 5 in IERA. Timer A (DMA sound complete)

conterm		=	$484

hw_giselect	=	$ffff8800
hw_giwrite	=	$ffff8802

save_hdw:	movem.l	d0-a6,-(sp)

		clr.b	hw_mfptacr.w			;Stop Timer A    
	
		move.w	sr,-(sp)
		move.w	#$2700,sr
		
		lea	save_hardware(pc),a0
	
		;move.w	$FFFF8242.w,(a0)+
		move.w	$0484.w,(a0)+
		move.b	hw_mfptacr.w,(a0)+
		move.b	hw_mfptbcr.w,(a0)+
		move.b	hw_mfpvr.w,(a0)+
		move.b	hw_mfpimra.w,(a0)+
		move.b	hw_mfpimrb.w,(a0)+
		move.b	hw_mfpiera.w,(a0)+
		move.b	hw_mfpierb.w,(a0)+
		move.b	hw_mfptadr.w,(a0)+
		move.b	hw_mfptddr.w,(a0)+
		move.b	hw_mfptbdr.w,(a0)+
		move.l	vec_timer_d.w,(a0)+
		move.l	vec_timer_c.w,(a0)+
		move.l	vec_timer_a.w,(a0)+
		move.l	vec_timer_b.w,(a0)+
		move.l	vec_buserr.w,(a0)+		; Exceptions (fr Falcon!)
		move.l	vec_div0.w,(a0)+		; Zero Divide
		move.l	vec_privilege.w,(a0)+		; Privilege Violation

		moveq	#8-1,d7
		lea	vec_spurious.w,a1		; Spurious IRQ + Autovecs (Timer)...
.sav_autov:	move.l	(a1)+,(a0)+
		dbra	d7,.sav_autov
	
		move.w	(sp)+,sr
		
		bsr	get_cpu_type
		cmp.w	#20,d0
		blt.s	.no_cache
		opt	p=68030
		movec	cacr,d1
		move.l	d1,(a0)+
		opt	p=68000
.no_cache:	
		movem.l	(sp)+,d0-a6
		rts

restore_hdw:	movem.l	d0-a6,-(sp)

		clr.b	hw_mfptacr.w			; Stop Timer A    

		move.w	sr,-(sp)
		move.w	#$2700,sr

		lea	save_hardware(pc),a0

		;move.w	(a0)+,$ffff8242.w
		move.w	(a0)+,$0484.w
		move.b	(a0)+,hw_mfptacr.w
		move.b	(a0)+,hw_mfptbcr.w
		move.b	(a0)+,hw_mfpvr.w
		move.b	(a0)+,hw_mfpimra.w
		move.b	(a0)+,hw_mfpimrb.w
		move.b	(a0)+,hw_mfpiera.w
		move.b	(a0)+,hw_mfpierb.w
		move.b	(a0)+,hw_mfptadr.w
		move.b	(a0)+,hw_mfptddr.w
		move.b	(a0)+,hw_mfptbdr.w
		move.l	(a0)+,vec_timer_d.w
		move.l	(a0)+,vec_timer_c.w
		move.l	(a0)+,vec_timer_a.w
		move.l	(a0)+,vec_timer_b.w
		move.l	(a0)+,vec_buserr.w
		move.l	(a0)+,vec_div0.w
		move.l	(a0)+,vec_privilege.w

		moveq	#8-1,d7
		lea	vec_spurious.w,a1
.res_autov:	move.l	(a0)+,(a1)+
		dbra	d7,.res_autov
		
		move.w	(sp)+,sr
		
		bsr	get_cpu_type
		cmp.w	#20,d0
		blt.s	.no_cache
		opt	p=68030
		move.l	(a0)+,d1
		movec	d1,cacr
		opt	p=68000
.no_cache:
		movem.l	(sp)+,d0-a6
		rts
;-------------------------------------------------------------------------------------
start_play:	movem.l	d0-a6,-(sp)

		lea playing(pc),a0
		tst.b	(a0)
		bne	.exit

		bsr	set_super
		
		bsr	save_hdw
	
		bsr	get_cpu_type
		cmp.w	#20,d0
		blt.s	.no_shadow
		move.w	#$2700,sr
		lea bus_error(pc),a0
		move.l	a0,vec_buserr.w
		lea .rte(pc),a0
		move.l	a0,vec_spurious.w
		move.l	a0,vec_div0.w
		move.l	a0,vec_privilege.w
		move.w	#$2300,sr

.no_shadow:	bclr	#0,conterm.w			; Tastaturklick aus (nur bei Backgrd.)    

		lea	timer_setup(pc),a2

		lea use_vbl(pc),a0
		tst.b	(a0)
		bne.s	.use_vbl

		lea	hw_mfp.w,a0
		
		move.w	timerA_freq(a2),d0
		bne	.use_tA

		move.w	timerB_freq(a2),d0
		bne	.use_tB

		move.w	timerC_freq(a2),d0
		bne	.use_tC
		
		move.w	timerD_freq(a2),d0
		bne.s	.use_tD

		lea use_vbl(pc),a0		
		tst.b	(a0)
		beq.s	.use_vbl
		lea musicmon(pc),a0
		tst.b	(a0)
		bne	.start_it

.use_vbl:	clr.w	timerA_freq(a2)
		clr.w	timerB_freq(a2)
		clr.w	timerD_freq(a2)
		clr.w	timerC_freq(a2)
		lea speed_Hz(pc),a0
		move.w	#50,(a0)+		; speed_Hz
		move.w	#50,(a0)+		; timediv
		lea calledplay_vbi(pc),a1
		move.l	a1,(a0)+	; callplay_exit
		move.l	vec_VBI.w,(a0)+	; old_vbl
		lea timer_a(pc),a0
		move.l	a0,vec_VBI.w
		bra	.start_it	
		
.force_tA:	moveq	#50,d0
		move.w	d0,timerC_freq(a2)
		move.b	#246,timerC_data(a2)
		move.b	#7,timerC_div(a2)
		lea use_vbl(pc),a0
		sf (a0)
		bra	.use_tC

.use_tD:	move.w	#$2700,sr
		lea speed_Hz(pc),a1
		move.w	d0,(a1)+	;	speed_Hz
		move.w	d0,(a1)+	; timediv
		and.b	#%11110000,tcdcr(a0)		;Stop timer D
		lea calledplay_tD(pc),a3
		move.l	a3,(a1)+	; callplay_exit
		lea timer_a(pc),a1
		move.l	a1,vec_timer_d.w		;Set new Timer A Interrupt routine    
		bclr	#3,vr(a0)			;Set "Automatic End-of-Interrupt" mode    
		bset	#4,imrb(a0)			;Interrupt mask for Timer A    
		bset	#4,ierb(a0)			;Turn on the interrup for Timer A    
		lea speed(pc),a1
		move.b	timerD_data(a2),(a1)	; speed
		move.b	(a1),tddr(a0)		;Set the Timer A data register    
		move.b	timerD_div(a2),d0
		and.b	#7,d0
		or.b	d0,tcdcr(a0)	 		; Timer mit Vorteiler 1:200 starten    
		bra	.start_it

.use_tA:	move.w	#$2700,sr
		lea speed_Hz(pc),a1
		move.w	d0,(a1)+	; speed_Hz
		move.w	d0,(a1)+	; timediv
		clr.b	tacr(a0)			;Stop Timer A    
		lea calledplay_tA(pc),a3
		move.l	a3,(a1)+ ;callplay_exit
		lea timer_a(pc),a3
		move.l	a3,vec_timer_a.w		;Set new Timer A Interrupt routine    
		bclr	#3,vr(a0)			;Set "Automatic End-of-Interrupt" mode    
		bset	#5,imra(a0)			;Interrupt mask for Timer A    
		bset	#5,iera(a0)			;Turn on the interrup for Timer A    
		lea speed(pc),a1
		move.b	timerA_data(a2),(a1)
		move.b	(a1),tadr(a0)		;Set the Timer A data register    
		move.b	timerA_div(a2),tacr(a0) 	; Timer mit Vorteiler 1:200 starten    
		bra	.start_it

.use_tB:	move.w	#$2700,sr
		lea speed_Hz(pc),a1
		move.w	d0,(a1)+	; speed_Hz
		move.w	d0,(a1)+ ; timediv
		clr.b	tbcr(a0)
		lea calledplay_tB(pc),a3
		move.l	a3,(a1)+	; callplay_exit
		lea timer_a(pc),a1
		move.l	a1,vec_timer_b.w		;Set new Timer A Interrupt routine    
		bclr	#3,vr(a0)			;Set "Automatic End-of-Interrupt" mode    
		bset	#0,imra(a0)			;Interrupt mask for Timer A    
		bset	#0,iera(a0)			;Turn on the interrup for Timer A    
		lea speed(pc),a1
		move.b	timerB_data(a2),(a1)
		move.b	(a1),tbdr(a0)		;Set the Timer A data register    
		move.b	timerB_div(a2),tbcr(a0)		; Timer mit Vorteiler 1:200 starten    
		bra	.start_it

.use_tC:	move.w	#$2700,sr
		lea speed_Hz(pc),a1
		move.w	d0,(a1)+	; speed_Hz
		move.w	d0,(a1)+	; timediv
		move.l	vec_timer_c.w,8(a1)	; old_tC
		lea tC_Hz(pc),a1
		move.w	#200,(a1)	; tC_Hz
		lea timer_c(pc),a1
		move.l	a1,vec_timer_c.w

.start_it:	moveq	#0,d0
		move.w	current_sng(pc),d0
		movea.l	song_address(pc),a0
		move.l	musicmon_buff(pc),d1
		jsr	(A0)				; Soundinit    
		stop	#$2300				; ab geht's...    

		lea playing(pc),a0
		st (a0)
		bsr	set_user
.exit:		movem.l	(sp)+,d0-a6
		rts

.rte:		rte
;-------------------------------------------------------------------------------------
stop_play:	movem.l	d0-a6,-(sp)

		lea playing(pc),a0
		tst.b (a0)
		beq	.exit
		
		bsr	set_super
		
		move.w	sr,-(sp)

		lea .stacksave(pc),a0		
		move.l sp,(a0)
	
		lea temp_stack(pc),sp

		move.w	#$2700,sr

		movea.l	song_address(pc),a0
		moveq	#0,d0
		jsr	4(a0)
		
		move.w	#$2700,sr
		lea use_vbl(pc),a0
		tst.b	(a0)
		beq.s	.no_vbl
		lea old_vbl(pc),a0
		move.l	(a0),vec_VBI.w
		clr.l	(a0)
		bra.s	.notC
		
.no_vbl:	lea	timer_setup(pc),a0
		tst.w	timerA_freq(a0)
		beq.s	.notA
		clr.b	hw_mfptacr.w			;Stop Timer A
.notA:		tst.w	timerB_freq(a0)
		beq.s	.notB
		clr.b	hw_mfptbcr.w
.notB:		tst.w	timerD_freq(a0)
		beq.s	.notD
		and.b	#%11110000,hw_mfptcdcr.w
.notD:		tst.w	timerC_freq(a0)
		beq.s	.notC

		move.l	old_tC(pc),vec_timer_c.w
.notC:		

		move.l	.stacksave(pc),sp
		move.w	(sp),sr
		
		bsr	restore_hdw
		lea old_vbl(pc),a0
		clr.l	(a0)

		move.w	#$2700,sr
		move.b	#$8,hw_giselect.w
		move.b	#0,hw_giwrite.w
		move.b	#$9,hw_giselect.w
		move.b	#0,hw_giwrite.w
		move.b	#$a,hw_giselect.w
		move.b	#0,hw_giwrite.w
		
		lea .stacksave(pc),a0	
		move.l	(a0),sp
		move.w	(sp)+,sr
	
		lea playing(pc),a0
		sf.b	(a0)+		; playing
		sf.b	(a0)+		; pause
		bsr	set_user
		
		move.l sndb(pc),a0
		clr.l 24(a0)		; current song  zro cot programme appelant

.exit:		movem.l	(sp)+,d0-a6
		rts	

.stacksave:	ds.l	1
.srsave:	ds.w	1
;-------------------------------------------------------------------------------------
;new_play:	movem.l	d0-a6,-(sp)
;
;		tst.b	playing
;		beq.s	.not_playing
;		bsr	stop_play
		
;.not_playing:	bsr	set_super

;		moveq	#0,d0
;		move.w	current_sng(pc),d0
;		movea.l	song_address(pc),a0
;		jsr	(A0)				; Soundinit    

;		bsr	set_user

;		movem.l	(sp)+,d0-a6
;		rts
;-------------------------------------------------------------------------------------
;This is the timer routine used for timer A, B and D. Also used when installing as vbl rout.

timer_a:        movem.l	D0-A6,-(SP)
 		lea pause(pc),a0             
		tst.b	(a0)
		beq.s	.no_pause
		
		moveq	#0,d0
		lea	hw_giselect.w,a0
		move.b	#8,(a0)
		lea	hw_giwrite.w,a1
		clr.b	(a1)
		move.b	#9,(a0)
		clr.b	(a1)
		move.b	#$a,(a0)
		clr.b	(a1)
		
		bra.s	.end_tima
	
.no_pause:	movea.l	song_address(pc),a0
		jsr	8(A0)	; Sound spielen

		lea speed_Hz(pc),a0
		subq.w	#1,2(a0)		; timediv
		bne.s	.end_tima
		move.w	(a0),2(a0)			; speed_Hz(pc),timediv		;#50,timediv

		moveq	#60,d2
		lea	hours(pc),a0
		move.b	5(a0),d0
		addq.b	#1,d0
		move.b	4(a0),d1
		cmp.b	d2,d0
		bls.s	.time_ok
		clr.b	d0
		addq.b	#1,d1
		cmp.b	d2,d1
		bls.s	.time_ok
		clr.b	d1
		addq.l	#1,(a0)

.time_ok:	move.b	d0,5(a0)
		move.b	d1,4(a0)
		move.b	11(a0),d0
		addq.b	#1,d0
		move.b	10(a0),d1
		cmp.b	d2,d0
		bls.s	.time_ok1
		clr.b	d0
		addq.b	#1,d1
		cmp.b	d2,d1
		bls.s	.time_ok1
		clr.b	d1
		addq.l	#1,6(a0)
.time_ok1:	move.b	d0,11(a0)
		move.b	d1,10(a0)
		
.end_tima:	movem.l	(SP)+,D0-A6
		move.l	callplay_exit(pc),-(sp)
		rts


calledplay_tA:	and.b	#%11011111,hw_mfpisra.w		 ; da SEI
		move.b	speed(pc),hw_mfptadr.w
		rte
calledplay_tB:	and.b	#%11111110,hw_mfpisra.w
		move.b	speed(pc),hw_mfptbdr.w
		rte
calledplay_tD:	and.b	#%11101111,hw_mfpisrb.w
		move.b	speed(pc),hw_mfptddr.w
		rte
calledplay_vbi:
.vbl_end:	move.l	old_vbl(pc),-(sp)
		rts
;--------------------------------------------------------------------------------------
timer_c:	move.l	d0,-(sp)
		move.w	speed_Hz(pc),d0
		move.l a0,-(sp)
		lea tC_Hz(pc),a0
		sub.w	d0,(a0)
		movea.l (sp)+,a0
		ble.s	.do_tc
		move.l	(sp),d0
.no_do:		move.l	old_tC(pc),(sp)
		rts
		
.do_tc:		move.l	(sp)+,d0
		movem.l	D0-A6,-(SP)

		move.w	sr,-(sp)
		move.w	#$2300,sr

		lea tC_Hz(pc),a0
		add.w	#200,(a0)

		lea pause(pc),a0
		tst.b	(a0)
		beq.s	.no_pause
	
		moveq	#0,d0
		lea	hw_giselect.w,a0
		move.b	#8,(a0)
		lea	hw_giwrite.w,a1
		clr.b	(a1)
		move.b	#9,(a0)
		clr.b	(a1)
		move.b	#$a,(a0)
		clr.b	(a1)
		
		bra.s	.end_tima
	
.no_pause:	movea.l	song_address(pc),a0
		jsr	8(A0)	; Sound spielen

		lea speed_Hz(pc),a0
		subq.w	#1,2(a0)	;	timediv
		bne.s	.end_tima
		move.w	(a0),2(a0)		; timediv		;#50,timediv

		moveq	#60,d2
		lea	hours(pc),a0
		move.b	5(a0),d0
		addq.b	#1,d0
		move.b	4(a0),d1
		cmp.b	d2,d0
		bls.s	.time_ok
		clr.b	d0
		addq.b	#1,d1
		cmp.b	d2,d1
		bls.s	.time_ok
		clr.b	d1
		addq.l	#1,(a0)

.time_ok:	move.b	d0,5(a0)
		move.b	d1,4(a0)
		move.b	11(a0),d0
		addq.b	#1,d0
		move.b	10(a0),d1
		cmp.b	d2,d0
		bls.s	.time_ok1
		clr.b	d0
		addq.b	#1,d1
		cmp.b	d2,d1
		bls.s	.time_ok1
		clr.b	d1
		addq.l	#1,6(a0)
.time_ok1:	move.b	d0,11(a0)
		move.b	d1,10(a0)
		
.end_tima:	move.w	(sp)+,sr
		movem.l	(SP)+,D0-A6
		move.l	old_tC(pc),-(sp)
		rts
;---------------------------------------------------------------------------------------
force_play:	movem.l	d0-a6,-(sp)

		lea song_address(pc),a0
		tst.l	(a0)
		beq	.end_tima
		lea playing(pc),a0
		tst.b	(a0)+ ; playing
		beq	.end_tima
		tst.b	(a0)+	; pause
		bne	.end_tima

		lea timer_setup+timerC_freq(pc),a0
		tst.w	(a0)
		beq	.end_tima
		bsr	set_super
		bsr.s	.play_it
		bsr.s	.play_it
		bsr.s	.play_it
		bsr.s	.play_it
		bsr.s	.play_it
		bsr.s	.play_it
		bsr	set_user
		bra.s	.end_tima
						
.play_it:	movea.l	song_address(pc),a0

		move.w	sr,-(sp)
		move.w	#$2700,sr
		jsr	8(A0)	; Sound spielen
		move.w	(sp)+,sr
		
		lea speed_Hz(pc),a0
		subq.w	#1,2(a0)	; timediv
		bne.s	.end
		move.w	(a0),2(a0)	; speed_Hz(pc),timediv

		moveq	#60,d2
		lea	hours(pc),a0
		move.b	5(a0),d0
		addq.b	#1,d0
		move.b	4(a0),d1
		cmp.b	d2,d0
		bls.s	.time_ok
		clr.b	d0
		addq.b	#1,d1
		cmp.b	d2,d1
		bls.s	.time_ok
		clr.b	d1
		addq.l	#1,(a0)

.time_ok:	move.b	d0,5(a0)
		move.b	d1,4(a0)
		move.b	11(a0),d0
		addq.b	#1,d0
		move.b	10(a0),d1
		cmp.b	d2,d0
		bls.s	.time_ok1
		clr.b	d0
		addq.b	#1,d1
		cmp.b	d2,d1
		bls.s	.time_ok1
		clr.b	d1
		addq.l	#1,6(a0)
.time_ok1:	move.b	d0,11(a0)
		move.b	d1,10(a0)
.end:		rts

.end_tima:	movem.l	(SP)+,D0-A6
		rts

;---------------------------------------------------------------------------------------
toggle_pause: move.l a0,-(sp)
		lea pause(pc),a0
		tst.b	(a0)
		movea.l (sp)+,a0
		beq.s	.set_on
		bsr.s	set_pause_off
		rts
.set_on		bsr.s	set_pause_on
		rts

set_pause_on:	movem.l	d0/a0-a2,-(sp)

		lea pause(pc),a0
		tst.b	(a0)
		bne.s	.exit

		bsr	set_super
		move.w	sr,-(sp)
		move.w	#$2700,sr
		
		lea	timer_setup(pc),a0
		lea	pause_save(pc),a1
		clr.w	(a1)
		clr.b	2(a1)

		tst.w	timerA_freq(a0)
		bne.s	.chk_B
		move.b	hw_mfptacr.w,(a1)
		clr.b	hw_mfptacr.w
.chk_B:		tst.w	timerB_freq(a0)
		bne.s	.chk_D
		move.b	hw_mfptbcr.w,1(a1)
		clr.b	hw_mfptbcr.w
.chk_D:		tst.w	timerD_freq(a0)
		bne.s	.pause_set
		move.b	hw_mfptcdcr.w,2(a1)
		and.b	#%11110000,hw_mfptcdcr.w
.pause_set:	
		lea pause(pc),a0
		st.b (a0)
		move.w	(sp)+,sr
		bsr	set_user
		
.exit		movem.l	(sp)+,d0/a0-a2
		rts

set_pause_off:	movem.l	d0/a0-a2,-(sp)

		lea pause(pc),a0
		tst.b	(a0)
		beq.s	.exit
		
		bsr	set_super
		move.w	sr,-(sp)
		move.w	#$2700,sr
		
		lea	pause_save(pc),a0
		move.b	(a0)+,d0
		beq.s	.no_A
		move.b	d0,hw_mfptacr.w
.no_A:		move.b	(a0)+,d0
		beq.s	.no_B
		move.b	d0,hw_mfptbcr.w
.no_B:		move.b	(a0),d0
		beq.s	.no_D
		and.b	#7,d0
		and.b	#%11110000,hw_mfptcdcr.w
		or.b	d0,hw_mfptcdcr.w
.no_D:		
		lea pause(pc),a0
		sf.b	(a0)
		move.w	(sp)+,sr
		bsr	set_user
		
.exit:		movem.l	(sp)+,d0/a0-a2
		rts
		
;------------------------------------------------------------------------------
set_super:	movem.l	d0-a6,-(sp)
		move.l	#1,-(sp)
		move.w	#$20,-(sp)
		trap	#1
		addq.l	#6,sp
		tst.w	d0
		bne.s	.insuper
		clr.l	-(sp)
		move.w	#$20,-(sp)
		trap	#1
		addq.l	#6,sp
		lea sav_usp(pc),a0
		move.l	d0,(a0)
.insuper:	movem.l	(sp)+,d0-a6
		rts

set_user:	movem.l	d0-a6,-(sp)
		move.l	#1,-(sp)
		move.w	#$20,-(sp)
		trap	#1
		addq.l	#6,sp
		tst.w	d0
		beq.s	.inuser
		move.l	sav_usp(pc),-(sp)
		move.w	#$20,-(sp)
		trap	#1
		addq.l	#6,sp
.inuser:	movem.l	(sp)+,d0-a6
		rts
sav_usp:	ds.l	1

;------------------------------------------------------------------------------
gcputyp:	reg d1/a0
get_cpu_type:	movem.l	gcputyp,-(sp)
		move.l	#'_CPU',d1
		bsr	find_cookie
		tst.l	d0
		bmi.s	.m68000		
		move.l	4(a0),d0
		bra.s	.exit
.m68000:	moveq	#0,d0
.exit:		movem.l	(sp)+,gcputyp
		rts

find_cookie:	move.l	$5a0.w,d0		;Get address of cookie jar in D0
		beq.s	.nojar			;If zero, there's no jar.
		move.l	d0,a0			;Move the address of the jar to A0
.search:	tst.l	(a0)			;Is this jar entry the last one ?
		beq.s	.nofind			;Yes, the cookie was not found
		cmp.l	(a0),d1			;Does this cookie match what we're looking for?
		beq.s	.foundit		;Yes, it does.
		addq.l	#8,a0			;Advance to the next jar entry
		bra.s	.search			;And start over
.nofind:	moveq	#-1,d0			;A negative (-1) means cookie not found
		rts
.nojar:		moveq	#-2,d0			;A negative (-2) means there's no jar
		rts
.foundit:	moveq	#0,d0			;A null in D0 means the cookie was found.
.exit:		rts

;------------------------------------------------------------------------------
***** FALCON 030 ROUTINEN *****
;f030_shadow:    ;>PART 'Buserror-Shadowregs'
; =====================================================
; Program called py the CPU in case of BUS ERROR
; it will try to correct it if it's due to an acces
; to shadowed YM register(s)
; =====================================================
bus_error:	move    #$2700,SR      	 	; IPL 7
		move.l a0,-(sp)
		lea .sav_d0(pc),a0
		move.l  D0,(a0)+		; dans sav d0
		move.l  (sp)+,d0
		move.l d0,(a0)			; dans sav a0
		move.l d0,a0

		moveq   #0,D0
		move.w  $0A(SP),D0      	; SSW
		btst    #8,D0           	; data/retry
		beq     .reprise        	; retry
		btst    #6,D0           	; read/write
		beq.s   .ecriture       	; write

.lecture:	bclr    #8,D0           	; will do a retry
		move.w  D0,$0A(SP)      	; change stack frame
		cmpi.w  #$FF88,$11(SP)  	; bits 8-23 = psg?
		bne.s   .no_psg_r       	; no => bye bye
		move.b  $FFFF8800.w,D0  	; read psg
		move.b  D0,$2C(SP)
		move.b  D0,$2D(SP)
		move.b  D0,$2E(SP)
		move.b  D0,$2F(SP)
		bra     .exit
.no_psg_r:	clr.l   $2C(SP)
		bra     .exit

.ecriture:	bclr    #8,D0
		move.w  D0,$0A(SP)
		cmpi.w  #$FF88,$11(SP)
		bne.s   .no_psg_w
		andi.b  #$02,$13(SP)
		bne.s   .ff8802
.ff8800:	andi.w  #$30,D0         	; oper size
		lsr.w   #4,D0
		beq.s   .size_13
		cmpi.w  #2,D0
		beq.s   .size_12
.size_11:	move.b  $1B(SP),$FFFF8800.w
		bra     .exit
.size_12:	move.b  $1A(SP),$FFFF8800.w
		bra     .exit
.size_13:	;move.l #$FC000000,$FFFF9800.w
		move.b  $18(SP),$FFFF8800.w
		move.b  $1A(SP),$FFFF8802.w
		bra     .exit

.ff8802:	andi.w  #$30,D0
		lsr.w   #4,D0
		beq.s   .size_23
		cmpi.w  #2,D0
		beq.s   .size_22
.size_21:	move.b  $1B(SP),$FFFF8802.w
		bra.s   .exit
.size_22:	move.b  $1A(SP),$FFFF8802.w
		bra.s   .exit
.size_23:	move.b  $18(SP),$FFFF8802.w
		move.b  $1A(SP),$FFFF8800.w
		bra.s   .exit

.no_psg_w:	;move.l #$FC000000,$FFFF9800.w
		bra.s   .exit

.reprise:	btst    #14,D0
		beq.s   .etageB
		btst    #15,D0
		beq.s   .etageC
		bra.s   .exit

.etageB:	bclr    #12,D0
		move.w  D0,$0A(SP)
		cmpi.w  #$0A,6(SP)      	; frame type A?
		bne.s   .frameBB
.frameBA:	movea.l 2(SP),A0
		move.l  A0,$0E(SP)
		bra.s   .exit
.frameBB:	movea.l $24(SP),A0
		move.w  -2(A0),$0E(SP)
		bra.s   .exit

.etageC:	bclr    #13,D0
		move.w  D0,$0A(SP)
		cmpi.w  #$0A,6(SP)
		bne.s   .frameCB
.frameCA:	movea.l 2(SP),A0
		move.w  2(A0),$0C(SP)
		bra.s   .exit
.frameCB:	movea.l $24(SP),A0
		move.w  -2(A0),$0C(SP)

.exit:		movea.l .sav_a0(pc),A0
		move.l  .sav_d0(pc),D0
		rte
; *** ne pas sparer
.sav_d0:	DC.L 0
.sav_a0:	DC.L 0
; ***


		section	data	

tC_Hz:		dc.w 200			;Timer C speed, 200 Hz.
; *** ne pas sparer
playing:	dc.b 0
pause:		dc.b 0
; *** jusqu'ici

t_no_inf:	dc.b	'?',0
t_songs:	ds.b	6
t_timer:	dc.b	'Timer ',0
		even

t_vblon		dc.b	"VBI, ?? Hz",0
t_vbloff:	dc.b	'Off!',0
t_vbiovr:	dc.b	", VBL override!",0
t_method:	ds.b	40					;30 char buffer for constructin method info
		even


		section	bss

; *** ne pas sparer
speed_Hz:	ds.w 1
timediv:	ds.w 1
callplay_exit:	ds.l	1
old_vbl:	ds.l	1
old_tC:		ds.l	1
; *** jusqu'ici

speed:		ds.b 1
use_vbl:	ds.b 1
musicmon:	ds.b 1

		even

hours:		ds.l 1
mins:		ds.b 1 	;+4
secs:		ds.b 1	;+5

shours:		ds.l 1	;+6
smins:		ds.b 1	;+10
ssecs:		ds.b 1	;+11

;saveu:		ds.l	1
;saves:		ds.l	1

save_hardware:	ds.b	100
save_cols:	ds.l	8
musicmon_buff:	ds.l	1

pause_save	ds.b	4

	;This temporary stack is necessary because I found some tunes totally destroyed the stack!!
	;See the source..

		ds.l	200
temp_stack:	ds.l	200


		rsreset
timerA_freq:	rs.w	1
timerA_div:	rs.b 	1
timerA_data:	rs.b	1

timerB_freq:	rs.w	1
timerB_div:	rs.b	1
timerB_data:	rs.b	1

timerC_freq:	rs.w	1
timerC_div:	rs.b	1
timerC_data:	rs.b	1

timerD_freq:	rs.w	1
timerD_div:	rs.b	1
timerD_data:	rs.b	1
TimFreq_ssize:	= __RS

timer_setup:	ds.b	TimFreq_ssize

composer_txt:	ds.l	1					;Address of composer text
title_txt:	ds.l	1					;Address of title text
ripper_txt:	ds.l	1					;address of ripper text
conversion_txt:	ds.l	1					;Address of conversion text
songs_txt:	ds.l	1
method_txt:	ds.l	1
buffer: ds.b 16
; *** ne pas sparer
sndb: ds.l 1
song_address:	ds.l	1					;Address of loaded tune
songs:		ds.w	1
current_sng:	ds.w	1
; *** jusqu'ici

		end