*************************************************
* Gun Demonstration program for Trojan PHAZER   *
* When run Shoot at Cross to calibrate          *
* Then fire at screen to plot point for gunshot *
*************************************************
* The driver bits are at the end of this proram *
* and are fully documented, not this is the     *
* straightfoward lose a frame version           *
*************************************************

	output FrameGun

	Section GunHelp,CODE_C

XMiddle		EQU 160		* Gun Calibrate point X
YMiddle		EQU 100		* Gun Calibrate point Y

	include "consts.s"	* constant includes
palsize		EQU 16
num_cols	EQU 15
scrheight	EQU 200
pix_div		EQU 8
c_div		EQU 1
Xshift		EQU 3
spr_len		EQU 8
msk_len		EQU 8
bpl1		EQU 40
bpl2		EQU 40
bpl3		EQU 2
m_off		EQU 2
m_pln		EQU 40
m_eol		EQU 120
ascr1		EQU $78000
ascr1d		EQU $78000
linelen		EQU 160
scr_size	EQU ((linelen*scrheight)/4)-1

rts		* dummy labels
even

***********************************************************
* main program
InitStuff
	* Set palette to black and showinitial screen *
	move.l #load_palette,d0
	bsr set_palette
	bsr init_machine		* set machine bits

	move.w #$ffff,d0		* wait a bit
i_wait_1
	dbra d0,i_wait_1

	move.l #stack_pointer,a7	* new amiga stack
	bsr set_interrupts		* set up interrupts
	bsr init_scraddrs		* set main screen addresses
	bsr calibrate_screen

***********************************************************
main_loop
	tst.b plotter
	beq no_plot_point
	move.w GunX,d0
	move.w GunY,d1
	bsr plot_point
no_plot_point
	*** DO GAME HERE ***
	bra main_loop
	rts

***********************************************************
* d0=X    d1=Y
plot_point
	clr.b plotter
	move.w d0,d2
	and.l #15,d0
	and.l #$fff0,d2
	lsr.w #3,d2
	move.w #%1000000000000000,d3
	lsr.w d0,d3
	mulu.w #160,d1
	add.l d2,d1
	add.l #ascr1,d1
	move.l d1,a0
	or.w d3,(a0)
	rts

***********************************************************
display_screen
	move.l #ascr1,d0
	bsr show_screen
	bsr frame_wait
	rts
***********************************************************
frame_wait
	tst.b frame_end
	beq frame_wait
	clr.b frame_end
	rts
***********************************************************
init_screen
	move.l #ascr1,a0
	bsr clear_screen
	rts
***********************************************************
readkey
	move.b KeyAddr,key_press
	clr.b KeyAddr
	rts
***********************************************************
init_machine
	bsr hard_sprites_off
	bsr set_up_screen
	bsr hard_data_off
	rts
***********************************************************
hard_sprites_off
	move.l #offsprite,d0
	move.l d0,d1
	swap d1
	move.l #coppersprs,a0
	add.l #2,a0
	move.w #7,d7
hard_off_loop
		move.w d1,(a0)
		add.l #4,a0
		move.w d0,(a0)
		add.l #4,a0
	dbra d7,hard_off_loop
***********************************************************
hard_data_off
	move.l #$dff014c,a0
	move.w #7,d7
hard_offd_loop
		move.l #0,(a0)
		add.l #8,a0
	dbra d7,hard_offd_loop
	rts
***********************************************************
* set up the amiga screen 
* reg BPLCON0 bit 15 = res 14,13,12 - BtPLanes
set_up_screen
	** Set Light Pen Bit (3) on in BPLCON0 **
	move.w #%0100000000001000,BPLCON0	* put in screen characteristics
	move.w #0,BPLCON1
	move.w #120,BPL1MOD
	move.w #120,BPL2MOD
	move.w #$38,DDFSTRT
	move.w #$d0,DDFSTOP
	move.w #$3881,DIWSTRT
	move.w #$ffc1,DIWSTOP
	move.l #copperlist,COP1LCH *
	move.w COPJMP1,d0
	
	rts

***********************************************************
set_interrupts
	move.w #%0111111111111111,DMACONW
	move.w #%1000011111000000,DMACONW
	move.w #%0111111111111111,INTENA
	move.b #%01111111,$bfed01
	move.b #%01111111,$bfdd00
	move.b #%10001000,$bfed01
	move.l #null_interrupt,$64
	move.l #level2_interrupt,$68
	move.l #level3_interrupt,$6c
	move.l #null_interrupt,$70
	move.l #null_interrupt,$74
	move.l #null_interrupt,$78
	move.w #%0000000011111111,ADKCON
	sf.b frame_end
	move.w #%1100000000111000,INTENA
	move.w #$7fff,INTREQ
	rts
null_interrupt
	move.w INTREQR,INTREQ
	rte
level2_interrupt
	move.b d0,-(sp)
	move.b $bfed01,d0
	move.b $bfec01,d0
	or.b #$40,$bfee01
	and.b #$bf,$bfee01
	move.w INTREQR,INTREQ
	move.b (sp)+,d0
	rte
level3_interrupt
	btst.b #5,INTREQR+1
	beq not_vblank_int
		bsr every_frame
not_vblank_int
	move.w INTREQR,INTREQ
	rte
***********************************************************
clear_screen
	move.w #7999,d0
	moveq.l #0,d1
clrscreenloop
		move.l d1,(a0)+
	dbra d0,clrscreenloop
	rts
***********************************************************
init_scraddrs
	move.l #ascr1,dispscr
	move.l #ascr1,dispscr
	move.l #ascr1d,dispscr_d
	move.l #ascr1d,dispscr_d
	move.l #0,writeoff
	move.l #4,dispoff
	rts
***********************************************************
set_palette
	move.l #COLOR0,a0
	move.l d0,a1
	move.w #15,d0
palette_loop
		move.w (a1)+,(a0)+
	dbra d0,palette_loop
	rts
***********************************************************
show_screen
	move.l d0,d1
	add.l #40,d1
	move.l d1,d2
	add.l #40,d2
	move.l d2,d3
	add.l #40,d3
	move.w d0,pln1low
	swap d0
	move.w d0,pln1high
	move.w d1,pln2low
	swap d1
	move.w d1,pln2high
	move.w d2,pln3low
	swap d2
	move.w d2,pln3high
	move.w d3,pln4low
	swap d3
	move.w d3,pln4high
	rts	

**************** COPPER *******************
copperlist
coppersprs
	dc.w $120,0,$122,0,$124,0,$126,0
	dc.w $128,0,$12a,0,$12c,0,$12e,0
	dc.w $130,0,$132,0,$134,0,$136,0
	dc.w $138,0,$13a,0,$13c,0,$13e,0
	dc.w $e0
pln1high
	dc.w $7
	dc.w $e2
pln1low
	dc.w $8000
	dc.w $e4
pln2high
	dc.w $7
	dc.w $e6
pln2low
	dc.w $8028
	dc.w $e8
pln3high
	dc.w $7
	dc.w $ea
pln3low
	dc.w $8050
	dc.w $ec
pln4high
	dc.w $7
	dc.w $ee
pln4low
	dc.w $8078
	dc.w $ffff,$fffe
offsprite
	dc.w $0101,$0100,0,0,0,0,0,0,0,0

************************** VARS ***************************
writescr		ds.l 1	* address of 1 screen
dispscr 		ds.l 1	* address of other
writescr_d		ds.l 1	* addr of display 1
dispscr_d		ds.l 1	* addr of 2
writeoff		ds.l 1	* offset (0/4) for tables
dispoff			ds.l 1	* opposite of above ie 4/0
junk			ds.l 1	* junk address
curr_pal		ds.l 1	* Current palette pointer
key_press		ds.b 1
frame_end		ds.b 1

plotter			ds.b 1	* Set when gun point recieved
scan_frame		ds.b 1  * Set when the frame is white
gun_button		ds.b 1	* gun port in value
gun_fired		ds.b 1	* fire shot
X_cal			ds.w 1	* X calibration
Y_cal			ds.w 1	* Y calibration
GunX			ds.w 1
GunY			ds.w 1

black_palette
	ds.l 8
load_palette
		dc.w $000,$fff,$003,$116
		dc.w $359,$69c,$adf,$a8d
		dc.w $65a,$326,$113,$dbf
		dc.w $a60,$fd0,$999,$333
white_palette
		dc.w $fff,$fff,$fff,$fff
		dc.w $fff,$fff,$fff,$fff
		dc.w $fff,$fff,$fff,$fff
		dc.w $fff,$fff,$fff,$fff

** my stack space **
	ds.l 70
stack_pointer
	ds.l 5

************************** END ***************************
***********************************************************
***********************************************************
***********************************************************
*      Gun Driver Code Follows 
***********************************************************
* executed every 50th sec 
every_frame
	add.b #1,frame_end
	movem.l d0-d7/a0-a6,-(sp)
	bsr do_gun_bits
	movem.l (sp)+,d0-d7/a0-a6
	rts

do_gun_bits
	tst.b scan_frame
	bne get_scan_vals
	bsr read_trigger	* Test gun trigger
	tst.b gun_button
	beq no_fire_gun
		st.b scan_frame		* Fired so set flag and white screen
		bsr set_read_frame	
no_fire_gun
	rts
get_scan_vals
		clr.b scan_frame
		bsr get_frame_info 	* get gun position
		move.b gun_fired,plotter
	rts

***********************************************************
calibrate_screen
	move.l #ascr1,a0		* clear both screens
	bsr clear_screen

	* Plot blob at 160,100 *
	* Or animate your sprite here *
	move.w #XMiddle,d0
	move.w #YMiddle,d1
	bsr plot_point
	move.w #XMiddle+1,d0
	move.w #YMiddle,d1
	bsr plot_point
	move.w #XMiddle-1,d0
	move.w #YMiddle,d1
	bsr plot_point
	move.w #XMiddle,d0
	move.w #YMiddle+1,d1
	bsr plot_point
	move.w #XMiddle,d0
	move.w #YMiddle-1,d1
	bsr plot_point
		
restart_screen
	clr.w X_cal
	clr.w Y_cal		* clear previous calibrations
no_cal_press
	bsr read_trigger	* Wait for trigger pull
	tst.b gun_button
	beq no_cal_press

	clr.b frame_end		* Wait for next frame start
	bsr frame_wait
	bsr gun_read		* Read the Gun X and Y

	move.w GunX,d0		* Get gun X&Y
	move.w GunY,d1

	sub.w #XMiddle,d0	* Get offsets from centre of target
	sub.w #YMiddle,d1

 	move.w d0,X_cal		* Store as calibrate offsets
	move.w d1,Y_cal		* These are added to shot pos

	tst.b gun_fired		* Make sure gun registered properly
	beq restart_screen	* Else calibrate again

	cmp.w #24,X_cal		* Check calibrated roughly right
	bcs no_restart_screen	* at roughly correct X
	cmp.w #-24,X_cal
	bcc no_restart_screen	* at roughly correct X
	bra restart_screen	* If not close then redo
no_restart_screen
	rts	

***********************************************************
* read the beam pos on the screen *
gun_read
	move.b #1,gun_fired		* Set gun fired flag
read_the_beam	
	move.l #white_palette,d0
	bsr set_palette			* White out screen
	* now computer is looking down the screen for beam *
frame_wait2			* wait for frame end before resetting cols
	tst.b frame_end
	beq frame_wait2
	clr.b frame_end

	* reset cols *
	move.l #load_palette,d0
	bsr set_palette

	bsr make_coords		* Get register and make coords
	
	move.w X_cal,d0		* SUBTRACT the calibration offsets
	move.w Y_cal,d1
	sub.w d0,GunX
	sub.w d1,GunY
	rts						* return to main program *

***********************************************************
* read the gun button and put val in gun_button
read_trigger
	sf.b gun_button		* Clear trigger flag
	btst.b #1,JOY1DAT	* Test tigger bit on port
	beq not_pressed_trigger
		not.b gun_button	* Set trigger flag
not_pressed_trigger
	rts

***********************************************************
set_read_frame
	move.l #white_palette,d0
	bsr set_palette			* White out screen
	rts

get_frame_info
	move.b #1,gun_fired		* Set gun fired flag
	* reset cols *
	move.l #load_palette,d0
	bsr set_palette
	bsr make_coords		* Get register and make coords
	move.w X_cal,d0		* SUBTRACT the calibration offsets
	move.w Y_cal,d1
	sub.w d0,GunX
	sub.w d1,GunY
	rts						* return to main program *

***********************************************************
* Correct the latched location into X and Y coords
make_coords
	move.l VPOSR,d0		* Latched lightpen location
	move.l d0,d1		* y copy
	and.l #$01ff00,d1
	lsr.l #8,d1		* correct Y
	and.l #511,d1

	and.w #$ff,d0
	lsl.w #1,d0
	and.w #511,d0		* correct X

	btst.l #8,d1		* check if Y>255
	bne clear_gunshot
	cmp.w #176,d0		* see if on left half of screen
	bcs off_left_part
		sub.w #192,d0
		bra install_coords
off_left_part
	cmp.w #90,d0
	bcc off_right_part
		add.w #452-192,d0
		bra install_coords
off_right_part 
clear_gunshot	* If off screen then come here
		sf.b gun_fired
install_coords
	and.l #511,d0
	and.l #511,d1
	move.w d0,GunX		* Store values
	move.w d1,GunY
	rts

***********************************************************
***********************************************************
***********************************************************
***********************************************************
