* Fond de programme de scrolling
* Par Christophe LARATTE
* En Aout 1992

* Je n'utilise pas les includes afin de faciliter la compilation (+ rapide)

* Exec.library
AllocMem		=	-198
CloseLibrary		=	-414
FreeMem			=	-210
GetMsg			=	-372
OpenLibrary		=	-552
ReplyMsg		=	-378
WaitPort		=	-384

* Graphics.library
Move			=	-240
ScrollRaster		=	-396
Text			=	-60

* Intuition.library
CloseScreen		=	-066
CloseWindow		=	-072
OpenScreen		=	-198
OpenWindow		=	-204
ShowTitle		=	-282
ViewPortAddress		=	-300

wd_RPort		=	$32
wd_UserPort		=	$56

Class			=	$14
Code			=	$18
MouseY			=	$22

; tous les adressages sur la partie data du programme sont effectués
; en relatif, c.a.d avec par exemple move.l truc(pc),a0
; ainsi on ne crée pas de hunk reloc32, hunk qui sert à corriger
; les adresses quand on effectue des adressages en absolu
; ex : move.l truc,a0


	move.l	4.w,a6			Ouverture d'intuition
	moveq	#33,d0			la version 33 correspond à la
	lea	IntuitionName(pc),a1	plus vieille encore en service
	jsr	OpenLibrary(a6)
	lea	_IntuitionBase(pc),a0	| aurait pu être remplacé par
	move.l	d0,(a0)			| move.l d0,IntutionBase
; mais cette méthode est moins belle car elle oblige le compilateur
; a créer un hunk reloc32. Donc en fait on perd de la place.
	beq	NoInt

	moveq	#33,d0			Ouverture de graphics
	lea	GfxName(pc),a1
	jsr	OpenLibrary(a6)
	lea	_GfxBase(pc),a0
	move.l	d0,(a0)
	beq	NoGfx

	lea	Title(pc),a0		; toujours pour ne pas créer
	lea	TitleAddress(pc),a1	; de reloc32
	move.l	a0,(a1)			;

	move.l	_IntuitionBase(pc),a6	Ouverture de l'écran
	lea	NewScreen(pc),a0
	jsr	OpenScreen(a6)
	lea	Screen(pc),a0		l'adresse de l'écran est sauvegardé
	move.l	d0,(a0)			dans la structure de la fenêtre
	beq	NoScreen		ainsi on gagne pas mal de place

	lea	NewWindow(pc),a0	Ouverture de la fenêtre
	jsr	OpenWindow(a6)
	lea	Window(pc),a0
	move.l	d0,(a0)
	beq	NoWindow

	jsr	ViewPortAddress(a6)	Sauvegarde des ports
	lea	ViewPort(pc),a0
	move.l	d0,(a0)
	move.l	Window(pc),a0
	lea	RastPort(pc),a1
	move.l	wd_RPort(a0),(a1)
	lea	UserPort(pc),a1
	move.l	wd_UserPort(a0),(a1)
	bsr	RedrawDisplay		on initialise l'affichage

Attente	move.l	4.w,a6			Attend une action
	move.l	UserPort(pc),a4
	move.l	a4,a0
	jsr	WaitPort(a6)		<= cette fonction système endort
	move.l	a4,a0			   le programme jusqu'à ce que
	jsr	GetMsg(a6)	<=\	   vous le réveilliez en utilisant
	move.l	d0,a1		  |	   la souris, ainsi il n'utilise pas
	move.l	Class(a1),a3	  |	   de cycle CPU (le microprocesseur)
	move.w	Code(a1),a2	  \======= récupère le message en provenance
	move.w	MouseY(a1),d2		   d'intuition
	jsr	ReplyMsg(a6)		<= averti intuition qu'on a pris
	cmp.l	#$10,a3			   connaissance du message et qu'il
					 ; peut l'enlever
	beq.s	MouseMove
	cmp.l	#8,a3			<= si Class n'est pas à 8 alors il
	bne.s	Attente			   ne s'agit pas de la souris
	cmp.w	#$69,a2			<= si on appuie sur le bouton droit
	beq	END			<= c'est la fin !
	lea	MouseFlag(pc),a0
	cmp.w	#$68,a2
	bne.s	.Cont
	move.b	#-1,(a0)		si le bouton est appuyé alors
	bra.s	Attente			MouseFlag vaut -1
.Cont	move.b	#0,(a0)			sinon il vaut 0
	bra.s	Attente

MouseMove
	move.b	MouseFlag(pc),d0
	tst.b	d0			si le bouton gauche est relaché
	beq.s	Attente			ça ne nous intéresse pas
	tst.w	d2	
	bpl.s	.Précédent		si le déplacement est positif alors
	move.l	_GfxBase(pc),a6		la souris a été vers la bas, donc
	move.l	RastPort(pc),a1		on affiche ce qui précède
	moveq	#0,d0			sinon on affiche ce qui suit
	moveq	#8,d1
	moveq	#0,d2
	moveq	#12,d3
	move.w	#639,d4
	move.w	#251,d5
	jsr	ScrollRaster(a6)
	move.l	RastPort(pc),a1
	moveq	#0,d0
	move.w	#250,d1
	jsr	Move(a6)
	lea	BaseDisplay(pc),a5
	move.l	(a5),a0
	add.l	#30*80,a0
	move.l	RastPort(pc),a1
	moveq	#80,d0
	jsr	Text(a6)
	add.l	#80,(a5)
	bra.s	.End
.Précédent
	move.l	_GfxBase(pc),a6
	move.l	RastPort(pc),a1
	moveq	#0,d0
	moveq	#-8,d1			<= on descend une partie de l'écran
	moveq	#0,d2			et cette partie libérée sera remplise
	moveq	#12,d3			par...
	move.w	#639,d4
	move.w	#251,d5
	jsr	ScrollRaster(a6)
	move.l	RastPort(pc),a1
	moveq	#0,d0
	move.w	#18,d1
	jsr	Move(a6)
	lea	BaseDisplay(pc),a5
	sub.l	#80,(a5)
	move.l	(a5),a0
	move.l	RastPort(pc),a1
	moveq	#80,d0
	jsr	Text(a6)		... du texte
.End	bsr.s	RedrawTitle
	bra	Attente


END	move.l	_IntuitionBase(pc),a6
	move.l	Window(pc),a0
	jsr	CloseWindow(a6)
NoWindow
	move.l	Screen(pc),a0
	jsr	CloseScreen(a6)
NoScreen
	move.l	4.w,a6
	move.l	_GfxBase(pc),a1
	jsr	CloseLibrary(a6)
NoGfx	move.l	_IntuitionBase(pc),a1
	jsr	CloseLibrary(a6)
NoInt	moveq	#0,d0
	rts


*  Supers routines   *

RedrawDisplay
	bsr.s	RedrawTitle
	moveq	#0,d7
	move.l	_GfxBase(pc),a6
.Cont	move.l	RastPort(pc),a1
	lea	BaseDisplay(pc),a5
	moveq	#0,d0
	move.w	d7,d1
	lsl.w	#3,d1			équivaut à mulu #8,d1 en plus rapide
	add.w	#18,d1
	jsr	Move(a6)
	move.l	(a5),a0
	move.l	RastPort(pc),a1
	moveq	#80,d0
	jsr	Text(a6)
	add.l	#80,(a5)
	addq.w	#1,d7
	cmp.w	#30,d7			simple boucle de 30 itérations
	bne.s	.Cont			on affiche donc ligne par ligne
	rts

RedrawTitle
	move.l	BaseDisplay(pc),d2	convertion d'un mot long
	lea	Title(pc),a0		en ASCII
	moveq	#1,d1
.Cont	rol.l	#4,d2
	move.b	d2,d0
	and.b	#%1111,d0
	add.b	#'0',d0
	cmp.b	#'9',d0
	ble.s	.Cont0
	addq.b	#'A'-'9'-1,d0
.Cont0	move.b	d0,(a0,d1.w)
	addq.b	#1,d1
	cmp.b	#9,d1
	bne.s	.Cont
	move.l	Screen(pc),a0
	moveq	#1,d0
	move.l	_IntuitionBase(pc),a6
	jsr	ShowTitle(a6)		je n'aime pas tellement cette méthode
	rts				mais faute de mieux...


MouseFlag	dc.b	0
 ; l'utilisation d'un flag pour savoir si le bouton gauche est appuyé
 ; est très mauvaise ! A vous d'en trouver une autre !
 ; (pensez à tester les bits de XXXX)

		even
 ; indispensable entre un octet et un mot ou mot long. Ainsi le programme
 ; met la prochaine donnée sur une valeur pair (even). (révisez votre 68000)


BaseDisplay	dc.l	0

ViewPort	dc.l	0
RastPort	dc.l	0
UserPort	dc.l	0

_IntuitionBase	dc.l	0
_GfxBase	dc.l	0
Window		dc.l	0

NewWindow	dc.w 0    		LeftEdge
		dc.w 0			TopEdge
		dc.w 640		Width
		dc.w 256		Height
		dc.b 1			DetailPen
		dc.b 0			BlockPen
		dc.l 8|$10|$100000	IDCMPflags
 ; 8 : MOUSEBUTTON -> dès qu'on appuiera sur un bouton de la souris le
 ; programme sera averti
 ; $10 : MOUVEMOVE -> dès qu'on déplacera la souris, le programme sera averti
 ; $10000 : DELTAMOVE -> les reports dûs à MOUSEMOVE sont transmis en
 ; position relative, c.a.d. par rapport à l'ancienne position

		dc.l $1000|$10000|$100|$800|$200	Flags
 ; $1000 : ACTIVATE -> la fenêtre est active à l'ouverture
 ; $800 : BORDERLESS -> sans bord
 ; $100 : BACKDROP -> la fenêtre est toujours au fond derrière toutes les
 ; autres
 ; $10000 : RMBTRAP -> pas de gestion de menu : on gère le bouton droit
 ; de la souris comme le gauche
 ; $200 : REPORTMOUSE -> averti le programme à chaque déplacement de souris
		dc.l 0			*FirstGadget
		dc.l 0			*CheckMark
		dc.l 0			*Title   (ASCII)
Screen		dc.l 0			*Screen
		dc.l 0			*Bitmap
		dc.w 0			MinWidth
		dc.w 0			MinHeight
		dc.w 0			MaxWidth (-1 : max)
		dc.w 0			MaxHeight
		dc.w $F			Type ($f : CUSTOMSCREEN)


NewScreen	dc.w 0    		LeftEdge
		dc.w 0			TopEdge
		dc.w 640		Width
		dc.w 256		Height
		dc.w 1			Depth
		dc.b 0			DetailPen
		dc.b 1			BlockPen
		dc.w $8000		ViewModes
		dc.w $1F		Type ($f : CUSTOMSCREEN)
		dc.l 0			Font
TitleAddress	dc.l 0			DefaultTitle
		dc.l 0			Gadgets
		dc.l 0			CustomBitMap

Title		dc.b	"$00000000",0

IntuitionName	dc.b	"intuition.library",0
GfxName		dc.b	"graphics.library",0

	END




