
********************************************
*				           *
*  Lame generic gouraud routine	           *
*  Not optimized at all - Just for sample  *
*  (C)oderight 1995 by Jedi/Sector One     *
*					   *
********************************************

!faraway	set 900

	org $100

; flat real mode

	d+
	move cs,a
	move a,ds
	move a,es
	add #@stack,a
	move a,ss
	bsr initFRM

; 320x200 / 256

	move #$13,a
	trap #$10

;	bsr xmode

; cls

	move #$a000,a
	move a,es
	xor a,a
	xor di,di
	move #320*200/2-1,c
	rep:stos

	push ds
	push es

	xor di,di
	move cs,a
	add #@bkg,a
	move a,es
	move #100,d
	move #160,bp
.loop2	move bp,c
	xor.b a,a
	rep:stos.b
	move.b #128,a
	move bp,c
	rep:stos.b
	dec d
	bne.s .loop2
	move #100,d
.loop2	move bp,c
	move.b #128,a
	rep:stos.b
	xor.b a,a
	move bp,c
	rep:stos.b
	dec d
	bne.s .loop2

	pop es
	pop ds

; that's the way I like it

	move cs,a
	move a,ds
	move a,es

; Clear the virtual screen

	move.l #pchouk,be
	move #[pchoukf-pchouk]/4,c
	xor.l ae,ae
.loop	move.l ae,(be)
	add.l #4,be
	dbf .loop

; Add the bottom border

	move.l #pchouk+320*200,be
	move #320,c
	move.b #-1,a
.loop	move.b a,(be)
	inc.l be
	dbf .loop

; Generate a fade table

	move.l #fadetable+5,be
	move #251,c
	xor.b a,a
	move.b a,-1(be)
	move.b a,-2(be)
	move.b a,-3(be)
	move.b a,-4(be)
	move.b a,-5(be)
.loop	move.b a,(be)
	inc.b a
	inc.l be
	dbf .loop

; Some great colors

	move #$3c8,d
	xor.b a,a
	out.b a,d
	inc d
	move.b #8,b
	move #64,c
	move c,bp
	sub #8,c
.loop	xor.b a,a
	out.b a,d
	out.b a,d
	move.b b,a
	out.b a,d
	inc.b b
	dbf .loop
	move bp,c
	xor.b b,b
.loop	xor.b a,a
	out.b a,d
	move.b b,a
	out.b a,d
	inc.b b
	move.b #63,a
	out.b a,d
	dbf .loop
	move #8,c
	xor.b a,a
.loop	move.b b,a
	out.b a,d
	move.b #63,a
	out.b a,d
	out.b a,d
	add.b #4,b
	dbf .loop

	move bp,c
	sub #8,c
	move.b #8,b
.loop	move.b b,a
	out.b a,d
	xor.b a,a
	out.b a,d
	move.b b,a
	out.b a,d
	inc.b b
	dbf .loop
	move bp,c
	xor.b b,b
.loop	move.b #63,a
	out.b a,d
	move.b b,a
	out.b a,d
	inc.b b
	move.b #63,a
	out.b a,d
	dbf .loop
	move #8,c
.loop	move.b #63,a
	out.b a,d
	out.b a,d
	out.b a,d
	dbf .loop


; Initialize the 320* table

	move.l #multable,be
	move #240,c
	xor a,a
.loop	move a,(be)
	add #320,a
	add.l #2,be
	dbf .loop

; Self-generate the vertical display routine

	move.l #realdraw,be
	move #240,c
	xor a,a
.loop
;	move #$a788,(be)	; move.b ah, ...
;	move #$a700,(be)	; add.b ah, ...
	move #$a708,(be)	; or.b ah, ...
;	move #$a710,(be)	; addx.b ah, ...
;	move #$a720,(be)	; and.b ah, ...
;	move #$a730,(be)	; xor.b ah, ...

	move a,2(be)		; offset(b)
	move #$c503,4(be)	; add bp,a
	add.l #6,be
	add #320,a
	dbf .loop

; test polygon

	intoff

zeloop
;	bsr fade
	bsr cpybck

happy1	move.l #0.l,ae
happy2	move.l #10.l,be
happy3	move.l #30.l,ce

	bsr initrotation

	inc happy1+2
	and #511,happy1+2
	inc happy2+2
	and #511,happy2+2
	add #3,happy3+2
	and #511,happy3+2

; Process objects

	move.l #object,sie
pipi	move.l #points+2,die
	move (sie),bp
	test bp,bp
	beq foune
	move bp,-2(die)
	add.l #2,sie
.loop	move #160,rotatedx
	move #100,rotatedy
	move.l #sintable,be
	xor.l ae,ae
	move 6(sie),a
	add #2,a
	and #511,a
	move a,6(sie)
	move.l (be,ae*4),ae
	asr.l #12-6,ae
	add #64,a
	move a,4(die)
	movesx.l (sie),be
	movesx.l 2(sie),ce
	movesx.l 4(sie),de
	push bp
	push.l sie
	move.l #!faraway,sie
	bsr rotate
	pop.l sie
	pop bp
	move rotatedx,a
	move a,(die)
	move rotatedy,a
	move a,2(die)
	add.l #8,sie
	add.l #6,die
	dec bp
	bne.s .loop
	move.l #points,be
	bsr poly
	bra pipi
foune

; Draw

;	move #$3c8,d
;	xor.b a,a
;	out.b a,d
;	inc d
;	out.b a,d
;	out.b a,d
;	move.b #$31,a
;	out.b a,d

;	bsr vsync
	bsr cpyscrn

;	move #$3c8,d
;	xor.b a,a
;	out.b a,d
;	inc d
;	out.b a,d
;	out.b a,d
;	out.b a,d

* Press [Escape] to logout !

        in.b #$60,a
        cmp.b #129,a
        bne zeloop

	bsr txtmode

	inton
	move #$4c00,a
	trap #$21

; kassos

	rts

; be : points addresses

poly	pusha.l
	xor.l ae,ae
	move (be),a		; a : first element of the list
	add.l #2,be
	move.l be,!fone1
	move.l be,!lone2

	add a,a
	move a,bp
	add bp,bp
	add bp,a		; *6 -> a : enda the list
	add.l be,ae
	sub.l #6,ae
	move.l ae,!lone1
	move.l ae,!fone2

	move -2(be),c

	move (be),bp		; xmin = first
	move.l be,sie		; addrmin = first addr
sort	move (be),a		; x
	cmp bp,a
	bge.s poaplupti		; zob
	move a,bp		; new xmin
	move.l be,sie		; new addy
poaplupti
	add.l #6,be
	dbf sort		; end of the sort loop. si = lefter item

	move.l sie,leftitem

; Compute the first upper item

	move.l sie,bpe
	bsr getnextitem
	move.l sie,upitem

; Compute the first lower item

	move.l bpe,sie
	bsr getpreviousitem
	move.l sie,downitem

; Compute the left addy

	move.l leftitem,de
	xor.l be,be
	move 2(de),b
	xor.l ae,ae
	move (de),a
;	add.l #$a0000,ae
	move.l ae,leftaddr

; Compute and store the upper slope

	move.l leftitem,sie
	move.l upitem,die
	bsr getslope
	move bp,upperslope
	move a,uppershadeslope

; Compute and store the lower slope

	move.l leftitem,sie
	move.l downitem,die
	bsr getslope
	move bp,lowerslope
	move a,lowershadeslope

; Init uppery and lowery

	move.l leftitem,sie
	move 2(sie),a
	asl #8,a
	move a,uppery
	move a,lowery

; Init uppershade and lowershade

	move 4(sie),a
	asl #8,a
	move a,uppershade
	move a,lowershade

; Get the horizontally shorter item

	move #0,alreadydone

snacker
	move.l upitem,ae
	move (ae),d
	move.l downitem,ae
	move (ae),b
	move d,c		; up first by default
	move.b #0,dsk
	cmp b,d
	ble.s upfirst
	move b,c
	move.b #1,dsk
upfirst	move.l leftitem,ae
	sub (ae),c		; c = width of the current segment
	move.l #alreadydone,be
	sub (be),c
	add c,(be)

; Draw the bizness

	xor a,a
	move a,gs

	test c,c
	ble.s breakit

.loop	move.l #multable,sie
	move.l curaddr,be
	move uppery,a
	xor.l de,de
	move.b ah,d
	move d,staxy
	move (sie,de*2),d
	add.l de,be
	move.l be,segmentup

	move.l curaddr,be
	move lowery,a
	xor.l de,de
	move.b ah,d
	move d,staxy2
	move (sie,de*2),d
	add.l de,be
	move.l be,segmentdown

	bsr drawsegment
	inc.l curaddr

breakit	move upperslope,a
	add a,uppery
	move lowerslope,a
	add a,lowery
	move uppershadeslope,a
	add a,uppershade
	move lowershadeslope,a
	add a,lowershade
	dec c
	bgt .loop

; If both segments converged to the same point, then the polygon is completed

	move.l upitem,a
	cmp.l downitem,a
	beq yoopikassos

; Next point

	move.b dsk,a
	test.b a,a		; 0 = up
	bne downstairs

; Snap the upper part

	move.l upitem,sie
	push.l sie
	bsr getnextitem
	move.l sie,upitem
	move.l sie,ae

	pop.l sie
	move.l ae,die
	bsr getslope
	move bp,upperslope
	move a,uppershadeslope

	bra snacker

downstairs

	move.l downitem,sie
	push.l sie
	bsr getpreviousitem
	move.l sie,downitem
	move.l sie,ae

	pop.l sie
	move.l ae,die
	bsr getslope
	move bp,lowerslope
	move a,lowershadeslope

	bra snacker

yoopikassos
	popa.l
	rts

; Draw a gouraud segment

drawsegment

	pusha.l

	xor.l ce,ce
	move staxy2,c
	sub staxy,c
	ble.s topdelire
xtazy
	move.l segmentup,be

	move.l ce,bpe
	move lowershade,a
	sub uppershade,a
	beq.s pipe
	ext.l
	ext.q
	idiv.l bpe
pipe
	move a,bp
	move uppershade,a

	add c,c
	move c,d
	add c,c
	add d,c			; *6
	move.l #realdraw+4,sie
	add.l ce,sie
	move.b (sie),c
	move.b #$c3,(sie)	; Move the 'rts'
	push ds
	move cs,d
	add #@pchouk,d
;	move #$a000,d
	move d,ds
	bsr realdraw
	pop ds

	move.b c,(sie)

topdelire
	popa.l
	rts

; Various datas

	align.l
leftitem
	dc.l 0
upitem	dc.l 0
downitem
	dc.l 0
curaddr
leftaddr
	dc.l 0
segmentup
	dc.l 0
segmentdown
	dc.l 0
upperslope
	dc.w 0
lowerslope
	dc.w 0
uppery	dc.w 0
lowery	dc.w 0
dsk	dc.w 0
alreadydone
	dc.w 0
staxy	dc.w 0
staxy2	dc.w 0
uppershadeslope
	dc.w 0
lowershadeslope
	dc.w 0
uppershade
	dc.w 0
lowershade
	dc.w 0

; Get the left xtrem of a segment in (sie), the right one in (die),
; computes the slope and returns it in bp
; The shading step is also computed and returns in ae

getslope
	move 2(die),a
	sub 2(sie),a
	ext.l
	ext.q
	asl.l #8,ae
	xor.l be,be
	move (die),b
	sub (sie),b
	beq.s exitslp
	idiv.l be		; ae# = (y2#-y1#)/(x2#-x1#)
exitslp
	move a,bp
onslp

; Compute the shading

	move 4(die),a
	sub 4(sie),a
	ext.l
	ext.q
	asl.l #8,ae
	xor.l be,be
	move (die),b
	sub (sie),b
	beq.s exitslp2
	idiv.l be		; ae# = (s2#-s1#)/(x2#-x1#)

exitslp2
	rts

; Takes sie, find the previous item and put it anew to sie

getpreviousitem

.tmp	cmp.l #'ideJ',sie	; first one ?
!fone1	set .tmp+3
	bne.s nomod1
.tmp	move.l #'ideJ',sie	; -> last one
!lone1	set .tmp+2
	bra.s endmod1
nomod1	sub.l #6,sie		; previous one
endmod1
	rts

; Take sie, find the next item and put it anew to sie

getnextitem

.tmp	cmp.l #'ideJ',sie	; last one ?
!fone2	set .tmp+3
	bne.s nomod2
.tmp	move.l #'ideJ',sie	; -> first one
!lone2	set .tmp+2
	bra.s endmod2
nomod2	add.l #6,sie		; next one
endmod2
	rts

	include frm.si

; Sample objects. Format is :
; - number of points
; - x, y, lightshade
; .points are ignored

object
	dc.w 4
	dc.w -64,64,-64,0+16
	dc.w -64,-64,-64,90+16
	dc.w 64,-64,-64,180+16
	dc.w 64,64,-64,270+16

	dc.w 4
	dc.w -64,64,64,71+16
	dc.w -64,-64,64,250+16
	dc.w -64,-64,-64,90+16
	dc.w -64,64,-64,0+16

	dc.w 4
	dc.w 64,64,-64,270+16
	dc.w 64,-64,-64,180+16
	dc.w 64,-64,64,90+16
	dc.w 64,64,64,30+16

	dc.w 4
	dc.w -64,-64,-64,90+16
	dc.w -64,-64,64,250+16
	dc.w 64,-64,64,90+16
	dc.w 64,-64,-64,180+16

	dc.w 4
	dc.w -64,64,64,71+16
	dc.w -64,64,-64,0+16
	dc.w 64,64,-64,270+16
	dc.w 64,64,64,30+16

	dc.w 0

points	dc.w 0
	dc.w 0,0,0
	dc.w 0,0,0
	dc.w 0,0,0
	dc.w 0,0,0

; Sinus tables

	align.l
sintable
	incbin sintable.sct
.costable	set sintable+128*4

	align.l

rots1	dc.l 0
rotc1	dc.l 0
rots2	dc.l 0
rotc2	dc.l 0
rots3	dc.l 0
rotc3	dc.l 0
rotj	dc.l 0
rotk	dc.l 0
rotl	dc.l 0
rotm	dc.l 0
rotd	dc.l 0
rotg	dc.l 0
rote	dc.l 0
roth	dc.l 0
rota	dc.l 0
rotb	dc.l 0

rotatedx
	dc.l 0
rotatedy
	dc.l 0

; 3D Rotations - Initialize the vectorial base
; ae = xrot   be = yrot   ce = zrot

initrotation
	move.l #sintable,sie
	move.l #.costable,die
	move.l (sie,ae*4),de
	move.l de,rots1
	move.l (die,ae*4),de
	move.l de,rotc1
	move.l (sie,be*4),de
	move.l de,rots2
	move.l (die,be*4),de
	move.l de,rotc2
	move.l (sie,ce*4),de
	move.l de,rots3
	move.l (die,ce*4),de
	move.l de,rotc3

	move.l rots3,be
	move.l rotc1,ae
	move.l ae,ce		; c = c1
	imul.l be,ae
	asr.l #12,ae
	move.l ae,rotj

	move.l rots1,ae
	move.l ae,bpe		; bp = s1
	imul.l be,ae
	asr.l #12,ae
	move.l ae,rotk

	move.l rotc3,de
	move.l ce,ae
	imul.l de,ae
	asr.l #12,ae
	move.l ae,rotl

	move.l bpe,ae
	imul.l de,ae
	asr.l #12,ae
	move.l ae,rotm

	move.l rots2,be		; b = s2
	imul.l be,ae		; a = m*s2
	asr.l #12,ae
	sub.l rotj,ae
	move.l ae,rotd

	move.l rotl,ae
	move.l ae,bpe		; bp = l
	imul.l be,ae		; a = l*s2
	asr.l #12,ae
	move.l rotk,ce		; c = k
	add.l ce,ae
	move.l ae,rotg

	move.l ce,ae
	imul.l be,ae
	asr.l #12,ae
	add.l bpe,ae
	move.l ae,rote

	move.l rotj,ae
	imul.l be,ae
	asr.l #12,ae
	sub.l rotm,ae
	move.l ae,roth

	move.l rotc2,be		; b = c2
	move.l rotc3,ae
	imul.l be,ae
	asr.l #12,ae
	move.l ae,rota

	move.l rots3,ae
	imul.l be,ae
	asr.l #12,ae
	move.l ae,rotb

	rts

; According to the previously calculated vectorial base, project
; a 3D couple of points on the 2D screen plane
; be = x   ce = y   de = z   sie = zdep
; Results addad to (rotatedx) and (rotatedy)

rotate
	move.l rota,bpe
	imul.l be,bpe
	move.l rotd,ae
	imul.l ce,ae
	add.l ae,bpe
	move.l rotg,ae
	imul.l de,ae
	add.l ae,bpe
	move.l sie,ae
	imul.l bpe,ae
	asr.l #12+10,ae
	add.l ae,rotatedx

	move.l rotb,bpe
	imul.l be,bpe
	move.l rote,ae
	imul.l ce,ae
	add.l ae,bpe
	move.l roth,ae
	imul.l de,ae
	add.l ae,bpe
	move.l sie,ae
	imul.l bpe,ae
	asr.l #12+10,ae
	add.l ae,rotatedy

	rts

cpybck
	push ds
	push es

	move cs,a
	add #@pchouk,a
	move a,es
	move cs,a
	add #@bkg,a
	move a,ds
	xor si,si
	xor di,di
	move #320*200/4,c
	rep:moves.l

	pop es
	pop ds

	rts

fade
	push ds
	push es

	move cs,a
	add #@pchouk,a
	move a,ds
	xor b,b
	assume pchouk
	move.l #fadetable,sie
	assume START

	move #320*200,c
	xor.l ae,ae
.loop	move.b 320(b),a
	move.b (sie,ae),a
	move.b a,(b)
	inc b
	dec c
	bne.s .loop

	pop es
	pop ds

	rts

cpyscrn
	push ds
	push es

	move #$a000,a
	move a,es
	move cs,a
	add #@pchouk,a
	move a,ds
	xor si,si
	xor di,di
	move #320*200/2,c
	rep:moves.w

	pop es
	pop ds

	rts

	include xymode.si

	section bss

; Self-generated code to draw a vertical shaded line

realdraw
	ds.w 6*240/2		; Generated at the beginning of the code
	rts			; Just for fun and security

multable
	ds.w 240		; 240 in case of a 320x240 resolution

	segment
pchouk	ds.l 320*240/4
pchoukf
	align.l
fadetable
	ds.b 256
	segment
bkg	ds.l 320*240/4
	segment
	ds.l 512
stack
