;
; Demo grafico (di Pierluigi Montanari)
; (cfr. AmigaByte 36, "Il copper e la libreria grafica")
;
; Per assemblare con il SEKA ASSEMBLER
;
; 1) caricare l'assemblatore
; 2) alle domande iniziali rispondere CHIP (tipo di memoria) e 200
;    (workspace)
; 3) caricare il sorgente con il comando R seguito dal nome del file senza
;    estensione (es.: R [return] AmigaByte_36:Listati/Demo [return])
; 4) assemblare il programma con il comando A (battere solo return alla
;    richiesta "Options")
; 5) salvare su disco l'eseguibile generato con il comando WO seguito dal
;    nome del file che gli si vuole attribuire
;

ALLOCMEM: 	=	-198	; Alcuni offsets di libreria....
FREEMEM:	=	-210
FORBID:		=	-132
PERMIT:		=	-138
OPENLIBRARY:	=	-552
CLOSELIBRARY:	=	-414
INITBITMAP:	=	-390
INITRASTPORT:	=	-198
MOVE:		=	-240
SETAPEN:	=	-342
DRAW:		=	-246
SETRAST:	=	-234
WRITEPIXEL:	=	-324
DRAWELLIPSE:	=	-180
TEXT:		=	-60

START:
	move.l 	$4,a6		;puntatore ad execbase in a6
	jsr 	forbid(a6)	;esegui la routine di sistema forbid
	move.l 	$4,a6		;puntatore ad execbase
	move.l	#20480,d0	;numero di bytes da liberare
	move.l	#2,d1		;attributi = MEMF_CHIP
	jsr	allocmem(a6)	;esegui
	tst.l	d0		;errore ?
	beq	error		;si', allora esci
	move.l	d0,bm_planes	;metti l'indirizzo della zoma di memoria
				;in bm_planes
	move.w	d0,lo		;mette la parte bassa dell' indirizzo alla
				;label "lo" che corrisponde nella copperlist
				;al valore da mettere in BPL1PTL
	swap	d0
	move.w	d0,hi		;mette la parte alta dell' indirizzo in "hi"
				;che corrisponde nella copperlist al valore
				;da mettere in BPL1PTH
	move.l 	$4,a6		;puntatore ad execbase
	move.l	#CopList,d1
	move.l	#EndList,d0
	sub.l	d1,d0		;dimensione della copperlist in d0
	move.l	#2,d1		;attributi = MEMF_CHIP
	jsr	allocmem(a6)	;esegui
	tst.l	d0		;errore ?
	beq	error		;si', allora esci
	move.l	d0,NewCopList	;salviamo l' indirizzo della nuova copperlist
	lea	CopList,a0	;adesso copiamo diligentemente la nostra
	lea	EndList,a1	;copperlist all' indirizzo appena avuto dalla
	move.l	NewCopList,a2	;funzione AllocMem. Questo per essere sicuri
CopiaClst:			;la nostra copperlist risieda EFFETTIVAMENTE
	move.w	(a0)+,(a2)+	;in chip-ram
	cmpi.l	a0,a1
	bne	CopiaClst
	lea 	gfxname,a1	;nome della libreria grafica
	clr.l 	d0		;versione indifferente
	jsr 	openlibrary(a6)	;apri la libreria
	move.l 	d0,gfxbase	;metti il puntatore al sicuro
			;con  le  successive  quattro istruzioni si attiva
			;copperlist: essendo il puntore ad una libreria
			;null'altro che una struttura,nella struttura
			;gfxbase, in una determinata posizione vi e' il
			;puntatore alla copperlist attuale ( lo schermo
			;che state osservando.. ).Prendiamo tale
			;puntatore e lo salviamo , ponendo al suo posto
			;l'indirizzo della nostra copperlist
	add.l 	#$32,d0		;ora puntiamo alla vecchia copperlist..		
	move.l 	d0,a0
	move.l 	(a0),OldCopl	;la salviamo in OldCopl e lo sostituiamo con
	move.l 	NewCopList,(a0)	;l'indirizzo della nuova copperlist in chip-ram
	move.l	gfxbase,a6	;inizializza la rastport...
	move.l	#rastport,a1
	jsr	initrastport(a6)
	move.l	#bitmap,a0	;inizializza la bitmap e la concatena alla
	move.l	a0,rp_bitmap	;rastport
	move.w	#1,d0
	move.w	#640,d1
	move.w	#256,d2
	move.l	gfxbase,a6
	jsr	initbitmap(a6)
				;da qui in poi potete divertirvi
	jsr	cls
	move.w	#0,d0
	move.w	#0,d1
	move.w	#639,d2
	move.w	#80,d3
loop1:	move.w	d0,x1
	move.w	d1,y1
	move.w	d2,x2
	move.w	d3,y2
	jsr 	rect
	addi.w	#10,d0
	addi.w	#5,d1
	subi.w	#10,d2
	subi.w	#5,d3
	cmpi.w	#40,d3
	bne	loop1
	move.l	#testo1,a0
	jsr	print	
	move.l	#testo2,a0
	jsr	print
	move.w	#300,d0
	move.w	#140,d1
	move.w	#80,d2
	move.w	#42,d3
loop2:	move.w	d0,x1
	move.w	d1,y1
	move.w	d2,rx
	move.w	d3,ry
	jsr	circle
	subi.w	#3,d3
	cmpi.w	#0,d3
	bne.s	loop2

WAIT:	andi.b	#$40,$bfe001	;aspetta la pressione del tasto sinistro del
	bne 	WAIT		;mouse

	move.l 	gfxbase,d0	;rimette al suo posto la vecchia copperlist
	add.l 	#$32,d0
	move.l 	d0,a0
	move.l 	oldcopl,(a0)
	move.l 	gfxbase,a1	;chiude la libreria grafica
	jsr 	closelibrary(a6)	
	move.l	$4,a6		;libera la memoria
	move.l	bm_planes,a1
	move.l	#20480,d0
	jsr	freemem(a6)

	move.l	$4,a6		;libera la memoria
	move.l	NewCopList,a1
	move.l	#CopList,d1
	move.l	#EndList,d0
	sub.l	d1,d0		;dimensione della copperlist in d0
	jsr	freemem(a6)

error:	move.l 	$4,a6		;rilascia libero il sistema
	jsr 	permit(a6)
	rts			;ritorna a casa....

;**************************************************************************
;
;                  SUBROUTINES DI TRACCIAMENTO PRIMITIVE
;
; Se  avete  letto  bene l' articolo allegato al presente listato, noterete
; che  non  vi  e'  nulla  di  strano in queste routines, che sono talmente
; semplici da commentarsi (quasi) da sole.Notate infine due cose:
;
; 1) Tutte  le  routines  salvano  i  registri  per  lasciarli  inalterati
;    all'utente
;
; 2) Tali  routines  NON  sono state fatte per la velocita' di esecuzione,
;    bensi'  per  la  semplicita'  di  lettura...   vedremo  poi come usare
;    direttamente il blitter per assolvere a tale compito.
;
; Qui  di  seguito  sono  riportate  le  funzioni  della  libreria  grafica
; utilizzate in questa puntata:
;
;-------------------------------------------------------------------------
;
; Initrastport:	offset di libreria: -198 
;
; Uso:	Initrastport (rp)  
;  	    	      A1	
; 
; Dove:	rp e' il puntatore alla struttura rastport
; 
; Scopo:  inizializza la struttura rastport ai valori standard.
;	La struttura rastport descrive una struttura di controllo di come
; 	in memoria sara' gestita la grafica.
; 
; 
;-------------------------------------------------------------------------
;    
; InitBitMap:	offset di libreria: -390
;
; Uso:   InitBitMap ( bm , depth, width, height )
;                    a0	   d0     d1    d2
; 
; Dove:  bm e' il puntatore alla struttura bitmap
;        depth rappresenta il numero di bitplanes da utilizzare
;        width rappresenta la largheza, in pixels, dei bitplanes
;        height rappresenta l' altezza , in pixels,dei bitplanes
;
; Scopo: Inizializza i vari elementi nella struttura bitmap, i quali
;        rispecchieranno  le  scelte  fatte  con  la chiamata (ovvero con i
;        valori  immesi  nei registri d0-d1-d2).  Bisogna pero' porre nella
;        struttura  (alla  label  bm_planes) gli indirizzi ,in memoria, dei
;        bitplanes stessi.
; 
;-------------------------------------------------------------------------
; 
; Text:		offset di libreria: -60
;
; Uso:	Text ( rp , string , count )
;	       a1     a0       d0
; 
; Dove:  rp e' il puntatore alla struttura rastport
;        string e' il puntatore alla stringa in memoria
;        count e' il numero di caratteri che compongono la stringa
; 
; Scopo: La funzione text serve a scrivere una stringa con il font usato nella
;        posizione desiderata (la posizione la si indica con la funzione move
;        -vedere oltre-).
;
; NOTA.1:  se il testo supera i limiti della rastport, esso viene troncato
;          quando esce.
; 
; NOTA.2:  all' inizializzazione della rastport, il font e' selezionato
;          automaticamente dalla routine ed e' il topaz font.
; 
;
;--------------------------------------------------------------------------
;
; 
; Move:		offset di libreria: -240
; 
; Uso:	Move ( rp , x , y )
; 	       a1   d0  d1
;
; Dove:  rp e' il puntatore alla struttura rastport
;        x  e'  il  valore  dell'  ascissa  relativa  all' angolo superiore
;          sinistro
;        y  e'  il  valore  dell'  ordinata  relativa all' angolo superiore
;           sinistro
; 
; Scopo: Muove la penna grafica nella posizione indicata da (x,y).
;        Il  valore  (0,0)  e'  quello  dell' angolo in alto a sinistra, il
;        valore  (640,200) (o (320,200) ) e' quello relativo all' angolo in
;        basso a destra dello schermo.
;
;-------------------------------------------------------------------------
; 
;
; Draw:		offset di libreria: -246
; 
; Uso:	Draw ( rp , x , y )
;	       a1   d0  d1
; 
; Dove:  rp e' il puntatore alla struttura rastport
;        x e' il valore dell' ascissa relativa alla fine della linea
;        y e' il valore dell' ordinata relativa alla fine della linea
; 
; Scopo: Disegna  una  linea dalla posizione attuale (data dalla funzione
;        move) fino alle coordinate indicate da x,y
; 
;-------------------------------------------------------------------------
;
;
; SetRast:	offset di libreria: -234
; 
; Uso:	SetRast	( rp , pen )
; 		  a1    d0
; 
; Dove:   rp e' il puntatore alla struttura rastport
;	  pen e' il valore della penna (da 0 a 255 ) da porre 			nella bitmap
; 
; Scopo:  Setta  il  contenuto  della  rastport  con il valore della penna
;         specificato  da  "pen".   Un  valore  di 0, ad esempio, cancella
;         tutta la rastport.
; 
;-------------------------------------------------------------------------
;
; WritePixel:	offset di libreria: -324
; 
; Uso:	error = WritePixel ( rp , x , y )
;	  d0	  	      a1  d0  d1
;
; Dove:   rp e' il puntatore alla struttura rastport
;	x  e' la coordinata x del punto
; 	y  e' la corrdinata y del punto
; 	error vale  0 se il punto e' stato disegnato
; 	      vale -1 se il punto e' fuori delle dimensioni 				 della rastport 
;
; Scopo:  Disegnare un punto nella rastport corrente alle coordinate (x,y)
; 
;-------------------------------------------------------------------------
; 
; DrawEllipse:	offset di libreria: -180						Uso:	DrawEllipse ( rp, cx, cy, a , b )
; 		         a1  d0  d1  d2  d3
; Dove:  rp e' il puntatore alla struttura rastport
;  	 cx e' l' ascissa del centro dell' ellisse (o 				circonferenza)
; 	 cy e' l' ordinata del centro dell' ellisse (o				circonferenza)
;	 a  e' il raggio orizzontale ( maggiore di zero ) dell' ellisse
;	 b  e' il raggio verticale ( maggiore di zero ) dell' ellisse
;
; Scopo:  Disegnare una ellisse oppure una circonferenza.
; L' ellisse avra' centro ( = distanza focale /2) di coordinate (cx,cy) e
; raggi a,b (per una circonferenza e' a=b).
; 
;**************************************************************************
;
;                            SUBROUTINE LINE
;
; Bisogna mettere in x1 e y1 le coordinate di partenza della linea, in x2 e
; y2 le coordinate finali della linea.
; 

line:	movem.l d0-d7/a0-a6,-(a7)
 	move.w	x1,d0
 	move.w	y1,d1
	move.l	#rastport,a1
	move.l	gfxbase,a6
	jsr	move(a6)
	move.w	x2,d0
	move.w	y2,d1
	move.l	#rastport,a1
	move.l	gfxbase,a6
	jsr	draw(a6)
	movem.l (a7)+,d0-d7/a0-a6
	rts
;
;**************************************************************************
;
;                            SUBROUTINE CLS
;
; Cancella  la  zona  di  lavoro  usando la funzione setrast della libreria
; grafica NON necessita di parametri.

cls:	movem.l d0-d7/a0-a6,-(a7)
	move.l	#rastport,a1
	move.l	gfxbase,a6
	move.b	#0,d0
	jsr	setrast(a6)			
	movem.l (a7)+,d0-d7/a0-a6
	rts
;
;**************************************************************************
;
;                            SUBROUTINE PLOT
;
; Disegna un punto sulla finestra grafica.
; PARAMETRI: in x1 e y1 bisogna porre le coordinate del punto.
;

plot:	movem.l d0-d7/a0-a6,-(a7)
	move.l	#rastport,a1
	move.l	gfxbase,a6
	move.w	x1,d0
	move.w	y1,d1
	jsr	writepixel(a6)		
	movem.l (a7)+,d0-d7/a0-a6
	rts
;
;**************************************************************************
;
;                             SUBROUTINE RECT
;
; Disegna un rettangolo sulla finestra grafica
; PARAMETRI:  in x1 ed y1 si pongono le coordinate dell' angolo in alto a
;             sinistra  del  rettangolo,  in x2 ed y2 le coordinate dell'
;             angolo in basso a destra.
;

rect:	movem.l d0-d7/a0-a6,-(a7)
	move.w	y2,-(a7)
	move.w	y1,y2
	jsr	line
	move.w	(a7)+,y2
	move.w	x1,-(a7)
	move.w	x2,x1
	jsr	line
	move.w	(a7)+,x1
	move.w	y1,-(a7)
	move.w	y2,y1
	jsr	line
	move.w	(a7)+,y1
	move.w	x1,x2
	jsr	line	
	movem.l (a7)+,d0-d7/a0-a6
	rts
;
;**************************************************************************
;
;                            SUBROUTINE  CIRCLE  
;
; Disegna una circonferenza od ellisse usando la funzione drawellipse.
; PARAMETRI:  In x1 ed y1 le coordinate del centro dell' asse focale, in rx
;             ed ry le lunghezze dei raggi (assi) sugli assi x ed y
;

circle:	movem.l d0-d7/a0-a6,-(a7)
	move.l	#rastport,a1
	move.l	gfxbase,a6
	move.w	x1,d0
	move.w	y1,d1
	move.w	rx,d2
	move.w	ry,d3
	jsr	drawellipse(a6)
	movem.l (a7)+,d0-d7/a0-a6
	rts

;
;**************************************************************************
;
;                            SUBROUTINE PRINT
;
; Scrive sul video una stringa.
; PARAMETRI: in  a0  va  posto l' indirizzo  della   linea  comando.
;            Tale linea comando consta di  due words  all' inizio le
;	     quali specificano le coordinate della stringa sul video
;	     Subito dopo va posta la stringa stessa che DEVE termina-
;	     re con uno zero. Esempio: se vogliamo scrivere "ciao"
;	     a partire dalle coordinate video (20,20) dovremo scrivere
;
;       move.l	#string,a0	;locazione della linea comando
;	jsr	print	     	;esegui la routine print
;	....
;	string: dc.w 20,20	;prima parte del comando: coordinate
;		dc.b 'ciao',0	;seconda parte "   "  " : stringa
;		even		;mettiamolo per evitare errori da
;				;parte dell' assemblatore...	
;

print:  movem.l d0-d7/a0-a6,-(a7)
	move.w	(a0)+,d0
	move.w	(a0)+,d1
	move.l	#rastport,a1
	move.l	gfxbase,a6		
	jsr	move(a6)
	move.l	a0,a1
	moveq	#-1,d0
	moveq	#0,d1
pr1:	addi.w	#1,d0
	cmpi.b	(a1)+,d1
	bne	pr1
	move.l	#rastport,a1
	move.l	gfxbase,a6
	jsr	text(a6)	
	movem.l (a7)+,d0-d7/a0-a6
	rts

;
;                 **** VARIABILI USATE DAL PROGRAMMA ****
;

x1:	dc.w	0			;variabili usate dal programma...
x2:	dc.w	0
y1:	dc.w	0
y2:	dc.w	0
rx:	dc.w	0
ry:	dc.w	0

Gfxname: dc.b 'graphics.library',0	;nome della libreria grafica
	 even
Testo1:	 dc.w	260,42
	 dc.b	"AMIGABYTE",0
	 even
Testo2:	 dc.w	40,220
	 dc.b	"Premi il tasto sinistro del mouse...",0
	 even

gfxbase: dc.l 0				;base della libreria grafica
OldCopl: dc.l 0				;indirizzo della vecchia copperlist
NewCopList:
	 dc.l 0				;indirizzo della nostra copperlist
					;nella chip-ram


;
;                            * LA COPPERLIST *
;
CopList:			
	dc.w 	$0100,%1001000000000000	; BPLCON0 = 1 bitplane
	dc.w	$0102,$0000		; BPLCON1 = 0 (per ora non interessa)
	dc.w	$0104,$0000		; BPLCON2 = 0 ( "   "   "    "   "  )
	dc.w	$0108,$0000	; BPL1MOD = modulo planes dispari 0
	dc.w	$010a,$0000	; BPL2MOD = modulo planes pari 0
	dc.w	$008E,$2C41	; DIWSTRT = $2c41 \valori scelti per centrare            
	dc.w	$0090,$10D1	; DIWSTOP = $10d1 /l' immagine....
	dc.w 	$0092,$003c	; DDFSTRT = $003c
	dc.w	$0094,$00d4	; DDFSTOP = $00d4
 	dc.w 	$00e0		; BPL1PTH = punta alla parte alta della		
hi:	dc.w	$7		; 	    zona di memoria ottenuta da
				;	    AllocMem (vedi listato)
	dc.w	$00E2		; BPL1PTL = punta alla parte bassa della
lo:	dc.w	$8000		;	    zona di memoria ottenuta da
				;	    AllocMem (vedi listato)
	dc.w	$0180,$0000	; COLOR00 = background nero
	dc.w	$0182,$0fff	; COLOR01 = tratto di disegno bianco
	dc.w 	$FFFF,$FFFE	; fine della copperlist
EndList:				

RastPort:
	rp_Layer: 	blk.l	1	; ^  Layer
	rp_BitMap: 	blk.l	1	; ^  BITMAP
	rp_AreaPtrn: 	blk.l	1	; ^  al pattern riempimento di aree
	rp_TmpRas: 	blk.l	1	; ^  ad uno spazio temporaneo
	rp_AreaInfo:	blk.l	1	;informazioni per il riempimento aree
	rp_GelsInfo: 	blk.l	1	;Graphics Elements (animazione)
	rp_Mask: 	blk.b	1	;mascheramento bit grafici
	rp_FgPen: 	blk.b	1	; # penna di primo piano
	rp_BgPen: 	blk.b	1	; # penna di sfondo
	rp_AOLPen: 	blk.b	1	; # penna riempimento contorni
	rp_DrawMode: 	blk.b	1	;modalita' di disegno
	rp_AreaPtSz: 	blk.b	1	;dimensione pattern riempimento aree
	rp_Dummy: 	blk.b	1	
	rp_linpatcnt: 	blk.b	1	; # byte utilizzati per i patterns
	rp_Flags: 	blk.w	1	;flags per la RastPort
	rp_LinePtrn: 	blk.w	1	; ^  pattern della linea
	rp_cp_x: 	blk.w	1	;attuale posizione X della penna
	rp_cp_y: 	blk.w	1	;attuale posizione Y della penna
	rp_minterm: 	blk.b	8	;speciale manipolazione bitplanes
	rp_PenWidth: 	blk.w	1	;larghezza della penna usata
	rp_PenHeight: 	blk.w	1
	rp_Font: 	blk.l	1	;attuale font impiegato
	rp_AlgoStyle: 	blk.b	1	;Algorithmic Style (italic,bold...)
	rp_TxFlags: 	blk.b	1	;flags di testo
	rp_TxHeight: 	blk.w	1	;altezza testo
	rp_TxWidth: 	blk.w	1	;ampiezza testo
	rp_TxBaseline:	blk.w	1	;definizione della linea base di testo
	rp_TxSpacing:	blk.w	1	;speciale spaziatura testo
	rp_RP_User:	blk.l	1	;attuale user RastPort
	rp_longreserved:blk.b	8	;\
	rp_wordreserved:blk.b	14	; | Usati dal sistema
	rp_reserved:	blk.b	8	;/

BitMap:
	bm_BytesPerRow:	blk.w	1
	bm_Rows:	blk.w	1
	bm_Flags:	blk.b	1
	bm_Depth:	blk.b	1
	bm_Pad:		blk.w	1
	bm_Planes:	blk.b	8*4

; That's all, folks !
; (c) 1991 AmigaByte
