* GPU-Mandelbrot
* 2. Versuch
* (weniger Hack, Adressen via TSM-Datei an 68K-Programm)
* erstellt : 6.12.94 (B.Schick)
* Datum	nderung
*----------------------------------
* 6.12.94	JSR eingebaut
*	ClearCross/DrawCross/getjoy eingebaut
*	MoveCross
* 18.12.94	DrawHorCross/DrawVerCross/Compute eingebaut


	path "e:\js\"

GPU	EQU 1

delay	equ 600

	include "macro\help.mac"
	include "macro\joypad1.mac"
**********************
* REGister-Definitionen
**********************
* GLOBAL
max_xy	reg 26
max_iter	reg 25
screen_ptr	reg 24
i_max	reg 23
r_min	reg 22
delta	reg 21

* alternative Register
CrossScreen.a	reg 20
CrossX.a	reg 19
CrossY.a	reg 18
CrossX1.a	reg 17
CrossY1.a	reg 16
Screen.a	reg 15
***********************
* LOKAL

*********************
* Konstanten
*********************
genau	equ 13
;ColorTab	EQU $F04000-1024-32      ; Platz fr Stack
screen            EQU $100000
TxtScreen         EQU $100000+224*224*2
CrossScreen       EQU TxtScreen+32*32

*********************
* Parameter (werden vom 68K-Prg. gefllt)
*********************
	ORG $f03000	; am Anfang
_delta::	ds.l 1	; GLOBAL => TSM-Datei
_r_min::	ds.l 1
_i_max::	ds.l 1
_max_iter::	ds.l 1
_max_xy::	ds.l 1
_screen_ptr::	ds.l 1
_ColorTab::	ds.l 1
LastJoy	ds.l 2
	RUN	; Gleich nach den Para. mit dem Prg. starten
*****************
** Werte holen **
*****************
StartMandel::	movei $f0211c,r0
	moveq 0,r1
	store r1,(r0)	; DIV_OFFSET => 32Bit unsigned

	movei _delta,r14
	load (r14),delta
	load (r14+4),r_min
	load (r14+8),i_max
	load (r14+12),max_iter
	load (r14+16),max_xy
	load (r14+20),screen_ptr
	moveta screen_ptr,Screen.a
********************
** Variablen Init **
********************
	movei SP_start,SP
	movei CrossScreen,r0
	moveta r0,CrossScreen.a

.main	movei ClearCross,r0
	JSR (r0)

	xor r1,r1
	movei $f10002,r0
	storew r1,(r0)
	movei Mandel,r0
	JSR (r0)
*
* ab hier beginnt die Umsetzung auf Voll-GPU
*
.again	movei ClearCross,r0
	JSR (r0)
	move max_xy,r0
	shrq #1,r0
	moveta r0,CrossX.a
	moveta r0,CrossY.a
	movei DrawCross,r0
	JSR (r0)

	movei MoveCross,r0
	JSR (r0)
	movefa CrossX.a,r0
	moveta r0,CrossX1.a
	addq #1,r0
	moveta r0,CrossX.a
	movefa CrossY.a,r0
	moveta r0,CrossY1.a
	addq #1,r0
	moveta r0,CrossY.a
	movei DrawCross,r0
	JSR (r0)
	movei GrowCross,r0
	JSR (r0)
	subq #1,r0
	movei .again,r0
	jump z,(r0)
	nop
	movei ComputeNew,r0
	JSR (r0)
	movei getjoy,r0
	JSR (r0)
	btst #28,r0
	jr nz,.exit
	nop
	movei .main,r0
	jump (r0)
	nop
.exit	STOP_GPU
*****************
* Mandelbrot
*****************
* lokale Register def.

XLOOP	reg 18
YLOOP	reg 17
ITER_LOOP	reg 16
ITER_ENDE	reg 15
ColorTab	reg 14
abbruch	reg 13
ModuloMaske	reg 12
iter_count	reg 11
ColorPtr	reg 10
hilfe1	reg  9
hilfe2	reg  8
x_count	reg  7
y_count	reg  6
_r1	reg  5
_i1	reg  4
_i0	reg  3
_r0	reg  2
_i	reg  1
_r	reg  0

Mandel::	movei 1023,ModuloMaske
	movei iter_ende,ITER_ENDE
	movei xloop,XLOOP
	movei yloop,YLOOP
	movei iter_loop,ITER_LOOP
	movei _ColorTab,ColorTab
	movei 4<<(genau*2),abbruch
	load (ColorTab),ColorTab
	movefa Screen.a,screen_ptr
*******************
** Hauptschleife **
*******************
	move i_max,_i0
	move max_xy,y_count
	move r_min,_r0
yloop	move max_xy,x_count
xloop	move max_iter,iter_count	; max_iter
	moveq #0,ColorPtr
	move _r0,_r	; r=r0
	move _i0,_i	; i=i0
	move _r,_r1
	move _i,_i1
iter_loop	imult _r1,_r1	; r^2
	imult _i1,_i1	; i^2

	move _r1,hilfe1
	move _r1,hilfe2
	add _i1,hilfe1	; r^2+i^2
	sub _i1,hilfe2	; r^2-i^2
	cmp abbruch,hilfe1
	addqt #1,ColorPtr
	jump nn,(ITER_ENDE)

	imult _r,_i
	sharq genau,hilfe2 ; normalisieren
	sharq genau-1,_i

	add _r0,hilfe2	; r16=r^2-i^2+r0
	add _i0,_i	; i=2*i*r+i0

	move hilfe2,_r
	subq 1,iter_count
	move _i,_i1
	jump nz,(ITER_LOOP)
	move hilfe2,_r1
	moveq #0,ColorPtr
	jr .cont
iter_ende	and ModuloMaske,ColorPtr
	addq 1,ColorPtr
.cont	add delta,_r0
	load (ColorTab+ColorPtr),ColorPtr
	subq #1,x_count
	storew ColorPtr,(screen_ptr)
	jump nz,(XLOOP)
	addq 2,screen_ptr

	subq 1,y_count
	move r_min,_r0		; r0=r_min
	jump nz,(YLOOP)
	sub delta,_i0	; i0 += delta
	RTS

	unreg XLOOP,YLOOP,ITER_LOOP,ITER_ENDE,ColorTab
	unreg abbruch,ModuloMaske,iter_count,ColorPtr
	unreg hilfe1,hilfe2,x_count,y_count
	unreg _r,_i,_r0,_i0,_r1,_i1

******************
** JoyPad holen **
******************
* IN : /
* OUT : r0
* zerstrte Regsister : r1..4
******************
getjoy	JOYPAD1
	RTS
*******************
** Kreuz lschen **
*******************
* IN  : CrossScreen.a
* OUT : /
* zerstrte Register : r0..r2/$f02118
*******************
ClearCross::	moveq #0,r0
	movei $f02118,r1
	movefa CrossScreen.a,r2
	store r0,(r1)
	move max_xy,r1
	mult r1,r1
	storep r0,(r2)
.loop	subq #8,r1
	addqt #8,r2
	jr nz,.loop
	storep r0,(r2)
	RTS
********************
** Kreuz zeichnen **
********************
* IN  : CrossX.a,CrossY.a,CrossScreen.a
* OUT : /
* zersrte Register : r0..r3
********************
DrawCross::	movefa CrossScreen.a,r3	; Adresse holen
	movefa CrossX.a,r0	; x holen
	add r0,r3
	move max_xy,r1
	moveq #2,r0
.loop0	loadb (r3),r2
	xor r0,r2
	subq #1,r1
	storeb r2,(r3)
	jr nz,.loop0
	add max_xy,r3

DrawHorCross::	movefa CrossY.a,r2	; y holen
	movefa CrossScreen.a,r3	; Adresse holen
	mult max_xy,r2
	move max_xy,r1
	add r2,r3
	moveq #2,r0
.loop1	loadb (r3),r2
	xor r0,r2
	subq #1,r1
	storeb r2,(r3)
	jr nz,.loop1
	addqt #1,r3
	RTS

DrawVerCross::	movefa CrossScreen.a,r3	; Adresse holen
	movefa CrossX.a,r0	; x holen
	add r0,r3
	move max_xy,r1
	moveq #2,r0
.loop0	loadb (r3),r2
	xor r0,r2
	subq #1,r1
	storeb r2,(r3)
	jr nz,.loop0
	add max_xy,r3
	RTS
*******************
** Kreuz bewegen **
*******************
* IN  : /
* OUT : neue CrossX.a/CrossY.a
* zerstrte Register : r0..r11
*******************
GETJOY	REG 6
DRAWCROSS	REG 7
LOOP	REG 8
DRAWHOR	REG 9
DRAWVER	reg 10

MoveCross::	movei getjoy,GETJOY	; JoyPad-Routine
.wait	JSR (GETJOY)
	cmpq #0,r0
	jr nz,.wait
	nop
	movei DrawHorCross,DRAWHOR
	movei DrawVerCross,DRAWVER
	movei .loop,LOOP
.loop	movei #delay,r11	; warten
.loop1	JSR (GETJOY)		; JoyPad lesen
	cmpq #0,r0
	jr z,.loop1
	subq #1,r11
	jr nn,.loop1
	btst #29,r0		; "A" ?
	jr z,.cont
	RTS
.cont	movefa CrossX.a,r4
	movefa CrossY.a,r5
	shrq #20,r0		; Cursor nach 0..3
	jump z,(LOOP)
	shrq #1,r0
	jr c,.up
	shrq #1,r0
	jr c,.down
	shrq #1,r0
	jr c,.left
	shrq #1,r0
	jump nc,(LOOP)
	nop
.right	jr .cont1
	addq #1,r4
.up	jr .cont2
	subq #1,r5
.down	jr .cont2
	addq #1,r5
.left	subq #1,r4
.cont1	cmp r4,max_xy
	jr z,.cont3
	cmpq #0,r4
	jr n,.cont3
	move DRAWVER,DRAWCROSS
	jr .cont4
.cont2	cmp r5,max_xy
	jr z,.cont3
	cmpq #0,r5
	jr nn,.cont4
	move DRAWHOR,DRAWCROSS
.cont3	jump (LOOP)
	nop
.cont4	JSR (DRAWCROSS)		; altes Kreuz lschen
	moveta r4,CrossX.a
	moveta r5,CrossY.a
	JSR (DRAWCROSS)		; neues Kreuz zeichnen
	jump (LOOP)
	nop

	UNREG GETJOY,LOOP,DRAWCROSS,DRAWHOR,DRAWVER
**********************
** Rahmen aufziehen **
**********************
* IN : CrossX.a,CrossY.a
* OUT: r0=0 => "A"
*      r0=1 => "B"
* zerstrte Register : 0..9
*
GETJOY	REG 6
DRAWCROSS	REG 7
LOOP	REG 8
COUNTER	REG 9

GrowCross::	movei getjoy,GETJOY	; JoyPad-Routine
.wait	JSR (GETJOY)
	cmpq #0,r0
	jr nz,.wait
	nop
	movei DrawCross,DRAWCROSS
	movei .loop,LOOP
.loop	movei #delay,COUNTER	; warten
.loop1	JSR (GETJOY)		; JoyPad lesen
	cmpq #0,r0
	jr z,.loop1
	subq #1,COUNTER
	jr nn,.loop1
	move r0,r1
	btst #29,r1		; "A" ?
	jr z,.cont
	moveq #0,r0		; Ende mit A
.exit	RTS
.cont	btst #25,r1		; "B" ?
	jr nz,.exit
	moveq #1,r0		; Ende mit B
	movefa CrossX.a,r4
	movefa CrossY.a,r5
	shrq #20,r1		; Cursor nach 0..3
	jump z,(LOOP)
	shrq #1,r1
	jr c,.smaller		; ^
	shrq #1,r1
	jr c,.bigger		; \/
	shrq #1,r1
	jr c,.smaller		; <-
	shrq #1,r1
	jump nc,(LOOP)		; nicht ->
.bigger	addq #1,r4
	jr .cont1
	addq #1,r5
.smaller	subq #1,r4
	jump n,(LOOP)
	subq #1,r5
	jump n,(LOOP)
.cont1	cmp max_xy,r4
	jump z,(LOOP)
	cmp max_xy,r5
	jump z,(LOOP)
	nop
	JSR (DRAWCROSS)
	moveta r4,CrossX.a
	moveta r5,CrossY.a
	JSR (DRAWCROSS)
	jump (LOOP)
	nop

	UNREG DRAWCROSS,GETJOY,LOOP,COUNTER
*****************************
** neue Eckwerte berechnen **
*****************************
* IN  : CrossX.a,CrossY.a,CrossX1.a,CrossY1.a
* OUT :
ComputeNew::	movefa CrossX1.a,r0
	movefa CrossX.a,r1
	movefa CrossY1.a,r2
	sub r0,r1
	jr nn,.ok
	abs r1
	movefa CrossX.a,r0
	movefa CrossY.a,r2
.ok	imult delta,r0		; neues r_min
	imult delta,r2
	add r0,r_min
	sub r2,i_max
	imult r1,delta
	div max_xy,delta	; neues Delta
	jr z,.ok2	; delta = 0 =>
	RTS
.ok2	moveq #1,delta
	RTS

