bong.asm
blupi-games_smaky-legacy/bong/src/bong.asm
	.TITLE	BONG

;	--------------------------------------
;		(C) 1987 - Daniel Roux
;	--------------------------------------

	.PROC	M680002
	.REF	SMAKY
	.REF	GRA


	.REV	1,0
	.CODE	800,2,B'1111,600,2000,300,2000,2,'N,'R,'F,09
	.TEXT	"(C)  Daniel ROUX et EPSITEC-system sa"


IFSMILE	=	0		; 1 => assemblage pour SMILE2



; En-tte d'un fichier .IMAGE
; ---------------------------

	.LOC	0
OIMTYP:	.BLKB	1		; H'01 = indique type image
OIMCOD:	.BLKB	1		; H'00 = indique pas de codage
OIMBIP:	.BLKB	1		; H'01 = 1 bit par point
OIMDIR:	.BLKB	1		; H'02 = coord. X-Y comme cran
OIMDLX:	.BLKB	2		; largeur image en points
OIMDLY:	.BLKB	2		; hauteur image en points
OIMNBB:	.BLKB	4		; nb de byte pour l'image
	.BLKB	20		; rserve
LGHIMA:


; Dfinition de l'entte d'un gnrateur de caractres
; ----------------------------------------------------

OGCMSB	=	H'04		; matrix size in bytes
OGCMHD	=	H'06		; matrix height in dots
OGCMWB	=	H'08		; matrix width in bytes
OGCFCA	=	H'0A		; ASCII code of first character
OGCLCA	=	H'0B		; ASCII code of last character
OGCLMA	=	H'0C		; left margin of matrix
OGCBLI	=	H'0E		; bottom of matrix to baseline
OGCISP	=	H'16		; interline space in dots
OGCWID	=	256		; 128 x width
OGCH1	=	256+128*1	; 128 x h1
OGCH2	=	256+128*2	; 128 x h2
OGCMAT	=	256+128*3	; 128 x matrix




; Constantes
; ----------

TIMING	=	50/25		; 25 images par seconde

MAXIRAQ	=	7		; inclinaison maximale (45 degrs)




; Caractres standard
; -------------------

GCTXF	=	'N		; fonte (N)
GCTXS	=	'R!2^7		; style/chasse (RF)
GCTXT	=	09		; taille (09)



; Icnes des IBP64
; ----------------

GCICF	=	'I		; fonte (I)
GCICS	=	'B		; style/chasse (BP)
GCICT	=	64		; taille (64)


VTANIME	=	4		; vitesse de l'animation de fin
NBANIME	=	5+1		; nb d'icnes d'animation (+1 vide)

ICOBALLE0=	8		; balle 0
IDXBALLE0=	63
IDYBALLE0=	63

ICOBALLE1=	16		; balle 1
IDXBALLE1=	41
IDYBALLE1=	41

ICOBALLE2=	24		; balle 2
IDXBALLE2=	31
IDYBALLE2=	31

ICOBALLE3=	32		; balle 3
IDXBALLE3=	31
IDYBALLE3=	31

ICOBALLE4=	40		; balle 4
IDXBALLE4=	37
IDYBALLE4=	37

ICOBALLE5=	48		; balle 5
IDXBALLE5=	29
IDYBALLE5=	29

ICOBALLE6=	56		; balle 6
IDXBALLE6=	46
IDYBALLE6=	46

ICORAQ	=	71		; raquette horizontale
IDXRAQ	=	64
IDYRAQ	=	64
ICXRAQ	=	31
ICYRAQ	=	20

ICORAQEND=	80		; raquette casse

ICOLANCE=	96		; lanceur
IDXLANCE=	64
IDYLANCE=	64

ICOASC	=	112		; ascenseur
IDXASC	=	64
IDYASC	=	64



; Positions dans l'image
; ----------------------

LXWDO	=	640		; largeur de l'cran
LYWDO	=	340		; hauteur de l'cran

MARGH	=	13		; marge en haut
MARGB	=	33		; marge en bas
MARGG	=	57		; marge  gauche
MARGD	=	10		; marge  droite

POSYRAQ	=	LYWDO-IDYRAQ-33	; position Y de la raquette
POSXRAQ	=	317		; position X de la raquette fixe

POSYASC	=	LYWDO-IDYASC-61	; position Y de l'ascenseur (en bas)

POSYCGA	=	LYWDO-208	; position du compteur "gagn"
POSXCGA	=	16

POSYCPE	=	LYWDO-157	; position du compteur "perdu"
POSXCPE	=	16

POSYJAU	=	LYWDO-45	; position de la jauge (en bas)
POSXJAU	=	21



; Descripteur d'un objet en chute libre
; -------------------------------------

	.LOC	0
OOBPOS:	.BLKB	4		; position (y;x)
OOBDIM:	.BLKB	4		; dimensions (dy;dx)
OOBVIT:	.BLKB	4		; vitesses (vy;vx)
OOBCHO:	.BLKB	4		; amortissement en cas de choc (ay;ax)
OOBACC:	.BLKB	2		; pesanteur (py)
OOBVIM:	.BLKB	2		; dure de vie maximale
OOBVIE:	.BLKB	2		; dure de vie de l'objet
OOBFIN:	.BLKB	2		; dure de fin de l'objet
OOBVIF:	.BLKB	2		; compteur de vitesse de fin
OOBICO:	.BLKB	1		; code de l'icne
OOBNEW:	.BLKB	1		; 1 => nouvel objet
OOBOLD:	.BLKB	1		; 1 => objet mort
	.EVEN
OOBMU1:	.BLKB	2		; bruit: choc avec un bord
OOBMU2:	.BLKB	2		; bruit: choc avec la raquette
OOBMU3:	.BLKB	2		; bruit: mort de l'objet
LOBJ:



; Variables
; ---------

	.LOC	0

OMACHINE:.BLKB	1		; type de la machine (SMAKY8/SMAKY100)
OINV:	.BLKB	1		; 1 => fond de l'cran blanc
	.EVEN

OPDDIS:	.BLKB	4		; ^descripteur de la fentre
OPGICO:	.BLKB	4		; ^gencar des icnes (IBP64)
OADRASTER:	.BLKB	4	;  adresse de GRA_RASTER
OADMATRIX:	.BLKB	4	;  adresse de GRA_MATRIX
OADDOT:		.BLKB	4	;  adresse de GRA_DOT
OADTRAME:	.BLKB	4	;  adresse de GRA_TRAME
OADLINE:	.BLKB	4	;  adresse de GRA_LINE
OADELLIPSE:	.BLKB	4	;  adresse de GRA_ELLIPSE
OADFILLO:	.BLKB	4	;  adresse de GRA_FILLO
OADFILLC:	.BLKB	4	;  adresse de GRA_FILLC
OADCLEAR:	.BLKB	4	;  adresse de GRA_CLEAR
OADSET:		.BLKB	4	;  adresse de GRA_SET
OADINV:		.BLKB	4	;  adresse de GRA_INV
OADQXDOT:	.BLKB	4	;  adresse de GRA_QXDOT
OBUDIS:	.BLKB	100		; buffer write-display

OPIMA:	.BLKB	4		; ^image principale du jeu
ODIMA:	.BLKB	4		; dimensions image

OLANPO:	.BLKB	4		; lanceur: position (y;x)
OLANIC:	.BLKB	1		; lanceur: icne
	.EVEN

OASCPO:	.BLKB	4		; ascenseur: position (y;x)
OASCDD:	.BLKB	2		; ascenseur: dlai avant la descente

ORAQPO:	.BLKB	4		; raquette: position (y;x)
ORAQIN:	.BLKB	2		; raquette: inclinaison
ORAQET:	.BLKB	1		; raquette: tat
 BRAQL	=  0			;  bouton gauche press
 BRAQR	=  1			;  bouton droite press
 BRAQC	=  2			;  raquette casse
	.EVEN

OJAUNI:	.BLKB	2		; jauge: niveau

OBALLE:	.BLKB	LOBJ		; balle principale

OFIXE:	.BLKB	1		; 1 => raquette fixe
OBEGIN:	.BLKB	1		; 1 => dbut du jeu
OEND:	.BLKB	1		; 1 => fin de la partie
OHELP:	.BLKB	1		; 1 => appel  l'aide
OGAIN:	.BLKB	1		; 1 => partie gagne
	.EVEN

OFONCT:	.BLKB	2		; fond: compteur pour le frottement

OCONGA:	.BLKB	2		; compteur des parties gagnes
OCONPE:	.BLKB	2		; compteur des parties perdues
OCONNB:	.BLKB	2		; nb de parties gagnes successives

OHAZA:	.BLKB	8		; registre 63 bits pour gnrateur alatoire
OHAZEX:	.BLKB	20		; pour tirage exclusif

LGVAR:





; Programme principal
; -------------------

	.LOC	0
START:
	.IF	~IFSMILE
	LIB	?OPELIB
	.ENDIF

	LOAD.L	D4,#LGVAR
	LOAD.W	D1,#MTYPCP
	GESMEM	?GETMEM		; demande mmoire pour variables
	JUMP,NE ERFAT
	LOAD.L	A6,A4		; A6 <-- ^variables
10$:
	CLR.B	(A4+)		; met toutes les variables  zro
	DEC.W	D4
	JUMP,NE 10$

	LOAD.W	D3,#3
	LIB	?MOUSE		; souris par le clavier


	NTREL	?GETMACHINE	; D4/A3 <-- paramtres
	RL.L	D4,#8		; D4 <-- type de la machine
	LOAD.B	(A6)+OMACHINE,D4


	LIB	?GCHDIS		; D6 <-- canal cran
	LOAD.W	D3,#TYPWDO	; D3 <-- type fentre cran
	LOAD.L	D4,#4		; D4 <-- longueur demande
	LOAD.L	A4,#(A6)+OPDDIS	; A4 <-- ^buffer
	FOS	?RSTATUS	; demande le ^rel !
	JUMP,NE ERFAT
	LOAD.L	A0,(A6)+OPDDIS	; A0 <-- ^descripteur de la fentre <<PREMANANT>>


	LOAD.W	D3,#GRA_RASTER
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADRASTER,A3

	LOAD.W	D3,#GRA_MATRIX
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADMATRIX,A3

	LOAD.W	D3,#GRA_DOT
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADDOT,A3

	LOAD.W	D3,#GRA_TRAME
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADTRAME,A3

	LOAD.W	D3,#GRA_LINE
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADLINE,A3

	LOAD.W	D3,#GRA_ELLIPSE
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADELLIPSE,A3

	LOAD.W	D3,#GRA_FILLO
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADFILLO,A3

	LOAD.W	D3,#GRA_FILLC
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADFILLC,A3

	LOAD.W	D3,#GRA_CLEAR
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADCLEAR,A3

	LOAD.W	D3,#GRA_SET
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADSET,A3

	LOAD.W	D3,#GRA_INV
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADINV,A3

	LOAD.W	D3,#GRA_QXDOT
	LIB_	GETAD
	JUMP,NE ERFAT
	LOAD.L	(A6)+OADQXDOT,A3


	LIB	?AFTIM
	.B	NOCURS		; pas de curseur !
	.B	AFCCMO		; pas de flche-souris
	.B	LOADGC		; charge les caractres standards
	.B	GCTXF
	.B	GCTXS
	.B	GCTXT
	.B	0
	.EVEN
	JUMP,NE ERFAT

	LIB	?AFTIM
	.B	LOADGC		; charge les icnes IBP64
	.B	GCICF
	.B	GCICS
	.B	GCICT
	.B	0
	.EVEN
	JUMP,NE ERFAT

	LIB	?AFTIM
	.B	USEGC		; utilise les icnes IBP64
	.B	GCICF
	.B	GCICS
	.B	GCICT
	.B	0
	.EVEN
	LOAD.L	(A6)+OPGICO,(A0)+ODFPGC
	LIB	?AFTIM
	.B	USEGC		; charge les caractres standard
	.B	GCTXF
	.B	GCTXS
	.B	GCTXT
	.B	0
	.EVEN


	SET.B	(A6)+OINV	; le fond de l'cran est blanc

	LOAD.L	A3,#R16"NMIMA
	CALL	LOADIMAGE	; affiche l'image de fond
	JUMP,NE	ERFAT
	LOAD.L	(A6)+OPIMA,A4
	LOAD.L	(A6)+ODIMA,D4


	LOAD.W	D4,#LYWDO
	LOAD.W	D3,(A0)+ODFDY
	SUB.W	D3,D4
	SR.W	D3,#1
	SWAP.W	D3
	SWAP.W	D4
	LOAD.W	D4,#LXWDO
	LOAD.W	D3,(A0)+ODFDX
	SUB.W	D3,D4
	SR.W	D3,#1
	LIB	?CREWDO		; cre swdo (utile pour SMAKY 8)
	LIB	?USEWDO

AIDE:
	CLR.B	(A6)+OEND
	CLR.B	(A6)+OHELP
	CLR.B	(A6)+OBEGIN

	LOAD.L	A3,#R16"TXMENU0
	LIB	?AFMENU		; affiche les soft-keys

	SET.B	(A6)+OFIXE	; raquette immobile

	LOAD.L	A3,#R16"NHIMA
	CALL	AFIMAGE		; affiche l'image d'aide
	LOAD.L	(A6)+ORAQPO,#H'10000*POSYRAQ+POSXRAQ
	LOAD.W	(A6)+ORAQIN,#5
50$:
	CALL	ACTION		; actionne la raquette ...
	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	FINI
	TEST.B	(A6)+OBEGIN	; dbut de la partie ?
	JUMP,F	50$


	LOAD.L	A3,#R16"TXMENU1
	LIB	?AFMENU		; affiche les soft-keys

	LOAD.L	A3,#R16"NOIMA
	CALL	AFIMAGE		; affiche l'image d'aide
60$:
	LIB	?GETCAR
	COMP.W	D3,#END
	JUMP,EQ FINI
	COMP.W	D3,#F0
	JUMP,EQ FINI
	COMP.W	D3,#F0+SHIFT
	JUMP,EQ FINI

	COMP.W	D3,#F1
	JUMP,EQ 65$
	COMP.W	D3,#F1+SHIFT
	JUMP,EQ 65$
	COMP.W	D3,#F2
	JUMP,EQ 65$
	COMP.W	D3,#F2+SHIFT
	JUMP,EQ 65$
	COMP.W	D3,#F3
	JUMP,EQ 65$
	COMP.W	D3,#F3+SHIFT
	JUMP,EQ 65$
	COMP.W	D3,#SPACE
	JUMP,NE 60$
65$:
	LOAD.L	A3,#R16"TXMENU2
	LIB	?AFMENU		; affiche les soft-keys

	CLR.B	(A6)+OFIXE	; raquette mobile


	LOAD.L	A4,(A6)+OPIMA	; A4 <-- ^image principale
	LOAD.L	D4,(A6)+ODIMA	; D4 <-- dimensions
	CALL	SHOWIMAGE	; affiche l'image de fond

	CLR.L	(A6)+ORAQPO	; la raquette n'existe pas
	CLR.L	(A6)+OASCPO	; l'ascenseur n'existe pas
	LOAD.W	(A6)+OJAUNI,#-1	; jauge pas encore dessine

	CALL	COUPSAC		; gnrateur alatoire: coup de sac

NEW:
	CALL	GACOMPTE	; affiche le nombre de parties gagnes
	CALL	PECOMPTE	; affiche le nombre de parties perdues
	CLR.W	(A6)+OCONNB

	CLR.B	(A6)+OEND
	CLR.B	(A6)+OHELP
	CLR.B	(A6)+OGAIN
	TCLR.B	(A6)+ORAQET:#BRAQC ; une raquette neuve, une !

	LOAD.L	A5,#(A6)+OBALLE
	CALL	ALEAOBJET	; A5 <-- nouvel objet alatoire
	CALL	NEWOBJET	; A5 <-- nouvel objet alatoire

	LOAD.W	D4,#(LXWDO/2)-(IDXRAQ/2)
	CLR.W	D3
	CALL	MOVERAQ		; dessine une raquette en ordre !
	LOAD.L	D4,(A6)+ORAQPO
	CALL	PMOUSE		; et met la souris en place

	LOAD.W	D4,#POSYASC
	SWAP.W	D4
	CALL	MOVEASC		; met l'ascenseur en bas

	CALL	MOVEJAUGE	; met  jour la jauge

	CALL	ANIMLANCE	; lance l'objet ...

30$:
	TEST.B	(A6)+OHELP	; appel  l'aide ?
	JUMP,T	AIDE

	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	FINI

	TEST.B	(A6)+OGAIN	; partie gagne ?
	JUMP,T	50$		; oui => 50$

	LOAD.L	A5,#(A6)+OBALLE
	TEST.B	(A5)+OOBOLD	; objet mort ?
	JUMP,T	60$		; oui => 60$

	TEST.B	(A6)+ORAQET:#BRAQC ; raquette casse ?
	JUMP,BS 65$		; oui => 65$

	CALL	ACTION		; effectue une action ...

	LOAD.L	A5,#(A6)+OBALLE
	CALL	DOWNASC		; descend l'ascenseur
	CALL	MOVEOBJ		; dplace la balle
	CALL	MOVEJAUGE	; met  jour la jauge
	JUMP	30$

50$:				; gagn =>
	INC.W	(A6)+OCONGA	; une partie gagne de plus
	CALL	GACOMPTE	; affiche le nombre de parties gagnes
	INC.W	(A6)+OCONNB

	LOAD.L	A5,#(A6)+OBALLE
	CALL	ANIMASC		; monte l'objet avec l'ascenseur
	JUMP	30$

60$:				; perdu =>
	LOAD.W	D4,#25
61$:
	CALL	ACTION		; attend encore un peu ...
	DEC.W	D4
	JUMP,NE 61$
65$:
	CALL	INVOBJ		; efface la dernire balle !
	CLR.L	(A5)+OOBPOS
	SET.B	(A5)+OOBNEW

	TEST.W	(A6)+OCONNB	; une ou plusieures parties gagnes ?
	JUMP,NE 70$		; oui => 70$
				; non =>
	INC.W	(A6)+OCONPE	; une partie perdue de plus
	CALL	PECOMPTE	; affiche le nombre de parties perdues
70$:
	CLR.B	(A6)+OEND
	CLR.B	(A6)+OHELP
	CLR.B	(A6)+OBEGIN

	CALL	SETLANCE	; affiche un texte
	LOAD.L	A3,#R16"TXMENU3
	LIB	?AFMENU		; affiche les soft-keys
72$:
	CALL	ACTION		; attend une touche ...
	TEST.B	(A6)+OHELP	; appel  l'aide ?
	JUMP,T	AIDE
	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	FINI
	TEST.B	(A6)+OBEGIN	; lance une nouvelle balle ?
	JUMP,F	72$

	CALL	CLRLANCE	; efface le texte
	LOAD.L	A3,#R16"TXMENU2
	LIB	?AFMENU		; affiche les soft-keys
	JUMP	NEW


FINI:
	TEST.L	(A6)+OPIMA
	JUMP,EQ 20$
	LOAD.L	A4,(A6)+OPIMA
	CALL	KILLIMAGE	; libre l'image
20$:
	LOAD.L	A4,A6
	LOAD.W	D1,#MTYPCP
	GESMEM	?GIVMEM		; libre la mmoire des variables

ERFAT:
	LIB	?AFTIM
	.B	AFSCMO		; remet la flche-souris
	.B	KILLGC		; libre les icnes IBP64
	.B	GCICF
	.B	GCICS
	.B	GCICT
	.B	0
	.EVEN

	.IF	~IFSMILE
	LIB	?CLOLIB
	FOS	?STOP
	.ELSE
	EXIT
	.ENDIF




;--------\\
; ACTION  >
;========/

; Agit selon un vnement clavier/souris.

; in	-
; out	D7.W	EQ => action effectue
;		NE => pas d'action (timeout)
; mod	D7.W

ACTION:
	PUSHM.L	D0..D6,A0..A5

	LOAD.W	D4,#TIMING
	NTREL	?SETTIM		; met timeout pour 25 images/seconde
	LIB	?GETKEY		; attend clavier/souris ...
	LOAD.W	D0,D7
	LOAD.W	D4,#-1
	NTREL	?SETTIM		; remet timeout infini
	TEST.W	D0
	JUMP,NE MOREPEAT

	TEST.L	D3:#BKPSEUDO
	JUMP,BS ENDACTION

	COMP.W	D3,#KEYMPO
	JUMP,EQ MOMOVE
	COMP.W	D3,#KEYMDP
	JUMP,EQ MOLEFTP
	COMP.W	D3,#KEYMDR
	JUMP,EQ MOLEFTR
	COMP.W	D3,#KEYMGP
	JUMP,EQ MORIGHTP
	COMP.W	D3,#KEYMGR
	JUMP,EQ MORIGHTR

	COMP.W	D3,#END
	JUMP,EQ DOEND
	COMP.W	D3,#F0
	JUMP,EQ DOEND
	COMP.W	D3,#F0+SHIFT
	JUMP,EQ DOEND

	COMP.W	D3,#F1
	JUMP,EQ DOBEGIN
	COMP.W	D3,#F1+SHIFT
	JUMP,EQ DOBEGIN
	COMP.W	D3,#F2
	JUMP,EQ DOBEGIN
	COMP.W	D3,#F2+SHIFT
	JUMP,EQ DOBEGIN
	COMP.W	D3,#F3
	JUMP,EQ DOBEGIN
	COMP.W	D3,#F3+SHIFT
	JUMP,EQ DOBEGIN
	COMP.W	D3,#KEYMMP
	JUMP,EQ DOBEGIN1
	COMP.W	D3,#SPACE
	JUMP,EQ DOBEGIN

	COMP.W	D3,#F13
	JUMP,EQ DOHELP
	COMP.W	D3,#F13+SHIFT
	JUMP,EQ DOHELP
	COMP.W	D3,#F14
	JUMP,EQ DOHELP
	COMP.W	D3,#F14+SHIFT
	JUMP,EQ DOHELP
	COMP.W	D3,#F15
	JUMP,EQ DOHELP
	COMP.W	D3,#F15+SHIFT
	JUMP,EQ DOHELP
	COMP.W	D3,#HELP
	JUMP,EQ DOHELP

	JUMP	ENDACTION



MOREPEAT:			; rpte ventuellement qq chose =>
	TEST.B	(A6)+ORAQET:#BRAQL
	JUMP,BS MOLEFTP
	TEST.B	(A6)+ORAQET:#BRAQR
	JUMP,BS MORIGHTP
	JUMP	ENDACTION

MOMOVE:				; souris dplace =>
	CALL	IFMOUSE		; D4 <-- position de la souris
	JUMP,NE ENDACTION
	LOAD.W	D3,(A6)+ORAQIN	; D3 <-- inclinaison
	CALL	MOVERAQ		; dplace la raquette
	LOAD.L	D4,(A6)+ORAQPO
	CALL	PMOUSE		; met la souris o est la raquette !
	JUMP	MOREPEAT


MOLEFTP:			; [GAUCHE] press =>
	TSET.B	(A6)+ORAQET:#BRAQL
	LOAD.L	D4,(A6)+ORAQPO
	LOAD.W	D3,(A6)+ORAQIN
	ADD.W	D3,#+1
	COMP.W	D3,#+MAXIRAQ
	JUMP,LT 50$
	LOAD.W	D3,#+MAXIRAQ
	TCLR.B	(A6)+ORAQET:#BRAQL
50$:
	CALL	MOVERAQ		; dplace la raquette
	JUMP	ENDACTION

MOLEFTR:			; [GAUCHE] relch =>
	TCLR.B	(A6)+ORAQET:#BRAQL
	JUMP	ENDACTION

MORIGHTP:			; [DROITE] press =>
	TSET.B	(A6)+ORAQET:#BRAQR
	LOAD.L	D4,(A6)+ORAQPO
	LOAD.W	D3,(A6)+ORAQIN
	ADD.W	D3,#-1
	COMP.W	D3,#-MAXIRAQ
	JUMP,GT 50$
	LOAD.W	D3,#-MAXIRAQ
	TCLR.B	(A6)+ORAQET:#BRAQR
50$:
	CALL	MOVERAQ		; dplace la raquette
	JUMP	ENDACTION

MORIGHTR:			; [DROITE] relch =>
	TCLR.B	(A6)+ORAQET:#BRAQR
	JUMP	ENDACTION

DOEND:
	SET.B	(A6)+OEND	; signal la fin de la partie
	JUMP	ENDACTION

DOBEGIN:
	SET.B	(A6)+OBEGIN	; signal la dbut de la partie
	JUMP	ENDACTION

DOBEGIN1:
	TEST.B	(A6)+OFIXE	; raquette immobile ?
	JUMP,T	ENDACTION	; oui => ENDACTION
	SET.B	(A6)+OBEGIN	; signal la dbut de la partie
	JUMP	ENDACTION

DOHELP:
	SET.B	(A6)+OHELP	; signal un appel  l'aide
	SET.B	(A6)+OEND	; signal la fin de la partie
	JUMP	ENDACTION

ENDACTION:
	LOAD.W	D7,D0		; D7 <-- action ou pas

	POPM.L	D0..D6,A0..A5
	TEST.W	D7		; retour EQ/NE
	RET




;---------\\
; SETLANCE >
;=========/

; Affiche un texte d'aide au milieu de l'cran de jeu.

; in	-
; out	-
; mod	D7.W

SETLANCE:
	PUSHM.L	D2..D4

	TEST.B	(A6)+OINV	; fond de l'cran blanc ?
	JUMP,F	10$		; non => 10$
	LOAD.B	D3,#AFINV
	LIB	?AFCAR
10$:
	LOAD.L	D3,#H'10000*200+200
	LIB	?SETCURS

	LIB	?AFTIM
	.ASCIZ	"Le bouton du milieu de la souris"
	.EVEN

	SWAP.W	D3
	ADD.W	D3,(A0)+ODFCY
	SWAP.W	D3
	LIB	?SETCURS

	LIB	?AFTIM
	.ASCIZ	"lance une nouvelle balle ..."
	.EVEN

	LOAD.B	D3,#AFDIR
	LIB	?AFCAR

	LOAD.L	D3,#H'10000*174+182
	LOAD.L	D4,#H'10000*60+290
	LOAD.W	D2,#INVDOT
	LIB	?DRRECT

	ADD.W	D3,#2
	SWAP.W	D3
	ADD.W	D3,#2
	SWAP.W	D3
	SUB.W	D4,#3
	SWAP.W	D4
	SUB.W	D4,#3
	SWAP.W	D4
	CALL	DRINV

	POPM.L	D2..D4
	RET

;---------\\
; CLRLANCE >
;=========/

; Efface un texte d'aide au milieu de l'cran de jeu.

; in	-
; out	-
; mod	D7.W

CLRLANCE:
	PUSHM.L	D2..D4

	LOAD.L	D3,#H'10000*174+182
	LOAD.L	D4,#H'10000*61+291
	LOAD.W	D2,#INVDOT
	CALL	DRCLEAR

	POPM.L	D2..D4
	RET



;----------\\
; ALEAOBJET >
;==========/

; Choisi un nouvel objet alatoirement.

; in	A5.L	^description de l'objet
; out	-
; mod	D7.W

ALEAOBJET:
	PUSHM.L	D3,D4,A4

	LOAD.L	A4,#(A6)+OHAZEX
	LOAD.W	D3,#0
	LOAD.W	D4,#NTAOBJET
	CALL	EXHAZARD	; tirage exclusif
	LOAD.L	A4,#R16"TAOBJET
	MUL.WU	D4,#LTAOBJET
	ADD.L	A4,D4		; A4 <-- ^objet

	LOAD.W	D3,(A4+)
	LOAD.B	(A5)+OOBICO,D3
	LOAD.W	(A5)+OOBDIM+2,(A4+)
	LOAD.W	(A5)+OOBDIM+0,(A4+)
	LOAD.W	(A5)+OOBCHO+2,(A4+)
	LOAD.W	(A5)+OOBCHO+0,(A4+)
	LOAD.W	(A5)+OOBACC,(A4+)
	LOAD.W	(A5)+OOBVIM,(A4+)
	LOAD.W	(A5)+OOBMU1,(A4+)
	LOAD.W	(A5)+OOBMU2,(A4+)
	LOAD.W	(A5)+OOBMU3,(A4+)

	POPM.L	D3,D4,A4
	RET

TAOBJET:
	.W	ICOBALLE0
	.W	IDXBALLE0,IDYBALLE0
	.W	4,4
	.W	3
	.W	200
	.W	TMUSCOLB0-TMUS
	.W	TMUSCOLR0-TMUS
	.W	TMUSENDB0-TMUS
LTAOBJET = .-TAOBJET
	.W	ICOBALLE1
	.W	IDXBALLE1,IDYBALLE1
	.W	1,1
	.W	1
	.W	300
	.W	TMUSCOLB1-TMUS
	.W	TMUSCOLR1-TMUS
	.W	TMUSENDB1-TMUS

	.W	ICOBALLE2
	.W	IDXBALLE2,IDYBALLE2
	.W	1,1
	.W	1
	.W	350
	.W	TMUSCOLB2-TMUS
	.W	TMUSCOLR2-TMUS
	.W	TMUSENDB2-TMUS

	.W	ICOBALLE3
	.W	IDXBALLE3,IDYBALLE3
	.W	1,1
	.W	3
	.W	300
	.W	TMUSCOLB3-TMUS
	.W	TMUSCOLR3-TMUS
	.W	TMUSENDB3-TMUS

	.W	ICOBALLE4
	.W	IDXBALLE4,IDYBALLE4
	.W	4,4
	.W	4
	.W	200
	.W	TMUSCOLB4-TMUS
	.W	TMUSCOLR4-TMUS
	.W	TMUSENDB4-TMUS

	.W	ICOBALLE5
	.W	IDXBALLE5,IDYBALLE5
	.W	2,2
	.W	2
	.W	200
	.W	TMUSCOLB5-TMUS
	.W	TMUSCOLR5-TMUS
	.W	TMUSENDB5-TMUS

	.W	ICOBALLE6
	.W	IDXBALLE6,IDYBALLE6
	.W	3,3
	.W	2
	.W	200
	.W	TMUSCOLB6-TMUS
	.W	TMUSCOLR6-TMUS
	.W	TMUSENDB6-TMUS
NTAOBJET = (.-TAOBJET)/LTAOBJET


;---------\\
; NEWOBJET >
;=========/

; Initialise un nouvel objet de faon alatoire.

; in	A5.L	^descripteur de l'objet
; out	-
; mod	D7.W

NEWOBJET:
	PUSHM.L	D3,D4

	LOAD.W	D3,#MARGG+20
	LOAD.W	D4,#LXWDO-MARGD-200
	SUB.W	D4,(A5)+OOBDIM+2
	CALL	MMHAZARD
	LOAD.W	(A5)+OOBPOS+2,D4
	CLR.W	(A5)+OOBPOS+0
30$:
	LOAD.W	D3,#-10
	LOAD.W	D4,#+10
	CALL	MMHAZARD
	TEST.W	D4
	JUMP,EQ 30$
	LOAD.W	(A5)+OOBVIT+2,D4

	LOAD.W	D3,#+1
	LOAD.W	D4,#+6
	CALL	MMHAZARD
	LOAD.W	(A5)+OOBVIT+0,D4

	LOAD.W	(A5)+OOBVIE,(A5)+OOBVIM

	CLR.W	(A5)+OOBFIN
	CLR.W	(A5)+OOBVIF
	SET.B	(A5)+OOBNEW	; nouvel objet
	CLR.B	(A5)+OOBOLD	; pas encore mort

	POPM.L	D3,D4
	RET



;----------\\
; ANIMLANCE >
;==========/

; Anime le nouvement de lancement d'un objet quelconque.

; in	A5.L	^description de l'objet  lancer
;	D4.W	position de lancement (en X)
; out	-
; mod	D7.W

ANIMLANCE:
	PUSHM.L	D0..D4,A3

	LOAD.W	D1,(A5)+OOBPOS+2 ; D1 ;-- position d'arrive
	LOAD.W	D2,#MARGG+20	; D2 <-- position de dpart

	LOAD.B	D3,#ICOLANCE	; D3 <-- code icne lanceur  droite
	TEST.W	(A5)+OOBVIT+2
	JUMP,NC 20$
	ADD.B	D3,#8		; D3 <-- code icne lanceur  gauche

; Dplace le lanceur sur le position de lancement.

20$:
	LOAD.L	A3,#R16"TMUSLANAV
	CALL	PATATRA

	LOAD.W	D4,D2
	CALL	MOVOLANCE	; dplace le lanceur avec l'objet

	CALL	ACTION		; effectue une action ...
	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	90$		; oui => 90$

	ADD.W	D2,#6		; D2 <-- avance de gauche  droite
	COMP.W	D2,D1
	JUMP,LO 20$

; Lance l'objet.

	LOAD.L	A3,#R16"TMUSLANPR
	CALL	PATATRA

	LOAD.W	D1,#8
40$:
	LOAD.W	D4,D2
	CALL	MOVOLANCE	; dplace le lanceur avec l'objet

	CALL	ACTION		; effectue une action ...
	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	90$		; oui => 90$

	INC.B	D3		; D3 <-- animation suivante
	DEC.W	D1
	JUMP,NE 40$
90$:
	POPM.L	D0..D4,A3
	RET

;----------\\
; MOVOLANCE >
;==========/

; Dplace le lanceur avec l'objet.

; in	A5.L	^description de l'objet
;	D4.W	nouvelle position (en X)
;	D3.B	code de l'icne
; out	-
; mod	D7.W

MOVOLANCE:
	PUSHM.L	D0..D5

	LOAD.W	(A5)+OOBPOS+0,#MARGG+(IDYLANCE-22)
	SWAP.W	D4
	LOAD.W	D4,#MARGH	; D4 <-- impose la position en Y
	SWAP.W	D4
	LOAD.L	D0,D4		; D0 <-- nouvelle position
	LOAD.B	D1,D3		; D1 <-- icne

	TEST.L	(A6)+OLANPO
	JUMP,EQ 40$

	TEST.B	(A5)+OOBNEW
	JUMP,T	10$
	PUSHM.L	D3,D4
	LOAD.L	D4,(A6)+OLANPO
	LOAD.B	D3,(A6)+OLANIC
	CALL	INVLOBJ		; efface l'objet dans le lanceur
	POPM.L	D3,D4
10$:
	COMP.W	D4,(A6)+OLANPO+2 ; nouvelle position en X ?
	JUMP,EQ 30$		; non => 30$
	JUMP,LO 20$

; Remet un bout d'image avant le lanceur.

	SUB.W	D4,(A6)+OLANPO+2
	SWAP.W	D4
	LOAD.W	D4,#IDYLANCE
	SWAP.W	D4
	LOAD.L	D3,(A6)+OLANPO
	CALL	SAVEIMAGE
	JUMP	30$

; Remet un bout d'image aprs le lanceur.

20$:
	LOAD.L	D3,D4
	LOAD.W	D4,(A6)+OLANPO+2
	SUB.W	D4,D3
	SWAP.W	D4
	LOAD.W	D4,#IDYLANCE
	SWAP.W	D4
	ADD.W	D3,#IDXLANCE
	CALL	SAVEIMAGE

; Dessine le nouveau lanceur.

30$:
;;?	TEST.B	(A5)+OOBNEW
;;?	JUMP,T	40$
;;?	PUSHM.L	D3,D4
;;?	LOAD.L	D4,(A6)+OLANPO
;;?	LOAD.B	D3,(A6)+OLANIC
;;?	CALL	INVLOBJ		; efface l'objet dans le lanceur
;;?	POPM.L	D3,D4
40$:
	LOAD.B	D3,D1		; D3 <-- code de l'icne
	LOAD.L	D4,D0		; D4 <-- nouvelle position
	LOAD.L	D5,#H'10000*IDYLANCE+IDXLANCE
	LOAD.W	D2,#SETDOT	; D2 <-- mode "load"
	CALL	DRICONE		; dessine le nouveau lanceur

	CALL	INVLOBJ		; dessine l'objet dans le lanceur
	CLR.B	(A5)+OOBNEW

	LOAD.L	(A6)+OLANPO,D4	; mm. la nouvelle position
	LOAD.B	(A6)+OLANIC,D3	; mm. la nouvelle icne
90$:
	POPM.L	D0..D5
	RET

;----------\\
; MOVELANCE >
;==========/

; Dplace le lanceur tout seul.

; in	D4.W	nouvelle position (en X)
;	D3.B	code de l'icne
; out	-
; mod	D7.W

MOVELANCE:
	PUSHM.L	D0..D6,A5

	SWAP.W	D4
	LOAD.W	D4,#MARGH	; D4 <-- impose la position en Y
	SWAP.W	D4
	LOAD.L	D0,D4		; D0 <-- nouvelle position
	LOAD.B	D1,D3		; D1 <-- icne

	TEST.L	(A6)+OLANPO
	JUMP,EQ 40$

	LOAD.L	A5,#(A6)+OBALLE

	PUSH.L	D4
	LOAD.L	D3,(A6)+OLANPO
	LOAD.L	D4,#H'10000*IDYLANCE+IDXLANCE
	CALL	DETOBJ		; balle recoupe l'ancien lanceur ?
	LOAD.W	D6,D7		; D6 <-- zro si pas de collision
	POP.L	D4

	TEST.W	D6
	JUMP,NE 14$

	PUSH.L	D4
	LOAD.L	D3,D4
	LOAD.L	D4,#H'10000*IDYLANCE+IDXLANCE
	CALL	DETOBJ		; balle recoupe le nouveau lanceur ?
	LOAD.W	D6,D7		; D6 <-- zro si pas de collision
	POP.L	D4
14$:
	TEST.W	D6
	JUMP,EQ 16$
	CALL	INVOBJ		; efface la balle
16$:
	COMP.W	D4,(A6)+OLANPO+2 ; nouvelle position en X ?
	JUMP,EQ 40$		; non => 40$
	JUMP,LO 20$

; Remet un bout d'image avant le lanceur.

	SUB.W	D4,(A6)+OLANPO+2
	SWAP.W	D4
	LOAD.W	D4,#IDYLANCE
	SWAP.W	D4
	LOAD.L	D3,(A6)+OLANPO
	CALL	SAVEIMAGE
	JUMP	40$

; Remet un bout d'image aprs le lanceur.

20$:
	LOAD.L	D3,D4
	LOAD.W	D4,(A6)+OLANPO+2
	SUB.W	D4,D3
	SWAP.W	D4
	LOAD.W	D4,#IDYLANCE
	SWAP.W	D4
	ADD.W	D3,#IDXLANCE
	CALL	SAVEIMAGE

; Dessine le nouveau lanceur.

40$:
	LOAD.B	D3,D1		; D3 <-- code de l'icne
	LOAD.L	D4,D0		; D4 <-- nouvelle position
	LOAD.L	D5,#H'10000*IDYLANCE+IDXLANCE
	LOAD.W	D2,#SETDOT	; D2 <-- mode "load"
	CALL	DRICONE		; dessine le nouveau lanceur

	LOAD.L	(A6)+OLANPO,D4	; mm. la nouvelle position
	LOAD.B	(A6)+OLANIC,D3	; mm. la nouvelle icne

	TEST.W	D6
	JUMP,EQ 90$
	CALL	INVOBJ		; remet la balle
90$:
	POPM.L	D0..D6,A5
	RET

;--------\\
; INVLOBJ >
;--------/

; Inverse l'objet sur le lanceur.

; in	A5.L	^description de l'objet
;	D3.B	code de l'icne lanceur
;	D4.L	position du lanceur
; out	-
; mod	D7.W

INVLOBJ:
	PUSHM.L	D2..D5,A3

	CLR.W	D2
	COMP.B	D3,#ICOLANCE+8	; lance  gauche ?
	JUMP,LO 10$		; non => 10$
	LOAD.W	D2,(A5)+OOBDIM+2 ; oui => tient compte de la largeur de l'objet
10$:
	LOAD.L	A3,#R16"TALOBJ
	SUB.B	D3,#ICOLANCE	; D3 <-- 0..n
	AND.W	D3,#H'00FF
	SL.W	D3,#2		; D3 <-- *4 car table de 2x .W

	SUB.W	D4,D2
	ADD.W	D4,(A3)+(D3.W)+2
	SWAP.W	D4
	ADD.W	D4,(A3)+(D3.W)+0
	SWAP.W	D4

	CALL	GETICONE	; D2 <-- code de l'icne
	LOAD.B	D3,D2		; D3 <-- code de l'icne
	LOAD.W	D2,#INVDOT	; D2 <-- mode
	LOAD.L	D5,(A5)+OOBDIM	; D5 <-- dimensions
	CALL	DRICONE		; inverse l'icne

	LOAD.L	(A5)+OOBPOS,D4

	POPM.L	D2..D5,A3
	RET

TALOBJ:
	.W	IDYLANCE-23,8
	.W	IDYLANCE-23,12
	.W	IDYLANCE-23,16
	.W	IDYLANCE-23,20
	.W	IDYLANCE-23,24
	.W	IDYLANCE-23,28
	.W	IDYLANCE-23,32
	.W	IDYLANCE-23,36

	.W	IDYLANCE-23,56
	.W	IDYLANCE-23,54
	.W	IDYLANCE-23,52
	.W	IDYLANCE-23,48
	.W	IDYLANCE-23,44
	.W	IDYLANCE-23,40
	.W	IDYLANCE-23,36
	.W	IDYLANCE-23,32


;----------\\
; SAVEIMAGE >
;==========/

; Remet un bout de l'image initiale.

; in	D3.L	position (y,x)
;	D4.L	dimensions (dy,dx)
; out	-
; mod	D7.W

SAVEIMAGE:
	PUSHM.L	D1..D6,A3,A4

	LOAD.L	D1,D4		; D1 <-- dimensions

	LOAD.L	A3,(A6)+OPIMA	; A3 <-- ^image source
	LOAD.W	D5,#LXWDO/8	; D5 <-- ii source

	LOAD.L	D4,D3		; D4 <-- position destination
	LOAD.L	A4,#0		; destination dans l'cran
	LOAD.W	D6,#0		; D6 <-- ii destination

	LOAD.W	D2,#SETDOT
	CALL	DRRASTER

	EX.L	A4,A3
	CALL	INVLIMAGE
	EX.L	A3,A4

	LOAD.W	D2,#CLRDOT
	CALL	DRRASTER

	EX.L	A4,A3
	CALL	INVLIMAGE
;	EX.L	A3,A4

	POPM.L	D1..D6,A3,A4
	RET

;----------\\
; INVLIMAGE >
;----------/

; Inverse l'image rapidement, jusqu'au bas du lanceur.

; in	A4.L	^image
; out	-
; mod	D7.W

INVLIMAGE:
	PUSHM.L	D4,A4

	LOAD.W	D4,#((LXWDO*(MARGH+IDYLANCE))/(8*4))-1
20$:
	NOT.L	(A4+)
	DECJ.W,NMO D4,20$

	POPM.L	D4,A4
	RET


;--------\\
; DOWNASC >
;========/

; Descend l'ascenseur.

; in	-
; out	-
; mod	D7.W

DOWNASC:
	PUSH.L	D4

	TEST.W	(A6)+OASCDD	; dlai avant de descendre ?
	JUMP,EQ 20$		; dj coul => 20$

	DEC.W	(A6)+OASCDD
	JUMP	90$

20$:
	LOAD.L	D4,(A6)+OASCPO
	SWAP.W	D4
	COMP.W	D4,#POSYASC
	JUMP,EQ 90$

	ADD.W	D4,#2		; D4 <-- descend (len-te-ment...)
	COMP.W	D4,#POSYASC
	JUMP,LS 50$
	LOAD.W	D4,#POSYASC
50$:
	SWAP.W	D4
	CALL	MOVEASC		; descend l'ascenseur
90$:
	POP.L	D4
	RET

;--------\\
; ANIMASC >
;========/

; Anime l'ascenseur pour remettre l'objet dans le lanceur.

; in	A5.L	^description de l'objet
; out	-
; mod	D7.W

ANIMASC:
	PUSHM.L	D0..D4,A3

	LOAD.L	A3,#R16"TMUSYOUPIE
	CALL	PATATRA		; bruit

	LOAD.W	D4,#20
05$:
	CALL	ACTION		; effectue une action ...
	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	90$		; oui => 90$

	DEC.W	D4
	JUMP,NE 05$

; Monte l'ascenseur tout en dplaant le lanceur vers la droite.

	LOAD.W	D0,(A5)+OOBDIM+0
	ADD.W	D0,#MARGH-9	; D0 <-- hauteur pour l'ascenseur

	LOAD.W	D1,#LXWDO-MARGD-58
	SUB.W	D1,(A5)+OOBDIM+2 ; D1 <-- position pour le lanceur

	LOAD.W	D2,(A5)+OOBDIM+2
	MUL.WU	D2,#9		; D2 <-- priode initiale pour le bruit
10$:
	COMP.W	D0,(A6)+OASCPO+0 ; ascenseur en haut ?
	JUMP,NE 20$

	COMP.W	D1,(A6)+OLANPO+2 ; lanceur  droite ?
	JUMP,EQ 30$
20$:
	LOAD.L	D4,(A6)+OASCPO
	SWAP.W	D4
	SUB.W	D4,#8		; D4 <-- monte l'ascenseur
	COMP.W	D4,D0
	JUMP,HI 22$
	LOAD.W	D4,D0
22$:
	SWAP.W	D4
	CALL	MOVOASC		; dplace l'ascenseur avec l'objet

	LOAD.L	D4,(A6)+OLANPO
	ADD.W	D4,#12		; D4 <-- dplace le lanceur  droite
	COMP.W	D4,D1
	JUMP,LO 24$
	LOAD.W	D4,D1
24$:
	LOAD.B	D3,#ICOLANCE+7
	CALL	MOVELANCE	; dplace le lanceur sans l'objet

	CALL	ACTION		; effectue une action ...
	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	90$		; oui => 90$

	COMP.W	D0,(A6)+OASCPO+0 ; ascenseur en haut ?
	JUMP,EQ 28$		; oui => 28$

	SUB.W	D2,#10		; D2 <-- augmente la frquence
	PUSHM.L	D3..D6
	LOAD.W	D3,D2
	OR.W	D3,#PERIODE
	LOAD.W	D4,#SILENCE
	LOAD.W	D5,#SILENCE
	LOAD.W	D6,#H'100*255+1
	LIB	?ACCORD		; bruit lorsque l'ascenseur monte
	POPM.L	D3..D6
	JUMP	10$

28$:
	LOAD.L	A3,#R16"TMUSLANAV
	CALL	PATATRA
	JUMP	10$

; Tire le levier du lanceur.

30$:
	LOAD.L	D4,(A6)+OLANPO
	CALL	MOVOLANCE

	CALL	ACTION		; effectue une action ...
	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	90$		; oui => 90$

	CALL	ACTION		; effectue une action ...
	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	90$		; oui => 90$

	DEC.B	D3
	COMP.B	D3,#ICOLANCE
	JUMP,HS 30$

; Relance l'objet une nouvelle fois en dplaant le lanceur sur
; la position de dpart.

	CALL	INVOBJ		; efface l'objet

	CALL	NEWOBJET	; A5 <-- nouvel objet alatoire
	TEST.W	(A5)+OOBVIT+2
	JUMP,NC 35$
	NEG.W	(A5)+OOBVIT+2	; relance toujours  droite !
35$:
	LOAD.W	D1,(A5)+OOBPOS+2 ; D1 ;-- position d'arrive
	LOAD.W	D2,(A6)+OLANPO+2 ; D2 <-- position de dpart

	LOAD.W	(A6)+OASCDD,#20	; init dlai avant de descendre l'ascenseur
	LOAD.B	D3,#ICOLANCE	; D3 <-- code icne lanceur  droite
40$:
	LOAD.L	A3,#R16"TMUSLANAV
	CALL	PATATRA

	LOAD.W	D4,D2
	CALL	MOVOLANCE	; dplace le lanceur avec l'objet
	CALL	DOWNASC		; redescend l'ascenseur

	CALL	ACTION		; effectue une action ...
	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	90$		; oui => 90$

	SUB.W	D2,#8		; D2 <-- avance de droite  gauche
	COMP.W	D2,D1
	JUMP,HI 40$

; Lance l'objet.

	LOAD.L	A3,#R16"TMUSLANPR
	CALL	PATATRA

	LOAD.W	D1,#8
50$:
	LOAD.W	D4,D2
	CALL	MOVOLANCE	; dplace le lanceur avec l'objet
	CALL	DOWNASC		; redescend l'ascenseur

	CALL	ACTION		; effectue une action ...
	TEST.B	(A6)+OEND	; fin de la partie ?
	JUMP,T	90$		; oui => 90$

	INC.B	D3		; D3 <-- animation suivante
	DEC.W	D1
	JUMP,NE 50$

	CLR.B	(A6)+OGAIN	; nouvelle partie: ce n'est pas encore gagn !
90$:
	POPM.L	D0..D4,A3
	RET

;--------\\
; MOVOASC >
;========/

; Dplace l'ascenseur avec l'objet.

; in	D4.L	nouvelle position (y;-)
; out	-
; mod	D7.W

MOVOASC:
	PUSHM.L	D1..D5,A5

	LOAD.W	D4,#LXWDO-MARGD-IDXASC ; D4 <-- ascenseur toujours  droite

	COMP.L	D4,(A6)+OASCPO
	JUMP,EQ 90$

	LOAD.L	A5,#(A6)+OBALLE

	TEST.B	(A6)+OGAIN	; partie gagne ?
	JUMP,F	40$		; non => 40$
				; oui =>
	PUSH.L	D4
	LOAD.L	D4,(A6)+OASCPO
	CALL	INVAOBJ		; efface l'objet dans l'ascenseur
	POP.L	D4
40$:
	LOAD.B	D2,#ICOASC	; D2 <-- code de l'icne
	LOAD.L	D5,#H'10000*IDYASC+IDXASC ; D5 <-- dimensions
	LOAD.L	D3,(A6)+OASCPO	; D3 <-- ancienne position
	CALL	MOVELICONE	; dplace l'icne
	LOAD.L	(A6)+OASCPO,D4

	TEST.B	(A6)+OGAIN	; partie gagne ?
	JUMP,F	90$		; non => 90$
				; oui =>
	CALL	INVAOBJ		; remet l'objet dans l'ascenseur
90$:
	POPM.L	D1..D5,A5
	RET

;--------\\
; MOVEASC >
;========/

; Dplace l'ascenseur tout seul.

; in	D4.L	nouvelle position (y;-)
; out	-
; mod	D7.W

MOVEASC:
	PUSHM.L	D1..D5,A5

	LOAD.W	D4,#LXWDO-MARGD-IDXASC ; D4 <-- ascenseur toujours  droite

	COMP.L	D4,(A6)+OASCPO
	JUMP,EQ 90$

	LOAD.L	A5,#(A6)+OBALLE

	PUSH.L	D4
	LOAD.L	D3,(A6)+OASCPO
	LOAD.L	D4,#H'10000*IDYASC+IDXASC
	CALL	DETOBJ		; balle recoupe l'ancien ascenseur ?
	LOAD.W	D1,D7		; D1 <-- zro si pas de collision
	POP.L	D4

	TEST.W	D1
	JUMP,NE 20$

	PUSH.L	D4
	LOAD.L	D3,D4
	LOAD.L	D4,#H'10000*IDYASC+IDXASC
	CALL	DETOBJ		; balle recoupe le nouvel ascenseur ?
	LOAD.W	D1,D7		; D1 <-- zro si pas de collision
	POP.L	D4
20$:
	TEST.W	D1
	JUMP,EQ 40$
	CALL	INVOBJ		; efface la balle
40$:
	LOAD.B	D2,#ICOASC	; D2 <-- code de l'icne
	LOAD.L	D5,#H'10000*IDYASC+IDXASC ; D5 <-- dimensions
	LOAD.L	D3,(A6)+OASCPO	; D3 <-- ancienne position
	CALL	MOVELICONE	; dplace l'icne
	LOAD.L	(A6)+OASCPO,D4

	TEST.W	D1
	JUMP,EQ 90$
	CALL	INVOBJ		; remet la balle
90$:
	POPM.L	D1..D5,A5
	RET

;--------\\
; INVAOBJ >
;--------/

; Inverse l'objet sur l'ascenseur.

; in	A5.L	^description de l'objet
;	D4.L	position de l'ascenseur
; out	-
; mod	D7.W

INVAOBJ:
	PUSHM.L	D2..D5

	ADD.W	D4,#42
	SUB.W	D4,(A5)+OOBDIM+2
	SWAP.W	D4
	ADD.W	D4,#IDYASC-14
	SUB.W	D4,(A5)+OOBDIM+0
	SWAP.W	D4

	CALL	GETICONE	; D2 <-- code de l'icne
	LOAD.B	D3,D2		; D3 <-- code de l'icne
	LOAD.W	D2,#INVDOT	; D2 <-- mode
	LOAD.L	D5,(A5)+OOBDIM	; D5 <-- dimensions
	CALL	DRICONE		; inverse l'icne

	LOAD.L	(A5)+OOBPOS,D4

	POPM.L	D2..D5
	RET



;--------\\
; MOVEOBJ >
;========/

; Dplace un objet.

; in	A5.L	^descripteur de l'objet
; out	-
; mod	D7.W

MOVEOBJ:
	PUSHM.L	D2..D5

	LOAD.L	D4,(A5)+OOBPOS	; D4 <-- position actuelle
	LOAD.L	D2,D4
	ADD.W	D4,(A5)+OOBVIT+2
	SWAP.W	D4
	ADD.W	D4,(A5)+OOBVIT+0
	SWAP.W	D4

	CALL	BORDOBJ		; choc (oh l) avec un bord ?
	CALL	FONDOBJ		; glisse sur le fond
	CALL	ASCOBJ		; choc avec l'ascenseur ?
	CALL	RAQOBJ		; choc avec la raquette ?

;;?	TEST.B	(A6)+ORAQET:#BRAQC ; raquette casse ?
;;?	JUMP,BS 90$		; oui => 90$

	TEST.W	(A5)+OOBVIE	; objet en vie ?
	JUMP,NE 40$		; oui => 40$
				; non =>
	LOAD.L	D4,D2		; D4 <-- ne le dplace plus du tout
40$:
	LOAD.L	D3,(A5)+OOBPOS	; D3 <-- ancienne position
	LOAD.L	D5,(A5)+OOBDIM	; D5 <-- dimensions
	CALL	MOVEIICONE	; dplace l'objet
	LOAD.L	(A5)+OOBPOS,D4	; mm. nouvelle position

	LOAD.W	D4,(A5)+OOBACC
	ADD.W	(A5)+OOBVIT+0,D4 ; tient compte de la pesanteur !
90$:
	POPM.L	D2..D5
	RET

;--------\\
; BORDOBJ >
;--------/

; Teste une collision avec un bord de la fentre.

; in	A5.L	^descripteur de l'objet
;	D4.L	position (y;x)
; out	D4.L	position (y;x)
; mod	D4.L, D7.W

BORDOBJ:
	PUSHM.L	D2,D3

	CLR.W	D2		; D2 <-- pas de collision
	SWAP.W	D4

; Teste une collision avec le sol.

	LOAD.W	D3,(A0)+ODFFDY
	SUB.W	D3,#MARGB
	SUB.W	D3,(A5)+OOBDIM+0
	COMP.W	D4,D3		; collision avec le sol ?
	JUMP,LT 20$
	LOAD.W	D4,D3

	COMP.W	D4,(A5)+OOBPOS+0
	JUMP,NE 14$
	DEC.W	D2		; D2 <-- ne fait pas de bruit !
14$:
	LOAD.W	D3,(A5)+OOBVIT+0
	NEG.W	D3		; inverse la vitesse Vy
	ADD.W	D3,(A5)+OOBCHO+0
	JUMP,NS 15$
	CLR.W	D3
15$:
	LOAD.W	(A5)+OOBVIT+0,D3

	INC.W	D2		; D2 <-- une collision

; Teste une collision avec le plafond.

20$:
	LOAD.W	D3,#MARGH
	COMP.W	D4,D3		; collision avec le plafond ?
	JUMP,GT 30$
	LOAD.W	D4,D3

	COMP.W	D4,(A5)+OOBPOS+0
	JUMP,NE 24$
	DEC.W	D2		; D2 <-- ne fait pas de bruit !
24$:
	LOAD.W	D3,(A5)+OOBVIT+0
	NEG.W	D3		; inverse la vitesse Vy
	SUB.W	D3,(A5)+OOBCHO+0
	JUMP,NC 25$
	CLR.W	D3
25$:
	LOAD.W	(A5)+OOBVIT+0,D3

	INC.W	D2		; D2 <-- une collision

; Teste une collision avec le bord droite.

30$:
	SWAP.W	D4

	LOAD.W	D3,(A0)+ODFFDX
	SUB.W	D3,#MARGD
	SUB.W	D3,(A5)+OOBDIM+2
	COMP.W	D4,D3		; collision avec le bord droite ?
	JUMP,LT 40$
	LOAD.W	D4,D3

	COMP.W	D4,(A5)+OOBPOS+2
	JUMP,NE 34$
	DEC.W	D2		; D2 <-- ne fait pas de bruit !
34$:
	LOAD.W	D3,(A5)+OOBVIT+2
	NEG.W	D3		; inverse la vitesse Vx
	ADD.W	D3,(A5)+OOBCHO+2
	JUMP,NS 35$
	CLR.W	D3
35$:
	LOAD.W	(A5)+OOBVIT+2,D3

	INC.W	D2		; D2 <-- une collision

; Teste une collision avec le bord gauche.

40$:
	LOAD.W	D3,#MARGG
	COMP.W	D4,D3		; collision avec le bord gauche ?
	JUMP,GT 50$
	LOAD.W	D4,D3

	COMP.W	D4,(A5)+OOBPOS+2
	JUMP,NE 44$
	DEC.W	D2		; D2 <-- ne fait pas de bruit !
44$:
	LOAD.W	D3,(A5)+OOBVIT+2
	NEG.W	D3		; inverse la vitesse Vx
	SUB.W	D3,(A5)+OOBCHO+2
	JUMP,NC 45$
	CLR.W	D3
45$:
	LOAD.W	(A5)+OOBVIT+2,D3

	INC.W	D2		; D2 <-- une collision

; Fait un bruit en cas de collision.

50$:
	TEST.W	D2		; une collision ?
	JUMP,EQ 90$		; non => 90$
				; oui =>
	TEST.W	(A5)+OOBVIE	; objet en vie ?
	JUMP,EQ 90$		; non => 90$
				; oui =>
	CALL	MUS1OBJ		; bruit de collision avec un bord
90$:
	POPM.L	D2,D3
	RET

;--------\\
; FONDOBJ >
;--------/

; Simule un glissement sur le sol avec frottement.

; in	A5.L	^descripteur de l'objet
;	D4.L	position (y;x)
; out	D4.L	position (y;x)
; mod	D4.L, D7.W

FONDOBJ:
	PUSHM.L	D2,D3

	LOAD.L	D3,D4
	SWAP.W	D3
	COMP.W	D3,(A5)+OOBPOS+0 ; dplacement horizontal ?
	JUMP,NE 90$		; non => 90$

	ADD.W	D3,(A5)+OOBDIM+0
	SUB.W	D3,#IDYRAQ
	COMP.W	D3,#POSYRAQ	; est-on sur le sol ?
	JUMP,NE 90$		; non => 90$

	INC.W	(A6)+OFONCT
	COMP.W	(A6)+OFONCT,#7	; pour ne pas freiner trop brutalement !
	JUMP,LO 90$
	CLR.W	(A6)+OFONCT

	TEST.W	(A5)+OOBVIT+2
	JUMP,EQ 90$
	JUMP,NS 50$
				; dplacement de gauche  droite =>
	DEC.W	(A5)+OOBVIT+2	; freine ...
	JUMP	90$
50$:				; dplacement de droite  gauche =>
	INC.W	(A5)+OOBVIT+2	; freine ...
90$:
	POPM.L	D2,D3
	RET

;--------\\
; ASCOBJ  >
;--------/

; Teste une collision avec l'ascenseur.

; in	A5.L	^descripteur de l'objet
;	D4.L	position (y;x)
; out	D4.L	position (y;x)
; mod	D4.L, D7.W

ASCOBJ:
	PUSHM.L	D2,D3,D5

	LOAD.L	D5,D4		; D5 <-- nouvelle position
	PUSH.L	(A5)+OOBPOS
	LOAD.L	(A5)+OOBPOS,D5

	TEST.W	(A5)+OOBVIE
	JUMP,EQ 90$

	LOAD.L	D3,(A6)+OASCPO
	LOAD.L	D4,#H'10000*IDYASC+IDXASC
	CALL	DETOBJ		; nouvel objet dans l'ascenseur ?
	JUMP,EQ 90$		; non => 90$

; Regarde si la balle touche le corps de l'ascenseur.
; Si oui, c'est perdu.

	LOAD.L	D3,(A6)+OASCPO
	SWAP.W	D3
	ADD.W	D3,#IDYASC-12
	SWAP.W	D3
	LOAD.L	D4,#H'10000*12+IDXASC
	CALL	DETOBJ		; touche le plateau de l'ascenseur ?
	JUMP,NE 80$		; oui => 80$
				; non =>
	LOAD.L	D3,(A6)+OASCPO
	ADD.W	D3,#IDXASC-21
	LOAD.L	D4,#H'10000*IDYASC+21
	CALL	DETOBJ		; touche le corps de l'ascenseur ?
	JUMP,NE 80$		; oui => 80$

; Regarde si la balle est bien pose sur le plateau de l'ascenseur.

	TEST.W	(A5)+OOBVIT+2	; balle avance de droite  gauche ?
	JUMP,NS 90$		; oui => 90$

	LOAD.L	D4,D5
	ADD.W	D4,(A5)+OOBDIM+2

	LOAD.W	D3,(A6)+OASCPO+2
	COMP.W	D4,D3
	JUMP,LT 90$
	ADD.W	D3,#IDXASC
	COMP.W	D4,D3
	JUMP,GE 90$

	SWAP.W	D4
	ADD.W	D4,(A5)+OOBDIM+0

	LOAD.W	D3,(A6)+OASCPO+0
	ADD.W	D3,#(IDYASC-13)/2
	COMP.W	D4,D3
	JUMP,LT 90$
	ADD.W	D3,#((IDYASC-13)/2)+13
	COMP.W	D4,D3
	JUMP,GE 90$

	LOAD.L	D5,(A6)+OASCPO
	ADD.W	D5,#42
	SUB.W	D5,(A5)+OOBDIM+2
	SWAP.W	D5
	ADD.W	D5,#IDYASC-14
	SUB.W	D5,(A5)+OOBDIM+0
	SWAP.W	D5		; D5 <-- sur le plateau de l'ascenseur

	SET.B	(A6)+OGAIN	; signal partie gagne !
	JUMP	90$

80$:
	LOAD.W	(A5)+OOBVIE,#1	; mort de l'objet au coup suivant
90$:
	POP.L	(A5)+OOBPOS
	LOAD.L	D4,D5		; D4 <-- nouvelle position

	POPM.L	D2,D3,D5
	RET

;--------\\
; RAQOBJ  >
;--------/

; Teste une collision avec la raquette.

; in	A5.L	^descripteur de l'objet
;	D4.L	nouvelle position (y;x)
; out	D4.L	nouvelle position (y;x)
; mod	D4.L, D7.W

RAQOBJ:
	PUSHM.L	D0..D3,D5

	LOAD.L	D5,D4		; D5 <-- nouvelle position
	JUMP,EQ 90$
	TEST.L	(A5)+OOBPOS
	JUMP,EQ 90$
	TEST.L	(A6)+ORAQPO
	JUMP,EQ 90$

	TEST.B	(A6)+ORAQET:#BRAQC ; raquette casse ?
	JUMP,BS 90$		; oui => 90$

;;?	TEST.W	(A5)+OOBVIT+0	; est-ce que l'objet descend ?
;;?	JUMP,NS 90$		; non => 90$

	PUSH.L	(A5)+OOBPOS
	LOAD.L	(A5)+OOBPOS,D5
	LOAD.L	D3,(A6)+ORAQPO
	SWAP.W	D3
	ADD.W	D3,#22
	SWAP.W	D3
	LOAD.L	D4,#H'10000*(IDYRAQ-22)+IDXRAQ
	CALL	DETOBJ		; nouvel objet dans la raquette ?
	POP.L	(A5)+OOBPOS
	TEST.W	D7
	JUMP,EQ 90$		; non => 90$

	COMP.W	(A5)+OOBDIM+0,#40 ; gros objet ?
	JUMP,LO 20$		; non => 20$
	COMP.W	(A5)+OOBVIT+0,#25 ; balle va trop vite ?
	JUMP,LT 20$		; non => 20$
				; oui =>
	CALL	ENDRAQ		; paf, on casse la raquette !
	LOAD.L	D5,(A5)+OOBPOS
	JUMP	90$

; Regarde si la balle a heurt la raquette dessus ou sur un ct.

20$:
	CALL	RAQP1P2		; D1/D2 <-- points P1/P2 de la raquette
	LOAD.W	D4,(A5)+OOBDIM+0
	SR.W	D4,#1
	LOAD.L	D3,(A5)+OOBPOS
	SWAP.W	D3
	ADD.W	D3,D4
	SWAP.W	D3
	COMP.W	D3,(A6)+ORAQPO+2
	JUMP,HS 30$

; Collision avec le bord gauche.

	SWAP.W	D3
	SWAP.W	D1
	COMP.W	D3,D1		; dpart au-dessus de P1 ?
	JUMP,LO 50$		; non => 50$

	LOAD.W	D5,(A6)+ORAQPO+2
	SUB.W	D5,(A5)+OOBDIM+2

	LOAD.W	D3,(A5)+OOBVIT+2
	NEG.W	D3		; inverse la vitesse Vx
	ADD.W	D3,(A5)+OOBCHO+2
	JUMP,NS 25$
	CLR.W	D3
25$:
	LOAD.W	(A5)+OOBVIT+2,D3
	JUMP	90$

; Collision avec le bord droite.

30$:
	SWAP.W	D3
	SWAP.W	D2
	COMP.W	D3,D2		; dpart au-dessus de P2 ?
	JUMP,LO 50$		; non => 50$

	LOAD.W	D5,(A6)+ORAQPO+2
	ADD.W	D5,#IDXRAQ

	LOAD.W	D3,(A5)+OOBVIT+2
	NEG.W	D3		; inverse la vitesse Vx
	SUB.W	D3,(A5)+OOBCHO+2
	JUMP,NC 35$
	CLR.W	D3
35$:
	LOAD.W	(A5)+OOBVIT+2,D3
	JUMP	90$

; Modifie la position pour tenir compte ( peu prt) du rebond.

50$:
	LOAD.L	D4,D5
	SWAP.W	D4
	LOAD.W	D4,(A5)+OOBPOS+0
	SWAP.W	D4
	CALL	RAQDESSUS	; D4 <-- ramne dessus la raquette !
	LOAD.L	D5,D4

; Modifie la vitesse verticale.

	LOAD.W	D3,(A5)+OOBVIT+0
	NEG.W	D3		; inverse la vitesse Vy
	ADD.W	D3,(A5)+OOBCHO+0
	JUMP,NS 55$
	CLR.W	D3
55$:
	LOAD.W	(A5)+OOBVIT+0,D3

; Modifie la vitesse horizontale.

	LOAD.W	D4,(A6)+ORAQIN
	ASL.W	D4,#1

	NEG.W	D3
	COMP.W	D3,#4
	JUMP,HS 60$
	ASR.W	D4,#1
	COMP.W	D3,#2
	JUMP,HS 60$
	ASR.W	D4,#1
	COMP.W	D3,#1
	JUMP,HS 60$
	ASR.W	D4,#1
60$:
	ADD.W	(A5)+OOBVIT+2,D4

; Fait un bruit de collision avec la raquette.

	TEST.W	(A5)+OOBVIE	; objet en vie ?
	JUMP,EQ 90$		; non => 90$
				; oui =>
	LOAD.W	D3,(A5)+OOBVIT+0
	JUMP,NC 70$
	NEG.W	D3		; D3 <-- vitesse verticale absolue
70$:
	COMP.W	D3,#4		; petite vitesse ?
	JUMP,LO 90$		; oui => 90$
				; non =>
	CALL	MUS2OBJ		; bruit de collision avec la raquette
90$:
	LOAD.L	D4,D5		; D4 <-- nouvelle position

	POPM.L	D0..D3,D5
	RET

;----------\\
; RAQDESSUS >
;----------/

; Remne la balle sur la raquette si par hazard elle est descendue
; en dessous !

; in	D4.L	position de la balle
; out	D4.L	position toujours dessus la raquette
; mod	D4.L, D7.W

RAQDESSUS:
	PUSHM.L	D0..D3

	CALL	RAQP1P2		; D1/D2 <-- points P1/P2 de la raquette

	LOAD.W	D0,(A5)+OOBDIM+2
	SR.W	D0,#1
	SUB.W	D1,D0
	SUB.W	D2,D0
	SWAP.W	D1
	SWAP.W	D2
	LOAD.W	D0,(A5)+OOBDIM+0
	SUB.W	D1,D0
	SUB.W	D2,D0
	SWAP.W	D1
	SWAP.W	D2

	LOAD.L	D3,D4		; D3 <-- position de la balle
	CALL	GAPROVERT	; D3 <-- projection verticale sur D1-D2

	SWAP.W	D3
	SWAP.W	D4

;;?	COMP.W	D4,D3		; en dessus de la raquette ?
;;?	JUMP,LS 50$		; oui => 50$
	LOAD.W	D4,D3		; D4 <-- ramne dessus la raquette (en Y)
SUB.W D4,#2 ;;????????????????????????
50$:
	SWAP.W	D4

	POPM.L	D0..D3
	RET

;--------\\
; RAQP1P2 >
;========/

; Donne les points P1(y,x) et P2(y,x) qui sont les extrmits
; gauche et droite de la raquette (variable selon l'inclinaison).

; in	-
; out	D1.L	point P1(y,x)
;	D2.L	point P2(y,x)
; mod	D1.L, D2.L, D7.W

RAQP1P2:
	PUSHM.L	D3,A3

	LOAD.L	A3,#R16"TAIRAQ
	LOAD.W	D3,(A6)+ORAQIN
	NEG.W	D3
	ADD.W	D3,#MAXIRAQ
	SL.W	D3,#3		; D3 <-- *8 car table de 4x .W
	LOAD.L	D1,(A3)+(D3.W)+0 ; D1 <-- P1(y,x)
	LOAD.L	D2,(A3)+(D3.W)+4 ; D2 <-- P2(y,x)

	ADD.W	D1,(A6)+ORAQPO+2
	SWAP.W	D1
	SUB.W	D1,#IDYRAQ
	NEG.W	D1
	ADD.W	D1,(A6)+ORAQPO+0
	SWAP.W	D1

	ADD.W	D2,(A6)+ORAQPO+2
	SWAP.W	D2
	SUB.W	D2,#IDYRAQ
	NEG.W	D2
	ADD.W	D2,(A6)+ORAQPO+0
	SWAP.W	D2

	POPM.L	D3,A3
	RET

; Cette table donne les extrmits de la raquette, qui
; varie selon son inclinaison.

;		 P1      P2
;		 y,x     y,x
TAIRAQ:
	.W	62,13	18,57	; raquette \
	.W	59,10	21,60
	.W	56,07	24,62
	.W	55,06	27,63
	.W	52,03	31,62
	.W	49,03	34,63
	.W	46,01	37,62
	.W	41,00	41,63	; raquette -
	.W	07,01	45,63
	.W	34,01	48,61
	.W	31,02	51,60
	.W	28,01	54,58
	.W	25,02	56,56
	.W	22,04	59,53
	.W	18,06	62,50	; raquette /


;--------\\
; MOVERAQ >
;========/

; Dplace la raquette.

; in	D4.W	nouvelle position (x)
;	D3.W	nouvelle inclinaison (+/-)
; out	-
; mod	D7.W

MOVERAQ:
	PUSHM.L	D1..D5,A5

	TEST.B	(A6)+OFIXE	; raquette fixe ?
	JUMP,F	05$		; non => 05$
	LOAD.W	D4,#POSXRAQ	; D4 <-- impose la position horizontale
05$:
	SWAP.W	D4
	LOAD.W	D4,#POSYRAQ	; D4 <-- impose la position verticale
	SWAP.W	D4

	COMP.L	D4,(A6)+ORAQPO
	JUMP,NE 10$
	COMP.W	D3,(A6)+ORAQIN
	JUMP,EQ 90$
10$:
	LOAD.L	A5,#(A6)+OBALLE

; Si la balle est dans la mme tranche verticale que la raquette,
; refuse que la raquette dpasse la balle !

	CLR.W	D5		; D5 <-- balle en-dessus de la raquette

	TEST.W	(A5)+OOBVIE	; objet en vie ?
	JUMP,EQ 20$		; non => 20$

	CALL	RAQP1P2		; D1/D2 <-- points P1/P2 de la raquette
	SWAP.W	D1
	SWAP.W	D2
	COMP.W	D1,D2
	JUMP,HS 12$
	LOAD.W	D1,D2		; D1 <-- point le plus bas de la raquette
12$:
	LOAD.W	D2,(A5)+OOBPOS+0
	ADD.W	D2,(A5)+OOBDIM+0
	COMP.W	D2,D1		; balle en-dessus de la raquette ?
	JUMP,LS 20$		; oui => 20$
				; non =>
	LOAD.W	D5,(A5)+OOBDIM+2 ; D5 <-- balle en-dessous

	COMP.W	D4,(A6)+ORAQPO+2
	JUMP,LO 15$
				; dplacement vers la droite =>
	LOAD.W	D2,(A5)+OOBPOS+2
	ADD.W	D2,(A5)+OOBDIM+2
	COMP.W	D2,(A6)+ORAQPO+2
	JUMP,LE 20$

	LOAD.W	D2,(A5)+OOBPOS+2
	SUB.W	D2,#IDXRAQ-10
	COMP.W	D4,D2
	JUMP,LE 20$
	LOAD.W	D4,D2
	JUMP	20$
15$:				; dplacement vers la gauche =>
	LOAD.W	D2,(A5)+OOBPOS+2
	SUB.W	D2,#IDXRAQ
	COMP.W	D2,(A6)+ORAQPO+2
	JUMP,GE 20$

	LOAD.W	D2,(A5)+OOBPOS+2
	ADD.W	D2,(A5)+OOBDIM+2
	SUB.W	D2,#10
	COMP.W	D4,D2
	JUMP,GE 20$
	LOAD.W	D4,D2

; Dplace la raquette, en effaant puis en remettant la balle
; si elle recoupe l'ancienne ou la nouvelle raquette.

20$:
	LOAD.W	D2,#MARGG+2
	ADD.W	D2,D5
	COMP.W	D4,D2		; souris trop  gauche ?
	JUMP,GE 25$
	LOAD.W	D4,D2
25$:
	LOAD.W	D2,#LXWDO-MARGD-IDXASC-IDXRAQ-2
;;?	SUB.W	D2,D5
	COMP.W	D4,D2		; souris trop  droite ?
	JUMP,LE 30$
	LOAD.W	D4,D2
30$:
	PUSHM.L	D3,D4
	LOAD.L	D3,(A6)+ORAQPO
	LOAD.L	D4,#H'10000*IDYRAQ+IDXRAQ
	CALL	DETOBJ		; balle recoupe l'ancienne raquette ?
	LOAD.W	D1,D7		; D1 <-- zro si pas de collision
	POPM.L	D3,D4

	TEST.W	D1
	JUMP,NE 35$

	PUSHM.L	D3,D4
	LOAD.L	D3,D4
	LOAD.L	D4,#H'10000*IDYRAQ+IDXRAQ
	CALL	DETOBJ		; balle recoupe la nouvelle raquette ?
	LOAD.W	D1,D7		; D1 <-- zro si pas de collision
	POPM.L	D3,D4
35$:
	TEST.W	D1
	JUMP,EQ 40$
	CALL	INVOBJ		; efface la balle
40$:
	LOAD.W	(A6)+ORAQIN,D3
	LOAD.W	D2,D3		; D2 <-- nouvelle inclinaison
	NEG.W	D2
	ADD.B	D2,#ICORAQ	; D2 <-- code de l'icne

	LOAD.L	D5,#H'10000*IDYRAQ+IDXRAQ ; D5 <-- dimensions
	LOAD.L	D3,(A6)+ORAQPO	; D3 <-- ancienne position
	CALL	MOVELICONE	; dplace l'icne
	LOAD.L	(A6)+ORAQPO,D4

	TEST.W	D1
	JUMP,EQ 90$
	CALL	INVOBJ		; remet la balle
90$:
	POPM.L	D1..D5,A5
	RET

;--------\\
; ENDRAQ  >
;========/

; Animation de casse de la raquette.

; in	-
; out	-
; mod	D7.W

ENDRAQ:
	PUSHM.L	D1..D5,A3,A5

	TSET.B	(A6)+ORAQET:#BRAQC ; la raquette est casse

; Casse la raquette.

	LOAD.L	A3,#R16"TMUSENDRAQ
	CALL	PATATRA		; fait un bruit

	LOAD.L	A5,#(A6)+OBALLE
	CALL	INVOBJ		; efface la balle
	LOAD.W	D4,#POSYRAQ+22
	SUB.W	D4,(A5)+OOBDIM+0
	LOAD.W	(A5)+OOBPOS+0,D4
	CALL	INVOBJ		; remet la balle

	LOAD.W	D1,#4
	LOAD.W	D3,#ICORAQEND
20$:
	CALL	INVOBJ		; efface la balle

	LOAD.L	D4,(A6)+ORAQPO
	LOAD.L	D5,#H'10000*IDYRAQ+IDXRAQ
	LOAD.W	D2,#SETDOT
	CALL	DRICONE

	CALL	INVOBJ		; remet la balle

;;?	CALL	MOVEOBJ		; dplace la balle

	LOAD.W	D4,#TIMING
	NTREL	?DELMS		; attend un peu ...

	INC.W	D3
	DEC.W	D1
	JUMP,NE 20$

; Attend encore un peu.

	LOAD.W	D3,#50
50$:
;;?	CALL	MOVEOBJ		; dplace la balle

	LOAD.W	D4,#TIMING
	NTREL	?DELMS		; attend un peu ...

	DEC.W	D3
	JUMP,NE 50$

	POPM.L	D1..D5,A3,A5
	RET

;--------\\
; DETOBJ  >
;========/

; Dtecte si un objet (rectangulaire) entre en collision
; avec une zone rectangulaire quelconque.

; in	A5.L	^description de l'objet
;	D3.L	coin sup/gauche (y;x)
;	D4.L	dimensions (dy;dx)
; out	D7.W	EQ => pas de collision
;		NE => collision
; mod	D7.W

DETOBJ:
	PUSHM.L	D2..D4

	CLR.W	D7		; D7 <-- pas de collision

	LOAD.W	D2,(A5)+OOBPOS+2
	ADD.W	D2,(A5)+OOBDIM+2
	COMP.W	D3,D2
	JUMP,HS 90$

	SUB.W	D2,(A5)+OOBDIM+2
	ADD.W	D3,D4
	COMP.W	D3,D2
	JUMP,LO 90$

	SWAP.W	D3
	SWAP.W	D4

	LOAD.W	D2,(A5)+OOBPOS+0
	ADD.W	D2,(A5)+OOBDIM+0
	COMP.W	D3,D2
	JUMP,HS 90$

	SUB.W	D2,(A5)+OOBDIM+0
	ADD.W	D3,D4
	COMP.W	D3,D2
	JUMP,LO 90$

	LOAD.W	D7,#1		; D7 <-- collision
90$:
	POPM.L	D2..D4
	TEST.W	D7		; retour EQ/NE
	RET

;--------\\
; INVOBJ  >
;========/

; Inverse un objet.

; in	A5.L	^descripteur de l'objet
; out	-
; mod	D7.W

INVOBJ:
	PUSHM.L	D2..D5

	CALL	GETICONE	; D2 <-- code de l'icne
	LOAD.B	D3,D2		; D3 <-- code de l'icne
	LOAD.W	D2,#INVDOT	; D2 <-- mode
	LOAD.L	D4,(A5)+OOBPOS	; D4 <-- position
	LOAD.L	D5,(A5)+OOBDIM	; D5 <-- dimensions
	CALL	DRICONE		; inverse l'icne

	POPM.L	D2..D5
	RET


;-----------\\
; MOVEIICONE >
;===========/

; Dplace une icne sur l'cran en l'inversant.

; in	A5.L	^description de l'objet
;	D3.L	ancienne position (y;x)
;	D4.L	nouvelle position (y;x)
;	D5.L	dimensions (dy;dx)
; out	-
; mod	D7.W

MOVEIICONE:
	PUSHM.L	D1..D4

	CALL	GETICONE	; D2 <-- code de l'ancienne icne
	LOAD.B	D1,D2		; D1 <-- code de l'ancienne icne
	CALL	AGEICONE	; vieilli l'icne !
	CALL	GETICONE	; D2 <-- code de la nouvelle icne

	COMP.L	D3,D4		; nouvelle position = ancienne ?
	JUMP,NE 20$
	COMP.B	D1,D2		; nouvelle icne = ancienne ?
	JUMP,EQ 90$		; oui => 90$
20$:
	PUSH.L	D3
	LOAD.B	D3,D2		; D3 <-- code de la nouvelle icne
	LOAD.W	D2,#INVDOT	; D2 <-- mode
	CALL	DRICONE		; dessine la nouvelle icne
	POP.L	D3

	TEST.B	(A5)+OOBNEW
	JUMP,T	80$
	LOAD.L	D4,D3		; D4 <-- ancienne position
	LOAD.B	D3,D1		; D3 <-- code de l'ancienne icne
	LOAD.W	D2,#INVDOT	; D2 <-- mode
	CALL	DRICONE		; efface l'ancienne icne
80$:
	CLR.B	(A5)+OOBNEW
90$:
	POPM.L	D1..D4
	RET

;---------\\
; GETICONE >
;=========/

; Donne le code de l'icne d'un objet.

; in	A5.L	^description de l'objet
; out	D2.B	code de l'icne
; mod	D2.L, D7.W

GETICONE:
	PUSH.W	D3

	LOAD.B	D2,(A5)+OOBICO	; D2 <-- code de l'icne

	TEST.W	(A5)+OOBVIE
	JUMP,NE 90$

	LOAD.W	D3,(A5)+OOBFIN
	ADD.B	D2,D3
	COMP.W	D3,#NBANIME
	JUMP,LS 90$

	CLR.B	D2
90$:
	POP.W	D3
	RET

;---------\\
; AGEICONE >
;=========/

; Fait vieillir une icne, jusqu' sa mort !

; in	A5.L	^description de l'objet
; out	-
; mod	D7.W

AGEICONE:
	PUSH.L	D3

	TEST.W	(A5)+OOBVIE	; icne morte ?
	JUMP,EQ 20$		; oui => 20$

	DEC.W	(A5)+OOBVIE	; oeuvre inxorable du temps ...
	JUMP	90$

20$:				; mort de l'icne =>
	TEST.W	(A5)+OOBFIN
	JUMP,NE 30$
	TEST.W	(A5)+OOBVIF
	JUMP,NE 30$

	CALL	MUS3OBJ		; bruit de la mort de l'objet
30$:
	LOAD.W	D3,(A5)+OOBFIN
	COMP.W	D3,#NBANIME
	JUMP,LO 40$
	SET.B	(A5)+OOBOLD
	JUMP	90$

40$:
	INC.W	(A5)+OOBVIF
	COMP.W	(A5)+OOBVIF,#VTANIME
	JUMP,LO 90$
	CLR.W	(A5)+OOBVIF

	INC.W	(A5)+OOBFIN
90$:
	POP.L	D3
	RET


;-----------\\
; MOVELICONE >
;===========/

; Dplace une icne sur l'cran en mode "load".

; in	D2.B	code de l'icne
;	D3.L	ancienne position (y;x)
;	D4.L	nouvelle position (y;x)
;	D5.L	dimensions (dy;dx)
; out	-
; mod	D7.W

MOVELICONE:
	PUSHM.L	D2,D3

	CALL	MOVECLR		; efface ce qui dpasse

	LOAD.B	D3,D2		; D3 <-- code de l'icne
	LOAD.W	D2,#SETDOT	; D2 <-- mode "load"
	CALL	DRICONE		; dessine la nouvelle icne

	POPM.L	D2,D3
	RET

;--------\\
; MOVECLR >
;--------/

; Efface la zone laisse vide aprs un dplacement.

; in	D3.L	ancienne position (y;x)
;	D4.L	nouvelle position (y;x)
;	D5.L	dimensions (dy;dx)
; out	-
; mod	D7.W

MOVECLR:
	PUSHM.L	D3..D5

	TEST.L	D3		; ancienne position existe ?
	JUMP,EQ 90$		; non => 90$

	PUSHM.L	D3..D5
	SUB.W	D4,D3
	JUMP,NC 10$
	NEG.W	D4
10$:
	COMP.W	D4,D5		; trop loin horizontalement ?
	JUMP,HS 60$		; oui => 60$

	SWAP.W	D3
	SWAP.W	D4
	SWAP.W	D5

	SUB.W	D4,D3
	JUMP,NC 15$
	NEG.W	D4
15$:
	COMP.W	D4,D5		; trop loin verticalement ?
	JUMP,HS 60$		; oui => 60$
	POPM.L	D3..D5

	PUSHM.L	D3,D4

	SWAP.W	D4
	SWAP.W	D5
	LOAD.W	D4,D5
	SWAP.W	D5
	SWAP.W	D4

	COMP.W	D3,D4
	JUMP,EQ 30$
	JUMP,HI 20$

	SUB.W	D4,D3
	CALL	DRCLEAR		; efface la zone  gauche
	JUMP	30$
20$:
	SUB.W	D4,D3
	NEG.W	D4
	ADD.W	D3,D5
	SUB.W	D3,D4
	CALL	DRCLEAR		; efface la zone  droite
30$:
	POPM.L	D3,D4

	LOAD.W	D4,D5
	SWAP.W	D3
	SWAP.W	D4
	SWAP.W	D5
	COMP.W	D3,D4
	JUMP,EQ 90$
	JUMP,HI 40$

	SUB.W	D4,D3
	SWAP.W	D3
	SWAP.W	D4
	CALL	DRCLEAR		; efface la zone en haut
	JUMP	90$
40$:
	SUB.W	D4,D3
	NEG.W	D4
	ADD.W	D3,D5
	SUB.W	D3,D4
	SWAP.W	D3
	SWAP.W	D4
	CALL	DRCLEAR		; efface la zone en bas
	JUMP	90$

60$:
	POPM.L	D3..D5
	LOAD.L	D4,D5
	CALL	DRCLEAR		; efface toute l'ancienne zone
90$:
	POPM.L	D3..D5
	RET





; Gestion du tableau de bord
; --------------------------



;---------\\
; GACOMPTE >
;=========/

; Incrmente le compteur des parties gagnes.

; in	-
; out	-
; mod	D7.W

GACOMPTE:
	PUSHM.L	D4

	LOAD.W	D4,(A6)+OCONGA
	LOAD.L	D3,#H'10000*POSYCGA+POSXCGA
	CALL	MAJCOMPTE

	POPM.L	D4
	RET

;---------\\
; PECOMPTE >
;=========/

; Incrmente le compteur des parties perdues.

; in	-
; out	-
; mod	D7.W

PECOMPTE:
	PUSHM.L	D4

	LOAD.W	D4,(A6)+OCONPE
	LOAD.L	D3,#H'10000*POSYCPE+POSXCPE
	CALL	MAJCOMPTE

	POPM.L	D4
	RET

;----------\\
; MAJCOMPTE >
;----------/

; Affiche un compteur sur l'cran.

; in	D4.W	compteur (..n)
;	D3.L	position dans l'cran
; out	-
; mod	D7.W

MAJCOMPTE:
	PUSHM.L	D2..D4

	LOAD.L	D2,D3

	TEST.B	(A6)+OINV	; fond de l'cran blanc ?
	JUMP,F	20$
	LOAD.B	D3,#AFINV
	LIB	?AFCAR		; passe en vide inverse
20$:
	LOAD.L	D3,D2
	LIB	?SETCURS

	AND.L	D4,#H'FFFF
	DIV.WU	D4,#100
	CLR.W	D4
	SWAP.W	D4		; D4 <-- 0..99

	DIV.WU	D4,#10
	LOAD.B	D3,D4
	ADD.B	D3,#'0
	LIB	?AFCAR		; affiche les dizaines

	LOAD.L	D3,D2
	ADD.W	D3,#13
	LIB	?SETCURS

	SWAP.W	D4
	LOAD.B	D3,D4
	ADD.B	D3,#'0
	LIB	?AFCAR		; affiche les units

	LOAD.B	D3,#AFDIR
	LIB	?AFCAR

	POPM.L	D2..D4
	RET


;----------\\
; MOVEJAUGE >
;==========/

; Indique le temps restant dans la jauge.

; in	A5.L	^description de l'objet
; out	-
; mod	D7.W

MOVEJAUGE:
	PUSHM.L	D3,D4

	LOAD.W	D3,(A5)+OOBVIE
	MUL.WU	D3,#20
	DIV.WU	D3,(A5)+OOBVIM	; D3 <-- nouveau niveau

	COMP.W	D3,(A6)+OJAUNI
	JUMP,EQ 90$

	LOAD.W	D4,(A6)+OJAUNI
	CALL	INVJAUGE	; efface l'ancien niveau

	LOAD.W	D4,D3
	CALL	INVJAUGE	; dessine le nouveau niveau
	LOAD.W	(A6)+OJAUNI,D4
90$:
	POPM.L	D3,D4
	RET

;---------\\
; INVJAUGE >
;---------/

; Inverse la jauge du temps.

; in	D4.W	tat de la jauge (0..19)
; out	-
; mod	D7.W

INVJAUGE:
	PUSHM.L	D3,D4

	COMP.W	D4,#-1
	JUMP,EQ 90$

	LOAD.W	D3,#LYWDO-POSYJAU ; D3 <-- base en Y
	MUL.WU	D4,#3		; D4 <-- hauteur
	SUB.W	D3,#LYWDO
	NEG.W	D3
	SUB.W	D3,D4

	SWAP.W	D3
	SWAP.W	D4

	LOAD.W	D3,#POSXJAU	; D3 <-- base en X
	LOAD.W	D4,#9		; D4 <-- largeur

	CALL	DRINV
90$:
	POPM.L	D3,D4
	RET






; Routines de GA (gomtrie analytique)
; -------------------------------------


; Constante permettant de simuler une virgule fixe dans un nombre
; entier (16 bits) pour conserver une certaine prcision lors des
; divisions.
; La valeur GACONST=64 permet de traiter des nombres jusqu' 1024,
; selon la formule:  n < (2^16)/GACONST

;;?GACONST	=	64		; constante "c"
GACONST = 8
GAMAX	=	(2^15)-1	; valeur positive maximale



;----------\\
; GAPROVERT >
;==========/

; Calcul la projection verticale d'un point P(y,x) sur une
; droite P1(y,x)-P2(y,x).

; in	D1.L	P1(y,x) droite
;	D2.L	P2(y,x) droite
;	D3.L	P(y,x) point
; out	D3.L	V(y,x) projection verticale
; mod	D3.L, D7.W

GAPROVERT:
	PUSHM.L	D1,D2,D4

	EX.L	D1,D3
	EX.L	D2,D4
	CALL	GAAB		; D1/D2 <-- a/b
	EX.L	D4,D2
	EX.L	D3,D1

	MUL.WA	D1,D3
	ADD.W	D1,D2		; D1 <-- Vy
	CONV.LA.WA D1		; D1 <-- tend le signe sur 32 bits
	DIV.WA	D1,#GACONST

	SWAP.W	D3
	LOAD.W	D3,D1		; D3 <-- V(y,x)
	SWAP.W	D3

	POPM.L	D1,D2,D4
	RET

;---------\\
; GASYMAXE >
;=========/

; Calcul le point symtrique S'(y,x) d'un point S(y,x) sur
; une droite P1(y,x)-P2(y,x).

;	       Sx
;	       --- + Sy - b
;	        a
;	S'x = --------------
;	          1
;	         --- + a
;	          a
;
;	S'y = ( a * S'x) + b

; in	D1.L	P1(y,x) droite
;	D2.L	P2(y,x) droite
;	D4.L	S(y,x) point
; out	D0.L	S'(y,x) symtrique de S(y,x)
; mod	D0.L, D7.W

GASYMAXE:
	PUSHM.L	D1..D5

	EX.L	D1,D3
	EX.L	D2,D4
	CALL	GAAB		; D1/D2 <-- a/b
	EX.L	D4,D2
	EX.L	D3,D1

	LOAD.W	D0,D4		; D0 <-- Sx = S'x
	TEST.W	D1		; a=0 (horizontal) ?
	JUMP,EQ 50$		; oui => 50$
	MUL.WA	D0,#GACONST
	DIV.WA	D0,D1		; D0 <-- (Sx/a)

	SWAP.W	D4
	ADD.W	D0,D4		; D0 <-- (Sx/a) + Sy
	SWAP.W	D4

	LOAD.W	D3,D2
	CONV.LA.WA D3		; D3 <-- tend le signe sur 32 bits
	DIV.WA	D3,#GACONST
	SUB.W	D0,D3		; D0 <-- (Sx/a) + Sy + b

	LOAD.L	D3,#GACONST*GACONST
	DIV.WA	D3,D1
	ADD.W	D3,D1		; D3 <-- (1/a) + a

	MUL.WA	D0,#GACONST
	DIV.WA	D0,D3		; D0 <-- S"x
50$:
	MUL.WA	D1,D0
	ADD.W	D1,D2		; D1 <-- S"y
	CONV.LA.WA D1		; D1 <-- tend le signe sur 32 bits
	DIV.WA	D1,#GACONST

	SWAP.W	D0
	LOAD.W	D0,D1		; D0 <-- S"(y,x)
	SWAP.W	D0

	SUB.W	D0,D4
	ADD.W	D4,D0
	ADD.W	D4,D0
	SWAP.W	D0
	SWAP.W	D4
	SUB.W	D0,D4
	ADD.W	D4,D0
	ADD.W	D4,D0
	SWAP.W	D0
	SWAP.W	D4
	LOAD.L	D0,D4		; D0 <-- S'(y,x)

	POPM.L	D1..D5
	RET

;--------\\
; GAINTER >
;========/

; Calcul le point d'intersection Pi(y,x) de deux droites quelconques
; dfinies par deux points P1(y,x) et P2(y,x) chacune.

;	       b2 - b1
;	Pix = ---------
;	       a1 - a2
;
;	Piy = ( a1 * Pix) + b1

; in	D1.L	P1(y,x) droite 1
;	D2.L	P2(y,x) droite 1
;	D3.L	P1(y,x) droite 2
;	D4.L	P2(y,x) droite 2
; out	D0.L	Pi(y,x) point d'intersection
; mod	D0.L, D7.W

GAINTER:
	PUSHM.L	D1..D5

	CALL	GAAB		; D3/D4 <-- a2/b2

	EX.L	D1,D3
	EX.L	D2,D4
	CALL	GAAB		; D1/D2 <-- a1/b1
	EX.L	D4,D2
	EX.L	D3,D1

	LOAD.W	D0,D4
	SUB.W	D0,D2		; D0 <-- b2 - b1

	LOAD.W	D5,D1
	SUB.W	D5,D3		; D5 <-- a1 - a2
	JUMP,EQ 30$

	CONV.LA.WA D0		; D0 <-- tend le signe sur 32 bits
	DIV.WA	D0,D5		; D0 <-- Pix
	JUMP	40$

30$:				; droites parallles =>
	LOAD.W	D0,#GAMAX
40$:
	MUL.WA	D1,D0
	ADD.W	D1,D2		; D1 <-- Piy
	CONV.LA.WA D1		; D1 <-- tend le signe sur 32 bits
	DIV.WA	D1,#GACONST

	SWAP.W	D0
	LOAD.W	D0,D1		; D0 <-- Pi(y,x)
	SWAP.W	D0

	POPM.L	D1..D5
	RET

;--------\\
; GAAB    >
;--------/

; Calcul les coefficient "a" et "b" de l'quation "y=ax+b".

;	     P2y - P1y
;	a = -----------            [ pente ]
;	     P2x - P1x
;
;	b = P2y - ( a * P2x )      [ offset sur l'axe Y ]

; in	D3.L	P1(y,x)
;	D4.L	P2(y,x)
; out	D3.W	a * c
;	D4.W	b * c
; mod	D3.L, D4.L, D7.W

GAAB:
	PUSHM.L	D1,D2

	SWAP.W	D4
	LOAD.W	D1,D4
	SWAP.W	D4
	SWAP.W	D3
	SUB.W	D1,D3		; D1 <-- P2y-P1y
	SWAP.W	D3

	LOAD.W	D2,D4
	SUB.W	D2,D3		; D2 <-- P2x-P1x
	JUMP,EQ 30$

	MUL.WA	D1,#GACONST
	DIV.WA	D1,D2		; D1 <-- a * c
	JUMP	40$

30$:				; droite verticale =>
	LOAD.W	D2,D1
	LOAD.W	D1,#-GAMAX
	TEST.W	D2
	JUMP,NS 40$
	LOAD.W	D1,#+GAMAX
40$:
	LOAD.W	D2,D1
	MUL.WA	D2,D4		; D2 <-- a * P2x
	SWAP.W	D4
	MUL.WA	D4,#GACONST
	SUB.W	D2,D4
	NEG.W	D2		; D2 <-- b

	LOAD.W	D3,D1		; D3 <-- a * c
	LOAD.W	D4,D2		; D4 <-- b * c

	POPM.L	D1,D2
	RET





; Gestion des bruits
; ------------------



;--------\\
; MUS1OBJ >
;========/

; Fait entendre un bruit numro 1 li  un objet spcifique.

; in	A5.L	^description de l'objet
; out	-
; mod	D7.W

MUS1OBJ:
	PUSH.L	A3

	LOAD.L	A3,#R16"TMUS
	ADD.W	A3,(A5)+OOBMU1
	CALL	PATATRA

	POP.L	A3
	RET

;--------\\
; MUS2OBJ >
;========/

; Fait entendre un bruit numro 2 li  un objet spcifique.

; in	A5.L	^description de l'objet
; out	-
; mod	D7.W

MUS2OBJ:
	PUSH.L	A3

	LOAD.L	A3,#R16"TMUS
	ADD.W	A3,(A5)+OOBMU2
	CALL	PATATRA

	POP.L	A3
	RET

;--------\\
; MUS3OBJ >
;========/

; Fait entendre un bruit numro 3 li  un objet spcifique.

; in	A5.L	^description de l'objet
; out	-
; mod	D7.W

MUS3OBJ:
	PUSH.L	A3

	LOAD.L	A3,#R16"TMUS
	ADD.W	A3,(A5)+OOBMU3
	CALL	PATATRA

	POP.L	A3
	RET

;--------\\
; PATATRA >
;========/

; Fait un bruit rigolo !

; in	A3.L	^table de bruit
; out	-
; mod	D7.W

PATATRA:
	PUSH.L	A4

	LOAD.L	A4,A3
	TEST.W	(A4)
	JUMP,EQ 90$
	LIB	?PLAY
90$:
	POP.L	A4
	RET



TMUS:
TMUSCOLB0:
	.W	PERIODE+4095,PERIODE+4093,PERIODE+4090,H'100*25+0
	.W	0

TMUSCOLR0:
	.W	PERIODE+3050,PERIODE+3052,PERIODE+3055,H'100*25+0
	.W	0

TMUSENDB0:
	.W	PERIODE+4000,PERIODE+4003,BRUIT+16,H'100*255+10
	.W	PERIODE+4000,PERIODE+4003,BRUIT+19,H'100*255+10
	.W	PERIODE+4000,PERIODE+4003,BRUIT+22,H'100*255+10
	.W	PERIODE+4000,PERIODE+4003,BRUIT+25,H'100*255+10
	.W	PERIODE+4000,PERIODE+4003,BRUIT+28,H'100*255+10
	.W	PERIODE+4000,PERIODE+4003,BRUIT+31,H'100*20+0
	.W	0


TMUSCOLB1:
	.W	PERIODE+400,SILENCE,SILENCE,H'100*1+0
	.W	0

TMUSCOLR1:
	.W	PERIODE+800,PERIODE+801,PERIODE+802,H'100*4+0
	.W	0

TMUSENDB1:
	.W	BRUIT+0,SILENCE,SILENCE,H'100*50+0
	.W	0


TMUSCOLB2:
	.W	PERIODE+300,SILENCE,SILENCE,H'100*1+0
	.W	0

TMUSCOLR2:
	.W	PERIODE+600,PERIODE+601,PERIODE+602,H'100*4+0
	.W	0

TMUSENDB2:
	.W	PERIODE+3567,PERIODE+3254,BRUIT+31,H'100*30+0
	.W	0


TMUSCOLB3:
	.W	PERIODE+3000,PERIODE+3022,PERIODE+3044,H'100*255+4
	.W	PERIODE+3000,PERIODE+3011,PERIODE+3022,H'100*255+4
	.W	PERIODE+3000,PERIODE+3000,PERIODE+3000,H'100*10+1
	.W	0

TMUSCOLR3:
	.W	PERIODE+2000,PERIODE+2022,PERIODE+2044,H'100*255+4
	.W	PERIODE+2000,PERIODE+2011,PERIODE+2022,H'100*255+4
	.W	PERIODE+2000,PERIODE+2000,PERIODE+2000,H'100*10+1
	.W	0

TMUSENDB3:
	.W	BRUIT+0,SILENCE,SILENCE,H'100*255+2
	.W	BRUIT+4,SILENCE,SILENCE,H'100*255+2
	.W	BRUIT+8,SILENCE,SILENCE,H'100*255+2
	.W	BRUIT+12,SILENCE,SILENCE,H'100*255+2
	.W	BRUIT+16,SILENCE,SILENCE,H'100*255+2
	.W	BRUIT+20,SILENCE,SILENCE,H'100*255+2
	.W	BRUIT+24,SILENCE,SILENCE,H'100*255+2
	.W	BRUIT+28,SILENCE,SILENCE,H'100*255+2
	.W	BRUIT+31,SILENCE,SILENCE,H'100*30+0
	.W	0


TMUSCOLB4:
	.W	PERIODE+3000,PERIODE+3001,PERIODE+3002,H'100*6+0
	.W	0

TMUSCOLR4:
	.W	PERIODE+2000,PERIODE+2001,PERIODE+2002,H'100*6+0
	.W	0

TMUSENDB4:
	.W	PERIODE+3567,PERIODE+3254,BRUIT+31,H'100*50+0
	.W	0


TMUSCOLB5:
	.W	PERIODE+3000,PERIODE+3001,PERIODE+3002,H'100*20+0
	.W	0

TMUSCOLR5:
	.W	PERIODE+2000,PERIODE+2001,PERIODE+2002,H'100*20+0
	.W	0

TMUSENDB5:
	.W	PERIODE+3567,PERIODE+3254,BRUIT+31,H'100*50+0
	.W	0


TMUSCOLB6:
	.W	PERIODE+4000,PERIODE+4001,PERIODE+4002,H'100*20+0
	.W	0

TMUSCOLR6:
	.W	PERIODE+3000,PERIODE+3001,PERIODE+3002,H'100*20+0
	.W	0

TMUSENDB6:
	.W	PERIODE+3567,PERIODE+3254,BRUIT+16,H'100*50+0
	.W	0


TMUSENDRAQ:
	.W	PERIODE+3567,PERIODE+3254,BRUIT+0,H'100*10+5
	.W	PERIODE+3567,PERIODE+3254,BRUIT+12,H'100*10+5
	.W	PERIODE+3567,PERIODE+3254,BRUIT+24,H'100*10+5
	.W	PERIODE+3567,PERIODE+3254,BRUIT+31,H'100*10+0
	.W	0


TMUSLANAV:
	.W	PERIODE+1000,PERIODE+1001,PERIODE+998,H'100*1+0
	.W	0

TMUSLANPR:
	.W	PERIODE+1000,SILENCE,SILENCE,H'100*255+2
	.W	PERIODE+900,SILENCE,SILENCE,H'100*255+2
	.W	PERIODE+800,SILENCE,SILENCE,H'100*255+2
	.W	PERIODE+700,SILENCE,SILENCE,H'100*255+2
	.W	PERIODE+600,SILENCE,SILENCE,H'100*255+2
	.W	PERIODE+500,SILENCE,SILENCE,H'100*255+2
	.W	PERIODE+400,SILENCE,SILENCE,H'100*255+2
	.W	PERIODE+300,SILENCE,SILENCE,H'100*255+2
	.W	PERIODE+200,SILENCE,SILENCE,H'100*255+2
	.W	PERIODE+100,SILENCE,SILENCE,H'100*2+2
	.W	0


TMUSYOUPIE:
	.W	PERIODE+800,PERIODE+400,PERIODE+600,H'100*10+4
	.W	PERIODE+300,PERIODE+600,PERIODE+400,H'100*10+4
	.W	PERIODE+250,PERIODE+500,PERIODE+1000,H'100*10+4
	.W	PERIODE+600,PERIODE+300,PERIODE+400,H'100*10+4
	.W	PERIODE+1000,PERIODE+500,PERIODE+1500,H'100*10+4
	.W	PERIODE+500,PERIODE+1000,PERIODE+750,H'100*10+4
	.W	PERIODE+200,PERIODE+300,PERIODE+400,H'100*10+4
	.W	PERIODE+400,PERIODE+500,PERIODE+600,H'100*10+1
	.W	0

TMUSPERDU:
	.W	NOTE+14,NOTE+12+14,NOTE+14+34,H'100*30+15
	.W	NOTE+13,NOTE+12+13,NOTE+14+33,H'100*30+15
	.W	NOTE+12,NOTE+12+12,NOTE+14+32,H'100*30+15
	.W	NOTE+11,NOTE+12+11,NOTE+14+31,H'100*60+0
	.W	0





; Gestion de la souris
; --------------------



;--------\\
; IFMOUSE >
;========/

; Donne la position de la souris dans la swdo.

; in	-
; out	D4.L	position de la souris (y;x)
;	D7.W	erreur
; mod	D4.L, D7.W

IFMOUSE:
	PUSH.L	D3

	LIB	?IFMOUSE
	JUMP',NE 90$

	SUB.W	D4,(A0)+ODFFX
	JUMP',HS 20$
	CLR.W	D4
	LOAD.W	D7,#ERDIOUT
20$:
	SWAP.W	D4
	SUB.W	D4,(A0)+ODFFY
	JUMP',HS 30$
	CLR.W	D4
	LOAD.W	D7,#ERDIOUT
30$:
	SWAP.W	D4
90$:
	POP.L	D3
	TEST.W	D7		; retour EQ/NE
	RET

;--------\\
; PMOUSE  >
;========/

; Positionne la souris en (y;x).

; in	D4.L	nouvelle position y;x
; out	-
; mod	D7.W

PMOUSE:
	PUSHM.L	D3,D4,D6,A4

	ADD.W	D4,(A0)+ODFFX
	SWAP.W	D4
	ADD.W	D4,(A0)+ODFFY
	SWAP.W	D4

; Ramne la position dans la fentre si elle en sort.

	TEST.W	D4		; trop  gauche ?
	JUMP',NC 10$
	CLR.W	D4
10$:
	COMP.W	D4,(A0)+ODFDX	; trop  droite ?
	JUMP',LT 15$
	LOAD.W	D4,(A0)+ODFDX
	DEC.W	D4
15$:
	SWAP.W	D4
	TEST.W	D4		; trop en haut ?
	JUMP',NC 20$
	CLR.W	D4
20$:
	COMP.W	D4,(A0)+ODFDY	; trop en bas ?
	JUMP',LT 25$
	LOAD.W	D4,(A0)+ODFDY
	DEC.W	D4
25$:
	SWAP.W	D4

; Calcul la position absolue dans le grand bitmap $DIS_0.

	ADD.W	D4,(A0)+ODFX
	SWAP.W	D4
	ADD.W	D4,(A0)+ODFY
	SWAP.W	D4		; D4 <-- position dans $DIS_0 !

; Envoie la commande secrte et mystrieuse de positionnement.

 	LOAD.L	A4,#(A6)+OBUDIS+1
	LOAD.B	(A4)+0,#'P	; <P>
	LOAD.L	(A4)+1,D4	; <yy> <xx>
	CLR.B	(A4)+5
	LOAD.W	D3,#TYPIO	; D3 <-- type du driver souris
	LIB	?GCHMOU		; D6 <-- canal souris
	FOS	?COMMAND

	POPM.L	D3,D4,D6,A4
	RET





; Routines graphiques rapides
; ---------------------------



;--------\\
; DRICONE >
;========/

; Dessine une icne de IBP64.

; in	D3.B	code de l'icne (0..127)
;	D4.L	position coin inf/gauche (y;x)
;	D5.L	dimensions (dy;dx)
;	D2.W	mode
; out	-
; mod	D7.W

DRICONE:
	PUSHM.L	D0..D5,A1,A2,A4

	CLR.W	D1
	LOAD.B	D1,D3		; D1 <-- code de l'icne

	LOAD.L	A4,(A6)+OPGICO	; A4 <-- ^gencar IBP64

	LOAD.L	D3,D5		; D3 <-- dimensions

	CLR.W	D5
	LOAD.B	D5,(A4)+OGCMWB	; D5 <-- largeur en bytes

	MUL.WU	D1,(A4)+OGCMSB
	ADD.L	A4,#OGCMAT
	ADD.L	A4,D1		; A4 <-- ^la bonne matrice

	LOAD.W	D1,D2		; D1 <-- mode
	CLR.B	D2		; D2 <-- pas d'inversion vido
	COMP.B	D1,#INVDOT
	JUMP,EQ 50$
	TEST.B	(A6)+OINV	; fond de l'cran blanc ?
	JUMP,F	50$		; non => 50$
	NOT.B	D2		; D2 <-- inversion vido
50$:
	LOAD.L	A2,A0		; A2 <-- ^descripteur de la fentre
	LOAD.L	A1,(A6)+OADMATRIX
	CALL	(A1)		; appel de GRA_MATRIX

	POPM.L	D0..D5,A1,A2,A4
	RET


;--------\\
; DRRECT  >
;========/

; Dessine un rectangle.

; in	D3.L	coordonne origine (y;x)
;	D4.L	dimensions (dy;dx)
;	D2.W	mode
; out	-
; mod	D7.W

DRRECT:
	PUSHM.L	D3..D5

	LOAD.L	D5,D4		; D5 <-- dimensions (dy;dx)

	AND.L	D4,#H'FFFF
	CALL	DRLINE		; trace ligne suprieure

	LOAD.L	D4,D5
	CLR.W	D4
	CALL	DRLINE		; trace ligne de droite

	LOAD.L	D4,D5
	AND.L	D4,#H'FFFF
	NEG.W	D4
	CALL	DRLINE		; trace ligne infrieure

	LOAD.L	D4,D5
	SWAP.W	D4
	NEG.W	D4
	SWAP.W	D4
	CLR.W	D4
	CALL	DRLINE		; trace ligne de gauche

	POPM.L	D3..D5
	RET


;---------\\
; DRRASTER >
;=========/

; Dplace une surface rectangulaire mmoire/cran --> mmoire/cran.

; in	D3.L	coordonne source (y;x)
;	A3.L	^mmoire source/^nil si cran
;	D5.W	Iy source (si mmoire)
;	----
;	D4.L	coordonne destination (y;x)
;	A4.L	^mmoire destination/^nil si cran
;	D6.W	Iy destination (si mmoire)
;	----
;	D1.L	hauteur/largeur (y;x)
;	D2.B	opration (INVDOT, SETDOT, CLRDOT ou LOADDOT)
; out	-
; mod	D7.W

DRRASTER:
	PUSHM.L	D1,D2,A1,A2

	TEST.W	D1		; dx <= 0 ?
	JUMP',LE 90$
	SWAP.W	D1
	TEST.W	D1		; dy <= 0 ?
	JUMP',LE 90$
	SWAP.W	D1

	EX.L	D1,D2		; D2/D1 <-- mode/dimensions
	LOAD.L	A2,A0		; A2 <-- ^descripteur de la fentre
	LOAD.L	A1,(A6)+OADRASTER
	CALL	(A1)		; appel de GRA_RASTER
90$:
	POPM.L	D1,D2,A1,A2
	RET


;-------\\
; DRDOT  >
;=======/

; Dessine un point.

; in	D3.L	coordonne (y;x)
;	D2.W	mode
; out	-
; mod	D7.W

DRDOT:
	PUSHM.L	D1..D4,A1,A2

	LOAD.W	D1,D2		; D1 <-- mode
	LOAD.L	D4,D3		; D4 <-- y;x
	LOAD.L	A2,A0		; A2 <-- ^descripteur de la fentre
	LOAD.L	A1,(A6)+OADDOT
	CALL	(A1)		; appel de GRA_DOT

	POPM.L	D1..D4,A1,A2
	RET


;--------\\
; DRLINE  >
;========/

; Dessine un segment de droite.

; in	D3.L	coordonne origine (y;x)
;	D4.L	dimensions (dy;dx)
;	D2.W	mode
; out	D3.L	coordonne d'arrive (y;x)
; mod	D3.L, D7.W

DRLINE:
	PUSHM.L	D1,D2,D4,A1,A2

	LOAD.W	D1,D2		; D1 <-- mode
	EX.L	D3,D4		; D4/D3 <-- y;x/dy;dx
	LOAD.L	A2,A0		; A2 <-- ^descripteur de la fentre
	LOAD.L	A1,(A6)+OADLINE
	CALL	(A1)		; appel de GRA_LINE

	EX.L	D3,D4
	ADD.W	D3,D4		; D3 <-- arrive en X
	SWAP.W	D3
	SWAP.W	D4
	ADD.W	D3,D4		; D3 <-- arrive en Y
	SWAP.W	D3
;	SWAP.W	D4

	POPM.L	D1,D2,D4,A1,A2
	RET


;----------\\
; DRELLIPSE >
;==========/

; Dessine une ellipse, ou un arc d'ellipse.

; in	D3.L	coordonne centre (y;x)
;	D4.L	rayons (dy;dx)
;	D2.W	mode
;	D1.B	bitmap des octants  dessiner
; out	-
; mod	D7.W

DRELLIPSE:
	PUSHM.L	D1..D4,A1,A2

	EX.L	D1,D2		; D2/D1 <-- mode/octants
	EX.L	D3,D4		; D4/D3 <-- y;x/dy;dx
	LOAD.L	A2,A0		; A2 <-- ^descripteur de la fentre
	LOAD.L	A1,(A6)+OADELLIPSE
	CALL	(A1)		; appel de GRA_ELLIPSE

	POPM.L	D1..D4,A1,A2
	RET


;---------\\
; DRTRADEF >
;=========/

; Dfinit une trame.

; in	D3.L	trame
;	D4.L	trame
; out	-
; mod	D7.W

DRTRADEF:
	PUSHM.L	D1..D4

	COMP.B	(A6)+OMACHINE,#SMAKY100
	JUMP',NE 80$
				; si SMAKY100 =>
	LOAD.W	D1,#4-1
20$:
	CALL	FLIP
	RR.L	D3,#8
	DECJ.W,NMO D1,20$

	EX.L	D3,D4
	LOAD.W	D1,#4-1
30$:
	CALL	FLIP
	RR.L	D3,#8
	DECJ.W,NMO D1,30$
	EX.L	D4,D3
80$:
	LOAD.L	(A0)+ODFTRA+0,D3
	LOAD.L	(A0)+ODFTRA+4,D4

	POPM.L	D1..D4
	RET

;--------\\
; FLIP    >
;--------/

; Permute tous les bits de D3.B. Pas de boucle pour tre
; rapide, et pas de table de 256 bytes pour conomiser la RAM !

; in	D3.B	byte
; out	D3.B	byte "flipp"
; mod	D2.B, D3.B

FLIP:
	RLX.B	D3
	RRX.B	D2		; D2 <-- bit 0
	RLX.B	D3
	RRX.B	D2		; D2 <-- bit 1
	RLX.B	D3
	RRX.B	D2		; D2 <-- bit 2
	RLX.B	D3
	RRX.B	D2		; D2 <-- bit 3
	RLX.B	D3
	RRX.B	D2		; D2 <-- bit 4
	RLX.B	D3
	RRX.B	D2		; D2 <-- bit 5
	RLX.B	D3
	RRX.B	D2		; D2 <-- bit 6
	RLX.B	D3
	RRX.B	D2		; D2 <-- bit 7

	LOAD.B	D3,D2		; D3 <-- byte "flipp"
	RET


;---------\\
; DRTRAME  >
;=========/

; Dessine une surface rectangulaire.

; in	D3.L	coordonne origine (y;x)
;	D4.L	dimensions (dy;dx)
;	D2.W	mode
; out	-
; mod	D7.W

DRTRAME:
	PUSHM.L	D1..D4,A1,A2,A4

	TEST.W	D4		; dx <= 0 ?
	JUMP',LE 90$
	SWAP.W	D4
	TEST.W	D4		; dy <= 0 ?
	JUMP',LE 90$
	SWAP.W	D4

	LOAD.W	D1,D2		; D1 <-- mode
	EX.L	D3,D4		; D4/D3 <-- y;x/dy;dx
	LOAD.L	A4,#(A0)+ODFTRA	; A4 <-- ^trame utilisateur
	LOAD.L	A2,A0		; A2 <-- ^descripteur de la fentre
	LOAD.L	A1,(A6)+OADTRAME
	CALL	(A1)		; appel de GRA_TRAME
90$:
	POPM.L	D1..D4,A1,A2,A4
	RET


;--------\\
; DRZONE  >
;========/

; Efface, allume ou inverse une surface rectangulaire.

; in	D3.L	coordonne origine (y;x)
;	D4.L	dimensions (dy;dx)
;	D2.W	mode
; out	-
; mod	D7.W

DRZONE:
	COMP.B	D2,#INVDOT
	JUMP,EQ DRINV
	COMP.B	D2,#SETDOT
	JUMP,EQ DRSET

;---------\\
; DRCLEAR  >
;=========/

; Efface une surface rectangulaire.

; in	D3.L	coordonne origine (y;x)
;	D4.L	dimensions (dy;dx)
; out	-
; mod	D7.W

DRCLEAR:
	TEST.B	(A6)+OINV	; fond de l'cran blanc ?
	JUMP,T	DRSET0		; oui => DRSET0
DRCLEAR0:
	PUSHM.L	D1..D4,A1,A2

	TEST.W	D4		; dx <= 0 ?
	JUMP',LE 90$
	SWAP.W	D4
	TEST.W	D4		; dy <= 0 ?
	JUMP',LE 90$
	SWAP.W	D4

	LOAD.W	D1,D2		; D1 <-- mode
	EX.L	D3,D4		; D4/D3 <-- y;x/dy;dx
	LOAD.L	A2,A0		; A2 <-- ^descripteur de la fentre
	LOAD.L	A1,(A6)+OADCLEAR
	CALL	(A1)		; appel de GRA_SET
90$:
	POPM.L	D1..D4,A1,A2
	RET

;---------\\
; DRSET    >
;=========/

; Allume une surface rectangulaire.

; in	D3.L	coordonne origine (y;x)
;	D4.L	dimensions (dy;dx)
; out	-
; mod	D7.W

DRSET:
	TEST.B	(A6)+OINV	; fond de l'cran blanc ?
	JUMP,T	DRCLEAR0	; oui => DRCLEAR0
DRSET0:
	PUSHM.L	D1..D4,A1,A2

	TEST.W	D4		; dx <= 0 ?
	JUMP',LE 90$
	SWAP.W	D4
	TEST.W	D4		; dy <= 0 ?
	JUMP',LE 90$
	SWAP.W	D4

	LOAD.W	D1,D2		; D1 <-- mode
	EX.L	D3,D4		; D4/D3 <-- y;x/dy;dx
	LOAD.L	A2,A0		; A2 <-- ^descripteur de la fentre
	LOAD.L	A1,(A6)+OADSET
	CALL	(A1)		; appel de GRA_SET
90$:
	POPM.L	D1..D4,A1,A2
	RET

;---------\\
; DRINV    >
;=========/

; Inverse une surface rectangulaire.

; in	D3.L	coordonne origine (y;x)
;	D4.L	dimensions (dy;dx)
; out	-
; mod	D7.W

DRINV:
	PUSHM.L	D1..D4,A1,A2

	TEST.W	D4		; dx <= 0 ?
	JUMP',LE 90$
	SWAP.W	D4
	TEST.W	D4		; dy <= 0 ?
	JUMP',LE 90$
	SWAP.W	D4

	LOAD.W	D1,D2		; D1 <-- mode
	EX.L	D3,D4		; D4/D3 <-- y;x/dy;dx
	LOAD.L	A2,A0		; A2 <-- ^descripteur de la fentre
	LOAD.L	A1,(A6)+OADINV
	CALL	(A1)		; appel de GRA_INV
90$:
	POPM.L	D1..D4,A1,A2
	RET


;--------\\
; DRFILL  >
;========/

; Rempli une surface quelconque.

; in	D3.L	point de remplissage (y;x)
; out	D7.W	erreur
; mod	D7.W

DRFILL:
	PUSHM.L	D1..D4,A1,A2

	LOAD.L	D4,D3		; D4 <-- y;x
	LOAD.L	A2,A0		; A2 <-- ^descripteur de la fentre
	LOAD.L	A1,(A6)+OADFILLO
	CALL	(A1)		; appel de GRA_FILLO
	PUSH.W	D7
	LOAD.L	A1,(A6)+OADFILLC
	CALL	(A1)		; appel de GRA_FILLC
	POP.W	D7

	POPM.L	D1..D4,A1,A2
	TEST.W	D7		; retour EQ/NE
	RET



;--------\\
; AFIMAGE >
;========/

; Affiche une image, sans la conserver en mmoire.

; in	A3.L	^nom de l'image
; out	D7.W	erreur
; mod	D7.W

AFIMAGE:
	PUSH.L	A4

	CALL	LOADIMAGE	; charge l'image en mmoire
	JUMP,NE 90$
	CALL	SHOWIMAGE	; affiche l'image
	CALL	KILLIMAGE	; libre la mmoire
90$:
	POP.L	A4
	TEST.W	D7		; retour EQ/NE
	RET

;----------\\
; LOADIMAGE >
;==========/

; Charge une image en mmoire.

; in	A3.L	^nom de l'image
; out	A4.L	^image
;	D4.L	dimensions (dy;dx)
;	D7.W	erreur
; mod	A4.L, D7.W, A4.L

LOADIMAGE:
	PUSHM.L	D0,D1,D3,D6,A1..A3,A5

	LOAD.L	A5,A3		; A5 <-- ^nom de l'image

	LOAD.L	D4,#LGHIMA
	LOAD.W	D1,#MTYPCP
	GESMEM	?GETMEM		; demande un buffer pour l'en-tte
	JUMP,NE 90$
	LOAD.L	A2,A4		; A2 <-- ^en-tte

	LOAD.W	D3,#2^BOPRD!2^BOPSYS ; D3 <-- mode d'ouverture
	FOS	?OPEN		; ouvre l'image
	JUMP,NE 84$

	LOAD.L	A4,A2
	FOS	?RDBYTE		; lit l'en-tte
	JUMP,NE 82$

	COMP.B	(A2)+OIMTYP,#H'82 ; image du LAMI ?
	JUMP',NE 20$		; non => 20$
				; oui =>
	CLR.B	D3
	LOAD.L	D4,#256
	FOS	?SPOS		; saute la stupide en-tte de 256 bytes !
	JUMP,NE 82$

	LOAD.L	D4,#LGHIMA
	FOS	?RDBYTE		; lit l'en-tte
	JUMP,NE 82$
20$:
	LOAD.W	D0,(A2)+OIMDLX	; D0 <-- largeur de l'image
	LOAD.W	D1,(A2)+OIMDLY	; D1 <-- hauteur de l'image

	LOAD.W	D4,D0
	SR.W	D4,#3
	MUL.WU	D4,D1		; D4 <-- largeur*hauteur/8
	ADD.L	D4,#IMLBUF	; D4 <-- rserve pour codage
	PUSH.W	D1
	LOAD.W	D1,#MTYPCP
	GESMEM	?GETMEM		; demande un buffer pour toute l'image
	POPM.W	D1
	JUMP,NE 82$
	LOAD.L	A1,#(A4)+IMLBUF	; A1 <-- ^image

	LOAD.L	D4,(A2)+OIMNBB	; D4 <-- longueur  lire
	TEST.B	(A2)+OIMCOD	; image code ?
	JUMP',NE 30$		; oui => 30$
				; non =>
	LOAD.L	A4,A1
	FOS	?RDBYTE		; lit toute l'image dcode
	JUMP,NE 80$
	JUMP'	35$
30$:
	FOS	?RDBYTE		; lit toute l'image code
	JUMP,NE 80$
	LOAD.L	A3,A1
	GRA_	DECOIMA		; dcode l'image ...
	JUMP,NE 80$
35$:
	TEST.B	(A6)+OINV	; fond de l'cran blanc ?
	JUMP,T	40$		; oui => 40$
	CALL	INVIMAGE	; inverse compltement l'image
40$:
	LOAD.L	A4,A1		; A4 <-- ^image

	LOAD.W	D4,D1
	SWAP.W	D4
	LOAD.W	D4,D0		; D4 <-- dimensions de l'image

	CLR.W	D7		; D7 <-- ok
	JUMP	82$

80$:
	PUSH.W	D7
	LOAD.L	A4,#(A1)-IMLBUF
	LOAD.W	D1,#MTYPCP
	GESMEM	?GIVMEM		; rend la mmoire de l'image
	POP.W	D7
82$:
	PUSH.W	D7
	FOS	?CLOSE		; ferme l'image
	POP.W	D7
84$:
	PUSHM.L	D7,A4
	LOAD.L	A4,A2
	LOAD.W	D1,#MTYPCP
	GESMEM	?GIVMEM		; rend le buffer pour l'en-tete
	POPM.L	D7,A4
90$:
	POPM.L	D0,D1,D3,D6,A1..A3,A5
	TEST.W	D7		; retour EQ/NE
	RET

;----------\\
; SHOWIMAGE >
;==========/

; Affiche une image dans la (sous-)fentre.
; Si elle est trop petite, elle est centre au milieu de l'cran.
; Si elle est trop grande, on affiche sa partie centrale.

; in	A4.L	^image
;	D4.L	dimensions (dy;dx)
; out	-
; mod	D7.W

SHOWIMAGE:
	PUSHM.L	D0,D1,D3,D4,A3

	LIB	?AFTIM
	.B	NOCURS		; plus de curseur
	.B	EOP		; efface toute la fentre
	.B	0
	.EVEN

	LOAD.W	D0,D4		; D0 <-- largeur de l'image
	SWAP.W	D4
	LOAD.W	D1,D4		; D1 <-- hauteur de l'image

	LOAD.L	A3,#(A6)+OBUDIS	; A3 <-- ^buffer pour DRAWRASTER

	LOAD.W	D3,D0
	SR.W	D3,#3
	LOAD.W	(A3)+10,D3	; source: <ii>
	CLR.W	(A3)+20		; destination: <ii>

	LOAD.L	D4,(A0)+ODFFDY	; D4 <-- dimensions de la fentre
	COMP.W	D0,D4		; image trop large ?
	JUMP',HI 50$		; oui => 50$
	CLR.W	(A3)+2		; source: <xx>
	LOAD.W	(A3)+22,D0	; image: <dxx>
	SUB.W	D4,D0
	SR.W	D4,#1
	LOAD.W	(A3)+12,D4	; destination: <xx>
	JUMP'	55$
50$:
	SUB.W	D0,D4
	SR.W	D0,#1
	LOAD.W	(A3)+2,D0	; source: <xx>
	CLR.W	(A3)+12		; destination: <xx>
	LOAD.W	(A3)+22,D4	; image: <dxx>
55$:
	SWAP.W	D4
	COMP.W	D1,D4		; image trop haute ?
	JUMP',HI 60$		; oui => 60$
	CLR.W	(A3)+4		; source: <yy>
	LOAD.W	(A3)+24,D1	; image: <dyy>
	SUB.W	D4,D1
	SR.W	D4,#1
	LOAD.W	(A3)+14,D4	; destination: <yy>
	JUMP'	65$
60$:
	SUB.W	D1,D4
	SR.W	D1,#1
	LOAD.W	(A3)+4,D1	; source: <yy>
;	ADD.W	(A3)+14,#0	; destination: <yy>
	LOAD.W	(A3)+24,D4	; image: <dyy>
65$:
	LOAD.W	(A3)+0,#DRAWRASTER
	LOAD.L	(A3)+6,A4	; source: <pppp>
	CLR.L	(A3)+16		; destination: <pppp>
	LOAD.B	(A3)+26,#SETDOT	; image: <mode>
	LOAD.W	D3,#1+26	; D3 <-- longueur
	LIB	?STRING		; affiche l'image

	POPM.L	D0,D1,D3,D4,A3
	RET

;----------\\
; KILLIMAGE >
;==========/

; Libre la mmoire d'une image.

; in	A4.L	^image
; out	-
; mod	-

KILLIMAGE:
	PUSHM.L	D1,D7,A4

	LOAD.L	A4,#(A4)-IMLBUF
	LOAD.W	D1,#MTYPCP
	GESMEM	?GIVMEM		; rend la mmoire de l'image

	POPM.L	D1,D7,A4
	RET

;---------\
; INVIMAGE >
;---------/

; Inverse compltement une image.

; in	A1.L	^image
;	D0.W	largeur
;	D1.W	hauteur
; out	-
; mod	D7.W

INVIMAGE:
	PUSHM.L	D0,A1

	SR.W	D0,#3		; D0 <-- largeur en bytes
	MUL.WU	D0,D1		; D0 <-- nb total de bytes
	SR.W	D0,#2		; D0 <-- nb total de .L
	DEC.W	D0		; D0 <-- -1  cause NMO
20$:
	NOT.L	(A1+)
	DECJ.W,NMO D0,20$

	POPM.L	D0,A1
	RET






; Tirage de nombres alatoires
; ----------------------------



;--------\\
; COUPSAC >
;========/

; Coup de sac pour le gnrateur alatoire.

; in	-
; out	-
; mod	D7.W

COUPSAC:
	PUSHM.L	D3,D4

	LIB	?RDCLOCK	; D3/D4 <-- date et heure
	RR.L	D3,#3
	RL.L	D4,#7		; savante cuisine
	NOT.L	D3
	XOR.L	D4,D3
	LOAD.L	(A6)+OHAZA+0,D3
	LOAD.L	(A6)+OHAZA+4,D4

	LOAD.W	D3,#10-1
20$:
	CALL	HAZARD		; tire qq nombres
	DECJ.W,NMO D3,20$

	POPM.L	D3,D4
	RET

;---------\\
; EXHAZARD >
;=========/

; Tire un nombre alatoire exclusif.

; in	D3.W	+/- borne infrieure (min)
;	D4.W	+/- borne suprieure (max+1)
;	A4.L	^table d'exclusion
; out	D4.W	+/- nombre alatoire: D3 <= n < D4
; mod	D4.L, D7.W

EXHAZARD:
	PUSHM.L	D0..D3,A3

	LOAD.W	D2,D4
10$:
	LOAD.W	D1,D2
	SUB.W	D1,D3
	MUL.WU	D1,#3		; D1 <-- nb max d'essais
20$:
	LOAD.W	D4,D2		; D4 <-- borne suprieure
	CALL	MMHAZARD	; D4 <-- nombre alatoire

	LOAD.W	D0,D4
	SUB.W	D0,D3
	TEST.B	(A4)+(D0.W)	; nombre dj sorti ?
	JUMP,EQ 80$		; non => 80$
				; oui =>
	DEC.W	D1		; encore un essai ?
	JUMP,NE 20$		; oui => 20$

	LOAD.L	A3,A4
	LOAD.W	D1,D2
	SUB.W	D1,D3
40$:
	CLR.B	(A3+)		; recommence le tirage exclusif
	DEC.W	D1
	JUMP,NE 40$
	JUMP	10$

80$:
	SET.B	(A4)+(D0.W)	; celui-i est pris

	POPM.L	D0..D3,A3
	RET

;---------\\
; MMHAZARD >
;=========/

; Tire un nombre alatoire (16 bits) compris entre deux bornes.

; in	D3.W	+/- borne infrieure (min)
;	D4.W	+/- borne suprieure (max+1)
; out	D4.W	+/- nombre alatoire: D3 <= n < D4
; mod	D4.L, D7.W

MMHAZARD:
	PUSH.W	D2

	LOAD.W	D2,D4
	SUB.W	D2,D3		; D2 <-- sup - inf
	CALL	HAZARD

	AND.L	D4,#H'FFFF
	DIV.WU	D4,D2
	SWAP.W	D4		; D4 <-- reste de la division
	ADD.W	D4,D3

	POP.W	D2
	RET

;--------\\
; HAZARD  >
;========/

; Tire un nombre alatoire de 32 bits.
; On utilise un registre  dcalage de 63 bits, avec un XNOR entre
; les bits 0 et 60 pour calculer le nouveau bit inject.

; in	-
; out	D4.L	nombre
; mod	D4.L, D7.W

HAZARD:
	PUSHM.L	D2,D3

	LOAD.W	D2,#32-1

	LOAD.L	D3,(A6)+OHAZA+0
	LOAD.L	D4,(A6)+OHAZA+4
10$:
	TEST.L	D4:#1
	JUMP,BC 20$
	TEST.L	D3:#30
	JUMP,BC 35$
	JUMP	30$
20$:
	TEST.L	D3:#30
	JUMP,BS 35$
30$:
	CLRX
	RRX.L	D3,#1
	RRX.L	D4,#1
	JUMP	40$
35$:
	SETX
	RRX.L	D3,#1
	RRX.L	D4,#1
40$:
	LOAD.L	(A6)+OHAZA+0,D3
	LOAD.L	(A6)+OHAZA+4,D4

	DECJ.W,NMO D2,10$

	POPM.L	D2,D3
	RET







; Debug
; -----


DRD0:
	PUSHM.L	D2..D4

	LOAD.W	D2,#SETDOT

	LOAD.L	D3,D0
	SUB.W	D3,#10
	CLR.L	D4
	LOAD.W	D4,#20
	LIB	?DRSEG

	LOAD.L	D3,D0
	SWAP.W	D3
	SUB.W	D3,#10
	SWAP.W	D3
	LOAD.W	D4,#20
	SWAP.W	D4
	CLR.W	D4
	LIB	?DRSEG

	POPM.L	D2..D4
	RET

DRD0C:
	PUSHM.L	D2..D4

	LOAD.W	D2,#CLRDOT

	LOAD.L	D3,D0
	SUB.W	D3,#10
	CLR.L	D4
	LOAD.W	D4,#20
	LIB	?DRSEG

	LOAD.L	D3,D0
	SWAP.W	D3
	SUB.W	D3,#10
	SWAP.W	D3
	LOAD.W	D4,#20
	SWAP.W	D4
	CLR.W	D4
	LIB	?DRSEG

	POPM.L	D2..D4
	RET


AFCOOR:
	PUSH.L	D4

	LIB	?AFTIM
	.ASCIZ	" x="
	.EVEN
	CALL	AFD4

	SWAP.W	D4
	LIB	?AFTIM
	.ASCIZ	" y="
	.EVEN
	CALL	AFD4

	POP.L	D4
	RET

AFD4:
	PUSHM.L	D2..D4

	AND.L	D4,#H'FFFF
	TEST.W	D4
	JUMP,NC 20$
	LOAD.B	D3,#'-
	LIB	?AFCAR
	NEG.W	D4
20$:
	LOAD.W	D3,#8
	LOAD.W	D2,#2^BAFDCM
	LIB	?AFDEC

	POPM.L	D2..D4
	RET




; Textes
; ------

TXMENU0:
	.ASCIZ	""
	.ASCIZ	"Fin"

	.ASCIZ	"Suite des"
	.ASCIZ	"explications ..."

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""


TXMENU1:
	.ASCIZ	""
	.ASCIZ	"Fin"

	.ASCIZ	""
	.ASCIZ	"Dbut du jeu"

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""


TXMENU2:
	.ASCIZ	""
	.ASCIZ	"Fin"

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	"Aide"


TXMENU3:
	.ASCIZ	""
	.ASCIZ	"Fin"

	.ASCIZ	""
	.ASCIZ	"Relance une balle"

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	""

	.ASCIZ	""
	.ASCIZ	"Aide"


NHIMA:	.ASCIZ	"BONG_AIDE.IMAGE"
NOIMA:	.ASCIZ	"BONG_OBJ.IMAGE"
NMIMA:	.ASCIZ	"BONG_JEU.IMAGE"
	.EVEN






	.END	START
