;****************************************************************************
;*	Mario Kart							    *
;*			perspective control module			    *
;*							1992.07.13	    *
;****************************************************************************
		include rp5a22
		include rp5c77
		include D77C25
		include work.def
		include buffer.def
;----------------------------------------------------------------------------
		glb	Pers_init,Set_pers_data,Set_long_pers
		glb	Pers_parameter,Set_HDMA_parameter
		glb	Initial_pers_param,Initial_camera,Pers_parameter_init
		glb	Set_HDMA_data,Realtime_pers
		glb	Change_pers
;----------------------------------------------------------------------------
pers_start	equ	0000h			;0 line start
pers_full	equ	128			;128 line loop
;----------------------------------------------------------------------------
		comn
tempolary
pointer		equ	0000h		
ofset_m		equ	nmi_work1
ofset_n		equ	nmi_work2
;----------------------------------------------------------------------------
dma_offset_001  equ     2		       ; DMA parameter label
;----------------------------------------------------------------------------
bank80		sect	rel
;----------------------------------------------------------------------------
Pers_parameter
			;X=00h(screen A)  X=02h(screen B) 
		mem8
		sep	#00100000b
		lda	#dsp_parameter		;dsp parameter set comand num
		sta	!DSP_data		;set comand data
		mem16
		rep	#00100000b
		lda	<camera_x,x		; camera 's focus position x
		sta	!DSP_data 
		lda	<camera_y,x		;                   y
		sta	!DSP_data
		lda	#0000h
		sta	!DSP_data	;     ;    z=0 (const)
		lda	<camera_distance,x	;camera-focus distance
		asl	a
		asl	a
		sta	!DSP_data
		lda	<camera_zoom,x		;camera view angle
		sta	!DSP_data
		lda	<camera_direction,x	;direction camera focus dist
		sta	!DSP_data
		lda	<camera_pitch,x
		sta	!DSP_data		;parameter set end
		lda	!DSP_status
		bpl	$-3
		clc
		lda	<camera_raster,x    ;camera focus point raster number
		adc	!DSP_data	;read vertual center offset
		sta	<virtual_center,x
		clc
		adc	!DSP_data	;read horizon raster data
		jsr	(!Check_horizon_sub,x)
		sta	<horizon,x
		sec
		lda	!DSP_data	;read screen center X
		lda	<camera_x,x
		cmp	#8000h
		ror	a
		cmp	#8000h
		ror	a
		sta	<center_x,x
		sbc	#007fh		;ofset data
		sta	<scroll_h,x
		lda	!DSP_data 	;read screen center Y
		lda	<camera_y,x
		cmp	#8000h
		ror	a
		cmp	#8000h
		ror	a
		sta	<center_y,x
		sbc	<virtual_center,x
		inc	a		;ofset 01h
		sta	<scroll_v,x
		rts	
;----------------------------------------------------------------------------
Check_horizon_sub
		word	Horizon_a,Horizon_b
Horizon_a
		cmp	#0020h
		bcc	Not_over_screena
		lda	#0001h
Not_over_screena
		rts
Horizon_b
		cmp	#0090h
		bcc	Not_over_screenb
		lda	#0070h+01h
Not_over_screenb
		rts
;----------------------------------------------------------------------------
bank81		sect	rel
;----------------------------------------------------------------------------
		mem16
		idx16
Change_pers
		phb
		phk
		plb
		jsr	!Initial_pers_param
		jsr     !Pers_parameter_init
		jsr     !Set_HDMA_data
		plb
		rtl
;----------------------------------------------------------------------------
		mem16
		idx16
Set_pers_data
		ldx	#0000h
		stz	<camera_mode+00h
		jsr     !Initial_pers_param
		jsr	!Buffer_raster
		jsr	!Set_long_pers
		rts
;----------------------------------------------------------------------------
		mem8
		idx8
Pers_init
		sep	#00110000b
		lda	#DMA_high
		sta	<pointer+1
		lda	#low DMA_6
		ldx	#8*6
		sec
Initial_repeat
		sta	<pointer+00h
		ldy	#07h
Initial_loop
		dex
		lda	!HDMA_parameter,x
		sta	(<pointer),y
		dey
		bpl	Initial_loop
		lda	<pointer+0
		sbc	#16
		cmp	#low DMA_0
		bne	Initial_repeat
		mem16
		idx16
		rep	#00110000b
		rts
;----------------------------------------------------------------------------
		mem16
		idx16
Initial_camera
		ldx	#00h
		jsr     !Initial_pers_param
		jsr	!Pers_parameter_init
		ldx	#02h
		jsr     !Initial_pers_param
		jsr	!Pers_parameter_init
;----------------------------------------------------------------------------
Set_HDMA_data
		mem8
		sep	#00100000b		
		ldx	<game_mode
		jmp	(!Game_mode_select,x)
Mode_02
		ldx	<camera_mode+02h
		jmp     (!Camera_mode_select02,x)
Mode_04
		ldx	<camera_mode+00h
		jmp	(!Camera_mode_select04,x)
Mode_00		
Type_A_set
		ldy	#00h
		bra	Goto_set_HDMA
Type_B_set
		ldy	#0eh
		bra	Goto_set_HDMA
Type_C_set
		ldy	#1ch
;----------------------------------------------------------------------------
Goto_set_HDMA
		ldx	#0000h
Pers_HDMA_loop
		lda	!HDMA_data,y
		sta	!hdma_buffer+00h,x
		sta	!hdma_buffer+0dh,x
		sta	!hdma_buffer+1ah,x
		sta	!hdma_buffer+27h,x
		beq	Next_set_HDMA
		iny
		inx
		inx
		inx
		bra	Pers_HDMA_loop
Next_set_HDMA
		iny
		ldx	#0000h
Set_mode_screen
		lda	!HDMA_data,y
		sta	!mode_change_buffer,x
		sta	!through_screen_buffer,x
		beq	End_set_buffer
		iny
		inx
		lda     !HDMA_data,y
		sta	!mode_change_buffer,x
		beq	Mode_0_set
Mode_7_set
		lda	#011h
		bra	Set_through_data
Mode_0_set
		lda	#01eh
Set_through_data
		sta     !through_screen_buffer,x
		iny
		inx
		bra	Set_mode_screen
End_set_buffer
		mem16
		rep	#00100000b
		rts		
;----------------------------------------------------------------------------
Game_mode_select
		word	Mode_00,Mode_02,Mode_04
Camera_mode_select02
		word	Type_A_set,Type_A_set,Type_A_set
		word	Type_B_set,Type_B_set,Type_B_set,Type_B_set
Camera_mode_select04
		word	Type_A_set,Type_A_set,Type_A_set
		word	Type_C_set,Type_C_set,Type_C_set,Type_C_set
;----------------------------------------------------------------------------
HDMA_data
Type_A
		byte	18h,54h+80h,1ch,58h+80h-04h	;fot perspective
		byte	00h			;end code
		byte	18h+00h,00h		;for mode change&through
		byte	58h+00h,07h
		byte	18h+00h,00h
		byte	58h+00h,07h
		byte	00h			;end code
Type_B
		byte	18h,54h+80h,07h,6dh+80h-04h
		byte	00h			
		byte	18h+00h,00h
		byte	58h+00h,07h
		byte	03h+00h,00h
		byte	6dh+00h,07h
		byte	00h			;end code
Type_C
		byte	01h,6bh+80h,1ch,58h+80h-04h
		byte	00h
		byte	01h+00h,00h
		byte	6fh+00h,07h
		byte	18h+00h,00h  
		byte	58h+00h,07h
		byte	00h			;end code
;----------------------------------------------------------------------------
HDMA_parameter
;A parameter
		byte	dma_indirect+dma_offset_001,low Rotation_A
		lword	HDMA_A_param
		byte	00h,00h,7eh
;B parameter
		byte	dma_indirect+dma_offset_001,low Rotation_B
		lword	HDMA_B_param
		byte	00h,08h,7eh
;C parameter
		byte	dma_indirect+dma_offset_001,low Rotation_C
		lword	HDMA_C_param
		byte	00h,00h,7eh	
;D parameter
		byte	dma_indirect+dma_offset_001,low Rotation_D
		lword	HDMA_D_param
		byte	00h,00h,7eh
;mode_change
		byte	00000000b		;direct dma
		byte	05h			;BG Mode resister
		lword	mode_change_buffer
		byte	00,00,00
;through screen
		byte	00000000b
		byte	02ch			;212ch (through main)
		lword	through_screen_buffer	;throgh main buffer address
		byte	00,00,00
;----------------------------------------------------------------------------
Realtime_pers
;----------------------------------------------------------------------------
Set_realtime_pers
		mem8
		sep	#00100000b
		lda	#dsp_raster
		sta	!DSP_data
		mem16
		rep	#00100000b
		lda	<horizon,x
		sbc	<virtual_center,x
		sta	!DSP_data
		ldx	#000h
		ldy	#070h
Realtime_loop
		lda	!DSP_status
		bpl	$-3
		lda	!DSP_data
		sta	>realtime_bufferA,x
		lda	!DSP_data
		sta	>realtime_bufferB,x
		lda	!DSP_data
		sta	>realtime_bufferC,x
		lda	!DSP_data
		sta	>realtime_bufferD,x
		inx
		inx
		dey
		bne	Realtime_loop
		lda	#dsp_abort
		lda	!DSP_status
		bpl	$-3
		sta	!DSP_data
		sta	!DSP_data
		sta	!DSP_data
		sta	!DSP_data
		rts
;----------------------------------------------------------------------------
Buffer_raster  
		stz	<camera_direction+00h
Raster_loop
		ldx	#0000h
		jsr	!Pers_parameter_init
		jsr	!Set_raster
		lda	<camera_direction+00h
		clc
		adc	#0100h
		sta	<camera_direction+00h
		cmp	#08000h
		bne	Raster_loop
		rts
;----------------------------------------------------------------------------
Set_raster
		lda	<camera_direction
		sta	!Multiplicand-01h
		lda	#000c0h
		sta	!Multiplier
		mem8
		sep	#00100000b
		lda	#dsp_raster
		sta	!DSP_data		;comand calc pers raster
		mem16
		idx16
		rep	#00110000b
		lda	#18h+04h
		sbc	<virtual_center		;screen center
		sta	!DSP_data
		lda	!Multiply
		tax
;----------------------------------------------------------------------------
		ldy	#60h
Buffering_loop
		lda	!DSP_status		;DSP operation complete?
		bpl	$-3
		lda	!DSP_data		;read  A
		sta	>pers_buffer+0000h,x
		lda	!DSP_data		;dummy read B
		lda	!DSP_data		;dummy read C
		lda	!DSP_data		;read    D
		sta	>pers_buffer+6000h,x
		inx
		inx
		dey
		bne	Buffering_loop
		lda	!DSP_status
		bpl	$-3
		lda	#dsp_abort
		sta	!DSP_data
		sta	!DSP_data
		sta	!DSP_data
		sta	!DSP_data
		rts
;---------------------------------------------------------------------------
		mem16
		idx16
Pers_parameter_init
			;X=00h(screen A)  X=02h(screen B) 
		mem8
		sep	#00100000b
		lda	#dsp_parameter		;dsp parameter set comand num
		sta	!DSP_data		;set comand data
		mem16
		rep	#00100000b
		lda	<camera_x,x		; camera 's focus position x
		sta	!DSP_data 
		lda	<camera_y,x		;                   y
		sta	!DSP_data
		lda	#0000h
		sta	!DSP_data	;     ;    z=0 (const)
		lda	<camera_distance,x	;camera-focus distance
		sta	!DSP_data
		lda	<camera_zoom,x		;camera view angle
		sta	!DSP_data
		lda	<camera_direction,x	;direction camera focus dist
		sta	!DSP_data
		lda	<camera_pitch,x
		sta	!DSP_data		;parameter set end
		lda	!DSP_status
		bpl	$-3
		clc
		lda	<camera_raster,x    ;camera focus point raster number
		adc	!DSP_data	;read vertual center offset
		sta	<virtual_center,x
		clc
		adc	!DSP_data	;read horizon raster data
		jsr	(!Check_horizon,x)
		sta	<horizon,x
		sec
		lda	!DSP_data	;read screen center X
		sta	<center_x,x
		sbc	#007fh		;ofset data
		sta	<scroll_h,x
		sec
		lda	!DSP_data 	;read screen center Y
		sta	<center_y,x
		sbc	<virtual_center,x
		inc	a		;ofset 01h
		sta	<scroll_v,x
		rts	
;----------------------------------------------------------------------------
Check_horizon
		word	Horizon_A,Horizon_B
Horizon_A
		cmp	#0020h
		bcc	Not_over_screenA
		lda	#0001h
Not_over_screenA
		rts
Horizon_B
		cmp	#0090h
		bcc	Not_over_screenB
		lda	#0070h+01h
Not_over_screenB
		rts
;----------------------------------------------------------------------------
Camera_raster				;camera focus raster line
		word	0066h,0066h+0070h		;screen A & B
;----------------------------------------------------------------------------
Set_HDMA_parameter
		mem16
		idx16				;Entry m16X16
		ldx	<camera_mode+00h
		jsr	(!Set_HDMA_screenA,x)
		ldx	<camera_mode+02h
		jsr	(!Set_HDMA_screenB,x)
		rtl
;----------------------------------------------------------------------------
Set_HDMA_screenA
		word	Nomal_A,Nomal_A,Nomal_A,Long_persA
Set_HDMA_screenB
		word	Nomal_B,Nomal_B,Nomal_B,Long_persB
;----------------------------------------------------------------------------
Long_persA
		ldx	#04h
		bra	Set_long_sub
;----------------------------------------------------------------------------
Long_persB				;real time buffer
		ldx	#0ah
;----------------------------------------------------------------------------
Set_long_sub
		lda	#offset realtime_bufferA
		sta	!HDMA_A_param+00h,x
		lda	#offset realtime_bufferB
		sta	!HDMA_B_param+00h,x
		lda	#offset realtime_bufferC
		sta	!HDMA_C_param+00h,x
		lda	#offset realtime_bufferD
		sta	!HDMA_D_param+00h,x
		rts
;----------------------------------------------------------------------------
Nomal_A
		mem8
		idx8
		sep	#00110000b
		lda	#040h
		sta	<ofset_m+01h
		lda	#0a0h
		sta	<ofset_n+01h
		stz	<ofset_m+00h
		stz	<ofset_n+00h
Nomal_calc_A
Next_calc_A
		lda	#0c0h			;60h line buffer
		sta	!Multiplicand		
		lda	<camera_direction+01h
		pha				;>>>>>>>>>>>A
		bpl	CM_plus_100
		eor	#0ffh
CM_plus_100
		sta	!Multiplier
		pla				;<<<<<<<<<<<A
		pha				;>>>>>>>>A
		sec
		sbc	#040h
		bpl	CM_plus_200
		eor	#0ffh
CM_plus_200
		tay
		pla				;<<<<<<<A
		clc
		adc	#040h
		bpl	CM_plus_300
		eor	#0ffh
CM_plus_300
		tax
		mem16
		idx16
		rep	#00110000b
		lda	!Multiply
		sty	!Multiplier
;
		clc
		pha				;>>>>>>>A
		adc	<ofset_m+00h		
		sta     !HDMA_A_param+04h       ;M*sinx
		pla				;<<<<<<<<A
		adc	<ofset_n+00h
		sta	!HDMA_D_param+04h       ;N*-sinx
;
		lda	!Multiply
		stx	!Multiplier
;
		adc	<ofset_m+00h
		sta     !HDMA_C_param+04h       ;-N*cosx
;
		lda	!Multiply
		adc	<ofset_n+00h
		sta	!HDMA_B_param+04h       ;M*cosx
		rts
;----------------------------------------------------------------------------
		mem8
		idx8
Nomal_B
		sep	#00110000b
;
		lda	#040h
		sta	<ofset_m+01h
		lda	#0a0h
		sta	<ofset_n+01h
		stz	<ofset_m+00h
		stz	<ofset_n+00h
Nomal_calc_B
Next_calc_B
		lda	#0c0h			;60h line buffer
		sta	!Multiplicand		
		lda	<camera_direction+03h
		pha
		bpl	CM_plus_400
		eor	#0ffh
CM_plus_400
		sta	!Multiplier
		pla
		pha
		sec
		sbc	#040h
		bpl	CM_plus_500
		eor	#0ffh
CM_plus_500
		tay
		pla
		clc
		adc	#040h
		bpl	CM_plus_600
		eor	#0ffh
CM_plus_600
		tax
		mem16
		idx16
		rep	#00110000b
		lda	!Multiply
		sty	!Multiplier
;
		clc
		pha
		adc	<ofset_m+00h
		sta     !HDMA_A_param+0ah       ;M*sinx
		pla
		adc	<ofset_n+00h
		sta	!HDMA_D_param+0ah       ;N*-sinx
;
		lda	!Multiply
		stx	!Multiplier
;
		adc	<ofset_m+00h
		sta     !HDMA_C_param+0ah       ;-N*cosx
;
		lda	!Multiply
		adc	<ofset_n+00h
		sta	!HDMA_B_param+0ah       ;M*cosx
;	
		rts					
;----------------------------------------------------------------------------
Initial_pers_param
;							;X=index 00h or 02h
;							;need camera mode
		mem16
		idx16
		ldy	<camera_mode,x
		lda	!Camera_address,y
		tay
		lda	!00h,y
		sta	<camera_distance,x
		lda	!02h,y
		sta	<camera_pitch,x
		lda	!04h,y
		sta	<camera_zoom,x
		lda	!06h,y
		clc
		adc	!Camera_raster_ofset,x
		sta	<camera_raster,x
		lda	!08h,y
		sta     <camera_x,x             ;foucus position x
		lda	!0ah,y
		sec
		sbc	!Camera_y_ofset,x
		sta     <camera_y,x             ;       ;        y
		stz     <camera_direction,x     ;
		rts
;----------------------------------------------------------------------------
		mem16
		idx16
Set_long_pers
		lda	#06h
		sta	<camera_mode+00h
		ldx	#00h
		jsr	!Initial_pers_param
		jsr	!Pers_parameter_init
		jsr	!Set_realtime_pers
		rts
;---------------------------------------------------------------------------
Camera_raster_ofset
		word	0000h,0070h
Camera_y_ofset
		word	0038h*04h+180h,00a8h*04h
;---------------------------------------------------------------------------
Camera_address
		word	Camera_data1,Camera_data1,Camera_data1,Camera_data2
;							distance
;							pitch
;							zoom
;							raster
;							control
;							x
;							y
Camera_data1;-----------------------------Nomal game pers
		word	00040h
		word	03400h
		word	00100h
		word	00066h
Camera_data2;----------------------------Other pers(long range)
		word	00880h
		word	02a00h
		word	00200h
		word	00066h
		word	00200h*04h
		word	00480h*04h
		end
