
outstanding introduced/emulation bugs:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

search for 'XXX' in fe2.s to find comments on known breakage.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

for calling FmtStr:
	d0 = format type described below
	d4 = colour
	d5 = x
	d6 = y
	d7 = 0 ??

d0:
      < 0x3000  string 'd0' in stringtable L3e878, which contains
      		only "hello there" and "how are you" :-)
	0x3015	"%08x" hex (in d3)
	0x3014	"%08x" hex (in d2)
	0x3013	"%08x" hex (in d1)
	0x3012	HH:MM:SS (in d3)
	0x3011	HH:MM:SS (in d2)
	0x3010	HH:MM:SS (in d1)
	0x300f	dd-mon-year (day of year in d3)
	0x300e	dd-mon-year (in d2)
	0x300d	dd-mon-year (in d1)
	0x300c	int32 3 dec places (in d3)
	0x300b	int32 3 dec places (in d2)
	0x300a	int32 3 dec places (in d1)
	0x3009	int32 2 dec places (in d3)
	0x3008	int32 2 dec places (in d2)
	0x3007	int32 2 dec places (in d1)
	0x3006	int32 1 dec place (in d3)
	0x3005	int32 1 dec place (in d2)
	0x3004	int32 1 dec place (in d1)
	0x3003	int32 (in d3)
	0x3002	int32 (in d2)
	0x3001	int32 (in d1)
	0x3000  erm, like, do last thing printed.
	
	0x4xxx  use string xxx from stringtable A6_game_strings(a6)
	0x80xx - 0xa2xx
		use string xxx from stringtable in module given by:
		12 + a6 + (((d0*2) & 0xffff)>>7)
		(The module string table is then obtained by jumping
		to 40(addr), the address calculated above.
		( mod0 = 0x80xx, mod1 = 0x82xx, ... )
	
		hm. that there copy thingy is 0x98d8
		

SFX indices:
~~~~~~~~~~~~~

	0	ui_beep
	1	laser0
	2	laser1
	3	laser2
	4	launch_granted
	5	station_door_open
	6	explode1
	7	??
	8	explode2
	9	explode3
	10	explode4
	11	explode5
	12	explode6
	13	explode7
	14	explode8
	15	explode9
	16	explode10
	17	laser_burn
	18	??
	19	hyperspace (loop)
	20	hyperspace_end
	21	send_message
	22	fire_missile
	23	noise (loop)
	24	ECM
	25	warning!
	26	retract wheels (?)
	27	<silence?>
	28	select object
	29	bing
	30	big bing!
	31	launch_noise
	32	dildo

modfuncs:
~~~~~~~~~
4(a4) - init
20(a4) - every turn in 3d view
40(a4) - get string-table


random crap
~~~~~~~~~~~~~~~

the gamedata things the renderer has pointer to in a5:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
size	offset
WORD	0		offset added to gamedata pointer before passing to Project3DObj
WORD	2		offset to another fucking thing in this gamedata obj (L3e14e)
WORD	4		size of stackframe to allocate in L3e158
WORD	6		offset to yet another fucking thing in data obj
WORD	10		some size shift thingy
WORD	14		some size thingy

from gamedata + 0(gamedata).w (in a5 at Project3DObj):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
size	offset
WORD	0		(word & 0x1f) * 2 = offset to projection func in L3e10e
			Read with (a5)+, Passed to project funcs in d6.w.

Then different projector functions read their vertex,color,other crap from (a5)+,
and on return to Project3DObj the next word will be another projection func index.
Eg: for ProjectQuad_1:
	Bytes 0,1,2,3 of (a5) are the 4 vertex ids.
	WORD 4 is colour index of some kind.
for ProjectTriangle_1:
	Bytes 0,1,2 are 3 vertex ids.
	Byte 4 is colour index.


for shoving objects into the renderer:

Caller (ejemplo DrawBGStars):
	# Creates 286 byte stackframe with
	lea	-286(a7),a7
	move.l	a7,a6

	{ bg stars
		20(a6) = 0.l
		24(a6) = 0.l
		28(a6) = $200.l
		90(a6) = $b0.w
	}
	{ hyperspace cloud (during hyperspace)
		20(a6) = 0.l
		24(a6) = 0.l
		28(a6) = some value (bigger = more distant :)
		90(a6) = $ba.w
		116(a6) = 0.w
		122(a6) = $ffff.w
	}
		
	
	call Put3DObj:
		d0 = 90(a6).w
		a5 = Address of gamedata obj num 'd0.w'.

		a4 = a6

		# make 220 byte stackframe
		link	a6,#-220

		copy 32 bytes: -36(a6) = 0(a4) [caller stackframe]

		# so (in viewing coords)
		-16(a6) = x
		-12(a6) = y
		-8(a6) = z

		# game data shit
		-208(a6) = WORD 10(a5)

		-212(a6) = LONG a4 [caller stackframe]
		-156(a6) = 0.w
		-192(a6) = 0.w

		# flags Z if obj is onscreen
		call 3DObjClipOffscreen
		if not Z: return

		-64(a6) = 0.w
		-154(a6) = $111.w
		# lighting vector:
		copy 3 LONGs: -198(a6) = L60e2    (which is normally 556(a6))
		copy 4 LONGs: -104(a6) = L60f6    (which is normally 576(a6))
		
		call CalcZnLighting
			
		

	# Destroy stackframe
	lea	286(a7),a7
	
call CalcZnLighting:
	d0-2 = z,y,z
	d3 = 0
	d5 = $4000
	d4 = abs (z)
	# find a shift value (d3) to keep abs (x,y,z) coords < $4000
	while (d4 >= $4000) {
		d3 += 1
		d4 >>= 1
	}
	
	d4 = abs (x)
	d4 >>= d3
	while (d4 >= $4000) {
		d3 += 1
		d4 >>= 1
	}

	d4 = abs (y)
	d4 >>= d3
	while (d4 >= $4000) {
		d3 += 1
		d4 >>= 1
	}

	# all LONG
	x >>= d3
	y >>= d3
	z >>= d3

	# save shift val
	-44(a6) = WORD d3
	d3 += 7
	d4 -= WORD -208(a6)

	if (d3 < 0) {
		d3 = abs (d3)
		-44(a6) += WORD d3
		WORD x >>= d3
		WORD y >>= d3
		WORD z >>= d3
	}
	x = -x
	y = -y
	z = -z

	# WORD 3x3 matrix M[9] at -36(a6)
	x1 = HIGH WORD 2*(x*M[0] + y*M[1] + z*M[2])
	y1 = HIGH WORD 2*(x*M[3] + y*M[4] + z*M[5])
	z1 = HIGH WORD 2*(x*M[6] + y*M[7] + z*M[8])
	-50(a6) = WORD x1,y1,z1

	# Lighting vector
	x,y,z = -198(a6)
	x2 = HIGH WORD 2*(x*M[0] + y*M[1] + z*M[2])
	y2 = HIGH WORD 2*(x*M[3] + y*M[4] + z*M[5])
	z2 = HIGH WORD 2*(x*M[6] + y*M[7] + z*M[8])
	-42(a6) = WORD x2,y2,z2
	return
	

# flags Z if obj is onscreen
call 3DObjClipOffscreen:
	# a5 still game data shit
	x,y,z = viewing coords
	d3 = LONG (WORD 14(a5) << WORD -208(a6))
	z += d3
	# object behind viewer
	if z < 0: return
	x = abs x
	y = abs y
	x -= d3
	if x >= 0 goto l3966e
	x = 0
	l3966e:
	if x > z: return
	y -= d3
	if y >= 0: goto l39678
	y = 0
	l39678:
	y *= 2
	if y > z: return
	x = 0
	return
		
L3e14e:
	-216(a6) = LONG (gamedata + 2(gamedata).w)
	#alloc stackframe: 
	a7 -= WORD 4(gamedata)
	a4 = a7
	# and then some more
	a7 -= WORD 8(gamedata)
	a7 -= $c0
	# save gamedata obj pointer
	-4(a6) = LONG a5
	-220(a6) = LONG gamedata + 6(gamedata).w
	
	# -208(a6) is 10(a5)
	d4 = WORD -208(a6)
	d4 -= WORD 8
	# that shift val
	d4 -= -44(a6)
	
	if (d4 > 0) {
		shift each value in vector3 -50(a6) >> d4.
	}
	# we are the only caller of this func
	call L39690:
		# a4 is the stackframe allocated previously
		# a4 has 4(gamedata).w bytes below it and
		# 8(gamedata).w + $c0 bytes above.
		a0 = a4 + 18
		-160(a0) = 0.w
		-128(a0) = 0.w
		-96(a0) = 0.w
		-64(a0) = 0.w
		-32(a0) = 0.w
		# and then it is wiped according to the length in d0,
		# every 32 fuckheads
		return
	# also only caller of this one
	call L3a00c:
		a0 = 4(a7)
		d1 = 8(gamedata).w   # which is frame size above a4...
		# wtf is -98(a6)...
		(a0)+ = LONG -98(a6)
		d1 >>= 1
		d1 -= 3
		if (d1 < 0) return
		do {
			(a0)+ = #$8080.w
		} while (--d1 != -1)
		return
	# OK. so this a4 stackframe now looks like:
	# from 4(a7) to -160(a4) (len 8(gamedata).w) filled with $8080
	# -160(a4) to (4(gamedata).w + a4), every 32-bytes = 0.w
	#
	# The bit below a4 with 32-byte chunks is for storing model vertices
	# transformed to viewing coords. It goes like this:
	# WORD*2	0	projected 2D x,y coords
	# LONG*3	4	20 + viewing transform
	# WORD		18	zero if this vertex has not been setup yet
	# LONG*3	20	model coords transformed by model rotation
	#
	-152(a6) = $2.b
	a5 += WORD 0(a5)
	
	# phew..
	call Project3DObj....
	
	lea	-224(a6),a7
	return

3DPrimCullNLight:
	ARG d0 = WORD (BYTE color id thingy)*2
	a1 = LONG -220(a6) # gamedata + 6(gamedata).w
	
	bclr	#1,d0
	if (bit 1 was set) {
		# XXX finish...
	}
	d1,d3 = WORD -4(a1,d0.w)
	d0 = d1
	d1 <<= 8
	d2 = d3
	d2 &= 0xff00
	d3 <<= 8
	d0 >>= 7
	d0 &= 0xfffe

For ProjectCoords:
	Input:
		model coords	3xl	20(a0)
		world coords	3xl	-16(a6)
	Output:
		model+world	3xl	4(a0)
		2d projection	2xw	0(a0)

