;************************************************************************
;*									*
;*	 TITLE OF THIS WORK	     :	   "F-ZERO" software		*
;*									*
;*	 NAME OF AUTHER		     :	   Nintendo Co., Ltd.		*
;*									*
;*	 YEAR IN WHICH CREATION OF					*
;*	     THIS WORK WAS COMPLETED :	      1990,1991			*
;*									*
;*	 (C) 1990,1991 NINTENDO CO., LTD. ALL RIGHTS RESERVED		*
;*									*
;*									*
;*	 Copyright 1990,1991 NINTENDO CO., LTD. ALL RIGHTS RESERVED	*
;*									*
;*				    [ Apr.01,1989 --- May.14,1991 ]	*
;*									*
;*	    Programmer	Y.Nishida  M.Kimura  S.Yamashiro		*
;*									*
;************************************************************************


;************************************************************************
;*	 CAR_MAIN	   -- main module --				*
;************************************************************************
;
		INCLUDE	  RP5A22:
		INCLUDE	  RP5C77:
		INCLUDE	  VARIABLE
		INCLUDE	  BUFFER
;
;=============== Cross reference =======================================
;
		EXT	  Title_entry
		EXT	  Select_entry
		EXT	  Game_entry
		EXT	  Over_entry
		EXT	  Transfer_pers,Transfer_enemy,Set_backup_buff
		EXT	  Boot_APU,Start_sound
;
;=============== Cross definition ======================================
;
		GLB	  Write_color,Write_screen,Write_character,Write_VRAM
		GLB	  Clear_OAM,Start_DMA,Scan_emulate,Return_long
		GLB	  VRAMbuf_offset
;
;=============== Define local variable =================================
;
work		EQU	  0000H
;
;=======================================================================
;
		PROG
		EXTEND
;
;************************************************************************
;*		 Program start						*
;************************************************************************
;
		NATIVE
Program_entry
		SEI			      ; IRQ disable
		REP	  #00001001B	      ; Set binary mode
		XCE			      ; Set native mode
;-----------------------------------------------------------------------
		MEM8
		IDX8
		SEP	  #00110000B	      ; Memory,Index 8 bit mode
		STZ	  !NMI_control	      ; NMI disable
		STZ	  !DMA_burst	      ; M_DMA all enable
		STZ	  !DMA_syncro	      ; H_DMA all enable
		LDA	  #10000000B
		STA	  !PPU_control	      ; Screen blanking
		STZ	  !PPU_mode	      ; Set PPU mode
		STZ	  !4016H
;-----------------------------------------------------------------------
		MEM16
		REP	  #00100000B	      ; Memory 16 bit mode
		LDA	  #0000H
		TCD			      ; Set direct register
		LDA	  #01FFH
		TCS			      ; Set stack pointer
;
;************************************************************************
;*		 System initialize					*
;************************************************************************
;
		IDX8
		MEM8
		SEP	  #00110000B	      ; Memory,Index 8 bit mode
;-----------------------------------------------------------------------
		JSR	  Init_work	      ; Clear variable ( 0 page )
		JSR	  Boot_APU	      ; Boot APU
		LDA	  #01H
		STA	  <demo_flag	      ; Set demo mode
;
;=============== program start =========================================
;
		CLI			      ; IRQ enable
		LDA	  #10000001B
		STA	  !NMI_control	      ; NMI,Controller enable
;
;************************************************************************
;*		 Main routine						*
;************************************************************************
;
		MEM8
		IDX8
Main_routine
		SEP	  #00110000B	      ; Memory,Index 8 bit mode
		STZ	  <NMI_flag	      ; Clear software NMI flag
;
;=============== Wait NMI ==============================================
Main_routine100
		LDA	  <NMI_flag	      ; NMI flag on ?
		BEQ	  Main_routine100     ; no.
;
;=============== Main routine ==========================================
Main_routine200
		LDA	  <fade_flag	      ; Fade_in,Fade_out mode ?
		BNE	  Main_routine220     ; yes.
;-----------------------------------------------------------------------
Main_routine210 LDA	  <game_mode
		ASL	  A
		TAX
		JSR	  (!Mode_vector,X)     ; Call mode process
		BRA	  Main_routine
;-----------------------------------------------------------------------
Main_routine220 JSR	  Fade_in_out	      ; Fade_in,Fade_out
		BRA	  Main_routine
;-----------------------------------------------------------------------
Mode_vector	WORD	  Title_entry	      ; title mode
		WORD	  Select_entry	      ; demo mode
		WORD	  Game_entry	      ; game play mode
		WORD	  Over_entry	      ; game over mode
;
;************************************************************************
;*		 Fade_in Fade_out					*
;************************************************************************
;
		MEM8
		IDX8
Fade_in_out
		LDX	  <fade_count	      ; counter == 0 ?
		BEQ	  Fade_in_out_2	      ; yes.
		DEC	  <fade_count	      ; --counter == 0 ?
		BNE	  Fade_in_out30	      ; no.
;-----------------------------------------------------------------------
Fade_in_out_2	DEC	  A		      ; fade_in mode ?
		BNE	  Fade_out	      ; no.
;
;=============== Fade in ===============================================
Fade_in
		LDA	  <screen_contrast
		AND	  #0FH		      ; clear blanking bit
		INC	  A
		STA	  <screen_contrast    ; countrast++
		CMP	  #00001111B	      ; Contrast == 15 ?
		BNE	  Fade_in_out20	      ; no.
		BRA	  Fade_in_out10	      ; yes.
;
;=============== Fade out ==============================================
Fade_out
		DEC	  <screen_contrast    ; contrast-- == 0 ?
		BNE	  Fade_in_out20	      ; no.
		LDA	  #10000000B
		STA	  <screen_contrast    ; Set blanking bit
		LDA	  <sound_status_0     ; music fade out ?
		BPL	  Fade_in_out10	      ; no.
		AND	  #11110000B
		STA	  <sound_status_0     ; Reset music number
;
;=============== End of fade_in,fade_out ===============================
Fade_in_out10
		STZ	  <fade_flag	      ; Clear fade_in,fade_out flag
		LDA	  #02H
		STA	  <fade_step	      ; Set standard value to fade_step
		RTS
;-----------------------------------------------------------------------
Fade_in_out20	LDA	  <fade_step
		STA	  <fade_count	      ; Set fade_in,fade_out timer
Fade_in_out30	RTS
;
;************************************************************************
;*		 Initialize variable and buffer				*
;************************************************************************
;
		MEM16
		IDX16
Init_work
		PHP
		REP	  #00110000B	      ; Memory,Index 16 bit mode
;
;=============== Initial zero page =====================================
Init_work100
		STZ	  <0000H
		LDA	  #00FEH	      ; Acc = number of bytes
		LDX	  #0000H	      ; IX  = source address
		LDY	  #0001H	      ; IY  = destination address
		MVN	  #00H,#00H	      ; Clear zero page
;
;=============== Initial buffer ========================================
Init_work200
		STZ	  !0200H
		LDA	  #1DFEH	      ; Acc = number of bytes
		LDX	  #0200H	      ; IX  = source address
		LDY	  #0201H	      ; IY  = destination address
		MVN	  #00H,#00H	      ; Clear work buffer
;-----------------------------------------------------------------------
		LDA	  #024FFH	      ; Acc = number of bytes
		LDX	  #0C380H	      ; IX  = panel data address
		LDY	  #00000H	      ; IY  = panel buffer address
		MVN	  #0CH,#7FH	      ; Transfer map panel data
;-----------------------------------------------------------------------
		PHK
		JSR	  Transfer_pers	      ; Transfer perspective data
		PHK
		JSR	  Transfer_enemy      ; Transfer enemy character
		PHK
		JSR	  Set_backup_buff     ; Set best time buffer
;
;=============== Initialize work =======================================
Init_work300
		MEM16
		IDX8
		SEP	  #00010000B	      ; Index 8 bit mode
;-----------------------------------------------------------------------
		LDA	  #IRQ_exit	      ; Acc = IRQ exit address
		STA	  <IRQ_pointer	      ; Set IRQ_pointer
		LDX	  #04H
		STX	  <fade_step	      ; Set fade_in,fade_out step time
		LDX	  #10000000B
		STX	  <screen_contrast    ; Set screen blanking
		LDX	  #00000010B
		STX	  <window_color_sw    ; Set window color_add switch
;
;=============== End of initialize =====================================
Init_work900
		PLP			      ; Restore mode
		RTS
;
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;\\\\\\\\\\\\\\\ NMI routines \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;************************************************************************
;*		 NMI routine main					*
;************************************************************************
;
		MEM16
		IDX16
NMI_entry
		REP	  #00110000B	      ; Memory,Index 16 bit mode
		PHA
		PHX
		PHY
		PHD
		PHB
		LDA	  #0000H
		TCD
;-----------------------------------------------------------------------
		MEM8
		IDX8
		SEP	  #00110000B	      ; Memory,Index 8 bit mode
		PHA			      ; Acc = 0
		PLB			      ; Set data bank register
;
;=============== NMI routine ===========================================
NMI_routine
		LDA	  !NMI_status	      ; Reset hardware NMI flag ( hard )
		LDX	  <NMI_flag	      ; NMI waiting ?
		BNE	  Process_over	      ; no.
		DEC	  <NMI_flag	      ; Set software NMI flag
;-----------------------------------------------------------------------
		JSR	  Mode_change	      ; Pert BG mode change
		PHK
		JSR	  Write_screen	      ; Write screen ( scroll )
		JSR	  Write_object	      ; Write Object Attribute
		JSR	  Write_color	      ; Write color palet
		JSR	  Perspective	      ; Change perspective
		JSR	  Set_scroll	      ; Set scroll register
		JSR	  Set_window	      ; Set window DMA address
		JSR	  Write_VRAM	      ; Write data to VRAM
		JSR	  Write_character     ; Write character data
		JSR	  Write_meter	      ; Write meter
		JSR	  Write_crater	      ; Write crater
;-----------------------------------------------------------------------
		LDA	  <HDMA_switch
		STA	  !DMA_syncro	      ; Set HDMA switch
		LDA	  <screen_contrast
		STA	  !PPU_control	      ; Set screen contrast
;-----------------------------------------------------------------------
		INC	  <frame_counter      ; Increment frame counter
		PHK
		JSR	  Scan_controller     ; Scan controller
		JSR	  Start_sound
		JSR	  Set_IRQ	      ; Set IRQ
		BRA	  NMI_exit
;
;=============== Process over ==========================================
Process_over
		JSR	  Mode_change	      ; Pert BG mode change
		JSR	  Set_IRQ	      ; Set IRQ
;
;=============== NMI exit ==============================================
;
		MEM16
		IDX16
NMI_exit
		REP	  #00110000B	      ; Memory,Index 16 bit mode
		PLB
		PLD
		PLY
		PLX
		PLA
not_use		RTI
;
;************************************************************************
;*		 Scan controller emulate				*
;************************************************************************
;
		MEM16
Scan_emulate
		PHP
		REP	  #00110000B	      ; Memory 16 bit mode
;-----------------------------------------------------------------------
		LDA	  <stick_status	      ; Set controller status
		BRA	  Scan_control10
;
;************************************************************************
;*		 Scan controller					*
;************************************************************************
;
		MEM16
Scan_controller
		PHP
		REP	  #00110000B	      ; Memory 16 bit mode
;-----------------------------------------------------------------------
		LDA	  !Button
		STA	  <stick_status	      ; Set controller status
;-----------------------------------------------------------------------
Scan_control10	EOR	  <stick_backst
		PHA
		AND	  <stick_status
		STA	  <stick_trigger      ; Set controller trigger
;-----------------------------------------------------------------------
		PLA
		AND	  <stick_backst
		STA	  <stick_cleartg      ; Set controller clear trigger
;-----------------------------------------------------------------------
		LDA	  <stick_status
		STA	  <stick_backst	      ; Set controller back status
;-----------------------------------------------------------------------
		PLP			      ; Restore mode
		RTL
;
;************************************************************************
;*		 Set scroll register					*
;************************************************************************
;
		MEM8
		IDX8
Set_scroll
		LDA	  <BG2_scroll_h+0
		STA	  !Scroll_H+2	      ; Set BG2 scroll h ( low )
		LDA	  <BG2_scroll_h+1
		STA	  !Scroll_H+2	      ; Set BG2 scroll h ( high )
;
		LDA	  <BG2_scroll_v+0
		STA	  !Scroll_V+2	      ; Set BG2 scroll v ( low )
		LDA	  <BG2_scroll_v+1
		STA	  !Scroll_V+2	      ; Set BG2 scroll v ( high )
;-----------------------------------------------------------------------
		LDA	  <center_x+0
		STA	  !Rotation_center+0  ; Set rotation center x ( low )
		LDA	  <center_x+1
		STA	  !Rotation_center+0  ; Set rotation center x ( high )
;
		LDA	  <center_y+0
		STA	  !Rotation_center+1  ; Set rotation center y ( low )
		LDA	  <center_y+1
		STA	  !Rotation_center+1  ; Set rotation center y ( high )
;
;=============== Set BG1 scroll register ===============================
Set_scroll200
		LDA	  <part_flag	      ; part mode change ?
		BNE	  Set_scroll250	      ; no.
;-----------------------------------------------------------------------
		LDA	  <BG1_scroll_h+0
		STA	  !Scroll_H+0	      ; Set BG1 scroll h ( low )
		LDA	  <BG1_scroll_h+1
		STA	  !Scroll_H+0	      ; Set BG1 scroll h ( high )
;
		LDA	  <BG1_scroll_v+0
		STA	  !Scroll_V+0	      ; Set BG1 scroll v ( low )
		LDA	  <BG1_scroll_v+1
		STA	  !Scroll_V+0	      ; Set BG1 scroll v ( high )
		RTS
;-----------------------------------------------------------------------
Set_scroll250	LDY	  <scroll_selector
		LDA	  !scroll_table_L1,Y
		STA	  <vertical_timer+0
		STZ	  <vertical_timer+1   ; Set vertical count timer
		TYA
		CLC
		ADC	  #LOW scroll_table_1
		STA	  !DMA_1+2	      ; Set scroll HDMA table address low
		RTS
;
;************************************************************************
;*		 Write object						*
;************************************************************************
;
		MEM16
		IDX8
Write_object
		REP	  #00100000B	      ; Memory 16 bit mode
		STZ	  !Sprite_address     ; Set write address
;-----------------------------------------------------------------------
		LDA	  #0400H
		STA	  !DMA_0+0	      ; Set DMA ctrl & B address
		LDX	  #00H
		STX	  !DMA_0+4	      ; Set DMA A bank
		INX			      ; IX = 00000001B
;-----------------------------------------------------------------------
		LDY	  <objwte_flag
		BEQ	  Write_object500
;
;=============== Meter OAM data ========================================
Write_object100
		LDA	  #OAM_main
		STA	  !DMA_0+2	      ; Set DMA A address
		LDA	  #0100H
		STA	  !DMA_0+5	      ; Set DMA data length
		STX	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		LDA	  #OAM_main+1C0H
		STA	  !DMA_0+2	      ; Set DMA A address
		LDY	  #10H
		STY	  !DMA_0+5	      ; Set DMA data length
		STX	  !DMA_burst	      ; Start DMA channel #0
;
;=============== Car OAM data ==========================================
Write_object200
		LDY	  #20H
		LDA	  !OAM_address+00H
		STA	  !DMA_0+2	      ; Set DMA A address
		STY	  !DMA_0+5	      ; Set DMA data length low
		STX	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		LDA	  !OAM_address+02H
		STA	  !DMA_0+2	      ; Set DMA A address
		STY	  !DMA_0+5	      ; Set DMA data length low
		STX	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		LDA	  !OAM_address+04H
		STA	  !DMA_0+2	      ; Set DMA A address
		STY	  !DMA_0+5	      ; Set DMA data length low
		STX	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		LDA	  !OAM_address+06H
		STA	  !DMA_0+2	      ; Set DMA A address
		STY	  !DMA_0+5	      ; Set DMA data length low
		STX	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		LDA	  !OAM_address+08H
		STA	  !DMA_0+2	      ; Set DMA A address
		STY	  !DMA_0+5	      ; Set DMA data length low
		STX	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		LDA	  !OAM_address+0AH
		STA	  !DMA_0+2	      ; Set DMA A address
		STY	  !DMA_0+5	      ; Set DMA data length
		STX	  !DMA_burst	      ; Start DMA channel #0
;
;=============== Shadow OAM data and OAM sub ===========================
Write_object300
		LDA	  #OAM_main+1D0H
		STA	  !DMA_0+2	      ; Set DMA A address
		LDY	  #50H
		STY	  !DMA_0+5	      ; Set DMA data length
		STX	  !DMA_burst	      ; Start DMA channel #0
		BRA	  Write_object600
;
;=============== Write OAM all =========================================
Write_object500
		LDA	  #OAM_main
		STA	  !DMA_0+2	      ; Set DMA A address
		LDA	  #0220H
		STA	  !DMA_0+5	      ; Set DMA data length
		STX	  !DMA_burst	      ; Start DMA channel #0
;
;=============== Set object size =======================================
Write_object600
		LDX	  <OBJchar_status
		STX	  !Sprite_size	      ; Set OBJ status register
		SEP	  #00110000B	      ; Memory,Index 8 bit mode
		RTS
;
;************************************************************************
;*		 Write color						*
;************************************************************************
;
		MEM8
		IDX16
Write_color
		PHP
		SEP	  #00100000B	      ; Memory 8 bit mode
		REP	  #00010000B	      ; Index 16 bit mode
		LDA	  <colwte_flag	      ; color write mode
		BEQ	  Write_color900      ; no.
		DEC	  A		      ; screen flash ?
		BNE	  Write_color200      ; yes.
;
;=============== Color change ==========================================
Write_color100
		LDX	  #2200H
		STX	  !DMA_0+0	      ; Set DMA ctrl & B address
		LDX	  #color_buffer
		STX	  !DMA_0+2	      ; Set DMA A address
		STZ	  !DMA_0+4	      ; Set DMA A bank
		LDX	  #0200H
		STX	  !DMA_0+5	      ; Set DMA data length
;-----------------------------------------------------------------------
		STZ	  !Color_address      ; Set color write address
		LDA	  #00000001B
		STA	  !DMA_burst	      ; Start DMA channel #0
		BRA	  Write_color900
;
;=============== Color flash ===========================================
Write_color200
		LDX	  #2208H
		STX	  !DMA_0+0	      ; Set DMA ctrl & B address
		LDX	  #flash_color
		STX	  !DMA_0+2	      ; Set DMA A address
		STZ	  !DMA_0+4	      ; Set DMA A bank
		LDX	  #0100H
		STX	  !DMA_0+5	      ; Set DMA data length
;-----------------------------------------------------------------------
		STZ	  !Color_address      ; Set color write address
		LDA	  #00000001B
		STA	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		DEC	  <colwte_flag	      ; Reset flashing flag
;
;=============== Exit color write ======================================
Write_color900
		PLP			      ; Restore mode
		RTS
;
;************************************************************************
;*		 Write screen data to VRAM				*
;************************************************************************
;
		MEM8
		IDX16
Write_screen
		PHP
		SEP	  #00100000B	      ; Memory 8 bit mode
		REP	  #00010000B	      ; Index 16 bit mode
		LDA	  <srnwte_status      ; write buffer enable ?
		BEQ	  Write_screen300     ; no.
;-----------------------------------------------------------------------
		LDX	  #1800H
		STX	  !DMA_0+0	      ; Set DMA ctrl & B address
		LDA	  #7FH
		STA	  !DMA_0+4	      ; Set DMA A bank
;
;=============== Horizontal write ======================================
Write_screen100
		STZ	  !Screen_step	      ; Set inc. mode Low +1
		LDX	  <Hwrite_address
		STX	  !Screen_address     ; Set VRAM address
;-----------------------------------------------------------------------
		LDX	  #Hwrite_buffer1&0FFFFH
		STX	  !DMA_0+2	      ; Set DMA A aaddress
		LDX	  #0100H
		STX	  !DMA_0+5	      ; Set DMA data length
		LDA	  #00000001B
		STA	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		DEC	  <srnwte_status      ; vertical write ?
		BEQ	  Write_screen300     ; no.
;
;=============== Vertical write ========================================
Write_screen200
		LDA	  #00000011B
		STA	  !Screen_step	      ; Set inc. mode Low +128
		LDX	  <Vwrite_address
		STX	  !Screen_address     ; Set VRAM address
;-----------------------------------------------------------------------
		LDX	  #Vwrite_buffer1&0FFFFH
		STX	  !DMA_0+2	      ; Set DMA A aaddress
		LDX	  #0080H
		STX	  !DMA_0+5	      ; Set DMA data length
		LDA	  #00000001B
		STA	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		LDX	  <Vwrite_address
		INX
		STX	  !Screen_address     ; Set VRAM address
;-----------------------------------------------------------------------
		LDX	  #Vwrite_buffer2&0FFFFH
		STX	  !DMA_0+2	      ; Set DMA A aaddress
		LDX	  #0080H
		STX	  !DMA_0+5	      ; Set DMA data length
		LDA	  #00000001B
		STA	  !DMA_burst	      ; Start DMA channel #0
;
;=============== End of write screen ===================================
Write_screen300
		STZ	  <srnwte_status      ; Reset screen write flag
		PLP			      ; Restore mode
		RTL
;
;************************************************************************
;*		 Change perspective					*
;************************************************************************
;
		MEM8
		IDX8
Perspective
		LDA	  <pers_flag	      ; pers_flag enable ?
		BEQ	  Perspective300      ; no.
		DEC	  A		      ; no pers mode ?
		BNE	  Perspective200      ; yes.
;
;=============== Perspective ===========================================
Perspective100
		LDA	  <pers_selector
		CLC
		ADC	  #LOW pers_tableA1
		STA	  !DMA_4+2	      ; Set matrix A adrress low
		STA	  !DMA_7+2	      ; Set matrix D address low
		ADC	  #20H
		STA	  !DMA_5+2	      ; Set matrix B address low
		STA	  !DMA_6+2	      ; Set matrix C address low
;-----------------------------------------------------------------------
		LDA	  <pers_databank_A
		STA	  !DMA_4+7	      ; Set matrix A data bank
		LDA	  <pers_databank_B
		STA	  !DMA_5+7	      ; Set matrix B data bank
		LDA	  <pers_databank_C
		STA	  !DMA_6+7	      ; Set matrix C data bank
		LDA	  <pers_databank_D
		STA	  !DMA_7+7	      ; Set matrix D data bank
;-----------------------------------------------------------------------
		LDA	  #11110000B
		TSB	  <HDMA_switch	      ; Set HDMA channel #4,5,6,7
;-----------------------------------------------------------------------
		RTS
;
;=============== Rotation screen =======================================
Perspective200
		LDX	  <matrix_A+0
		LDY	  <matrix_A+1
		STX	  !Rotation_matrix+0
		STY	  !Rotation_matrix+0  ; Set rotation matrix A
		STX	  !Rotation_matrix+3
		STY	  !Rotation_matrix+3  ; Set rotation matrix D
;
		LDX	  <matrix_B+0
		LDY	  <matrix_B+1
		STX	  !Rotation_matrix+1
		STY	  !Rotation_matrix+1  ; Set rotation matrix B
;
		LDX	  <matrix_C+0
		LDY	  <matrix_C+1
		STX	  !Rotation_matrix+2
		STY	  !Rotation_matrix+2  ; Set rotation matrix C
;-----------------------------------------------------------------------
Perspective300	LDA	  <window_flag
		CMP	  #02H
		BEQ	  Perspective310
;-----------------------------------------------------------------------
		LDA	  #11110000B
		TRB	  <HDMA_switch	      ; Reset HDMA channel #4,5,6,7
Perspective310	RTS
;
;************************************************************************
;*		 Car character data write				*
;************************************************************************
;
		MEM16
		IDX8
Write_character
		PHP
		REP	  #00100000B	      ; Memory 16 bit mode
		SEP	  #00010000B	      ; Index 8 bit mode
		LDY	  <chrwte_status      ; chrwte_status enable ?
		BEQ	  Write_char900	      ; no.
;
;=============== Initialize ============================================
Write_char100
		LDX	  #10000000B
		STX	  !Screen_step	      ; Set inc. mode High +1
		LDA	  #1801H
		STA	  !DMA_0+0	      ; Set DMA ctrl & B address
;
;=============== Write character main ==================================
Write_char200
		LDX	  #00H
Write_char210	PHY
		LDA	  !chrdat_address+0,X
		STA	  !DMA_0+2	      ; Set DMA A address
		LDY	  !chrdat_bank,X
		STY	  !DMA_0+4	      ; Set DMA A address bank
;-----------------------------------------------------------------------
		LDA	  !chrwte_address,X
		STA	  !Screen_address     ; Set VRAM address
		LDA	  !chrwte_length,X
		STA	  !DMA_0+5	      ; Set lengt
		LDY	  #00000001B
		STY	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		LDA	  !chrwte_address,X
		CLC
		ADC	  #0100H
		STA	  !Screen_address     ; Set VRAM address
		LDA	  !chrwte_length,X
		STA	  !DMA_0+5	      ; Set lengt
		STY	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		INX
		INX
		PLY
		DEY
		BNE	  Write_char210
;
;=======================================================================
Write_char900
		STY	  <chrwte_status      ; Clear chrwte_status
		PLP
		RTS
;
;************************************************************************
;*		 Set window						*
;************************************************************************
;
		MEM16
		IDX8
Set_window
		REP	  #00100000B	      ; Memory 16 bit mode
		LDX	  <window_flag	      ; window on ?
		BEQ	  Set_window300	      ; no.
		DEX			      ; message window ?
		BNE	  Set_window200	      ; yes.
;
;=============== Color window on =======================================
Set_window100
		LDA	  <window_address
		STA	  !DMA_2+2	      ; Set DMA A address
		LDA	  !shadow_address
		STA	  !window_table+13H   ; Set my car shadow data address
		LDA	  <window_main
		STA	  !Through_window     ; Set window main/sub
		LDX	  <window_color_sw
		STX	  !Window_switch      ; Set window color_add switch
		LDA	  <window_control+0
		STA	  !Window_control+0
		LDX	  <window_control+2
		STX	  !Window_control+2
;-----------------------------------------------------------------------
		MEM8
		SEP	  #00110000B	      ; Memory,Index 8 bit mode
		LDA	  #00000100B
		TSB	  <HDMA_switch	      ; Set HDMA channel #2
		RTS
;
;=============== Message window on =====================================
Set_window200
		MEM16
		LDA	  <window_main
		STA	  !Through_window     ; Set window main/sub
		LDX	  <window_color_sw
		STX	  !Window_switch      ; Set window color_add switch
		LDA	  <window_control+0
		STA	  !Window_control+0
		LDX	  <window_control+2
		STX	  !Window_control+2
;-----------------------------------------------------------------------
		MEM8
		SEP	  #00110000B	      ; Memory,Index 8 bit mode
		RTS
;
;=============== Window off ============================================
Set_window300
		MEM16
		STZ	  !Through_window     ; Clear window main/sub
		LDX	  <window_color_sw
		STX	  !Window_switch      ; Set window color_add switch
;-----------------------------------------------------------------------
		MEM8
		SEP	  #00110000B	      ; Memory,Index 8 bit mode
		LDA	  #00000100B
		TRB	  <HDMA_switch	      ; Reset channel #2
		RTS
;
;************************************************************************
;*		 Write meter ( mode 1 BG3 )				*
;************************************************************************
;
		MEM8
		IDX16
Write_meter
		REP	  #00010000B	      ; Index 16 bit mode
		LDA	  <meter_switch	      ; display meter ?
		BEQ	  Write_meter190      ; no.
		CMP	  #00000100B	      ; normal write ?
		BNE	  Write_meter200      ; no.
;
;=============== Write meter main ( normal ) ===========================
Write_meter100
		STZ	  !Screen_step	      ; Set auto inc.
		LDX	  #7456H
		STX	  !Screen_address     ; Set write address
;-----------------------------------------------------------------------
		LDX	  #1800H
		STX	  !DMA_0+0	      ; Set DMA ctrl & B address
		LDX	  #meter_buffer+16H
		STX	  !DMA_0+2	      ; Set DMA A address
		STZ	  !DMA_0+4	      ; Set DMA A bank
		LDX	  #0045H
		STX	  !DMA_0+5	      ; Set DMA data length
		LDA	  #00000001B
		STA	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		LDA	  #10000000B
		STA	  !Screen_step	      ; Set inc. mode High +1
		LDX	  #74A7H
		STX	  !Screen_address     ; Set write address
		LDX	  !safe_rank_char
		STX	  !Screen_write
;-----------------------------------------------------------------------
Write_meter190	SEP	  #00110000B	      ; Memory,Index 8 bit mode
		RTS
;
;=============== Write score ( for display time mode ) =================
Write_meter200
		STZ	  !Screen_step	      ; Set auto inc.
		LDX	  #7440H
		STX	  !Screen_address     ; Set write address
;-----------------------------------------------------------------------
		LDX	  #1800H
		STX	  !DMA_0+0	      ; Set DMA ctrl & B address
		LDX	  #meter_buffer
		STX	  !DMA_0+2	      ; Set DMA A address
		STZ	  !DMA_0+4	      ; Set DMA A bank
		LDX	  #0080H
		STX	  !DMA_0+5	      ; Set DMA data length
		LDA	  #00000001B
		STA	  !DMA_burst	      ; Start DMA channel #0
		BRA	  Write_meter190
;
;************************************************************************
;*		 Write crater						*
;************************************************************************
;
		MEM16
		IDX8
Write_crater
		REP	  #00100000B	      ; Memory 16 bit mode
		LDX	  <crater_wteflg
		BEQ	  Write_crater999
;
;=============== Write crater main =====================================
Write_crater100
		LDX	  #00000000B
		STX	  <crater_wteflg      ; Reset crater write flag
		STX	  !Screen_step	      ; Set auto inc. low +1
;-----------------------------------------------------------------------
		LDA	  !crater_table+00H
		STA	  !Screen_address     ; Set crater address 1
		LDX	  !crater_table+02H
		STX	  !Screen_write
		LDX	  !crater_table+03H
		STX	  !Screen_write
;-----------------------------------------------------------------------
		LDA	  !crater_table+04H
		STA	  !Screen_address     ; Set crater address 2
		LDX	  !crater_table+06H
		STX	  !Screen_write
		LDX	  !crater_table+07H
		STX	  !Screen_write
		LDX	  !crater_table+08H
		STX	  !Screen_write
		LDX	  !crater_table+09H
		STX	  !Screen_write
;-----------------------------------------------------------------------
		LDA	  !crater_table+0AH
		STA	  !Screen_address     ; Set crater address 3
		LDX	  !crater_table+0CH
		STX	  !Screen_write
		LDX	  !crater_table+0DH
		STX	  !Screen_write
		LDX	  !crater_table+0EH
		STX	  !Screen_write
		LDX	  !crater_table+0FH
		STX	  !Screen_write
;-----------------------------------------------------------------------
		LDA	  !crater_table+10H
		STA	  !Screen_address     ; Set crater address 4
		LDX	  !crater_table+12H
		STX	  !Screen_write
		LDX	  !crater_table+13H
		STX	  !Screen_write
;=======================================================================
Write_crater999
		SEP	  #00110000B	      ; Memory,Index 8 bit mode
		RTS
;
;************************************************************************
;*		 Write data to VRAM ( mode 1 screen )			*
;************************************************************************
;
		MEM16
		IDX8
Write_VRAM
		PHP
		REP	  #00100000B	      ; memory 16 bit mode
		SEP	  #00010000B	      ; index 8 bit mode
;-----------------------------------------------------------------------
		LDX	  <VRAMbuf_pointer    ; data available ?
		BEQ	  Write_VRAM_220      ; no.
		BMI	  Write_attribute     ; if ( attribute change )
;
;=============== Register initialize ===================================
Write_VRAM_100
		LDY	  #10000000B
		STY	  !Screen_step	      ; Set address inc. high +1
		LDA	  #1801H
		STA	  !DMA_0+0	      ; Set DMA ctrl & B address
;
;=============== VRAM write main =======================================
Write_VRAM_200
		LDY	  !VRAMbuf_offset-1,X
		LDA	  !VRAMwte_buffer+0,Y
		STA	  !Screen_address     ; Set write address
		LDA	  !VRAMwte_buffer+2,Y
		STA	  !DMA_0+2	      ; Set DMA A address
		LDA	  !VRAMwte_buffer+4,Y
		STA	  !DMA_0+4	      ; Set DMA A bank
		LDA	  !VRAMwte_buffer+6,Y
		STA	  !DMA_0+5	      ; Set DMA data length
		LDY	  #00000001B	      ; DMA trigger data
		STY	  !DMA_burst	      ; Start DMA channel #0
		DEX
		BNE	  Write_VRAM_200
;-----------------------------------------------------------------------
Write_VRAM_210	STX	  <VRAMbuf_pointer    ; Clear VRAM buffer pointer
Write_VRAM_220	PLP
		RTS
;
;=======================================================================
VRAMbuf_offset	BYTE	  00H,08H,10H,18H,20H,28H,30H,38H
;
;************************************************************************
;*		 Write BG attribute data				*
;************************************************************************
;
		MEM16
		IDX8
Write_attribute
		TXA
		AND	  #01111111B
		TAX			      ; IX = data pointer
;
;=============== Register initialize ===================================
Write_attrib100
		LDY	  #10000000B
		STY	  !Screen_step	      ; Set address inc. high +1
		LDA	  #1908H
		STA	  !DMA_0+0	      ; Set DMA ctrl & B address
		STZ	  !DMA_0+2
		STZ	  !DMA_0+3	      ; Set DMA A address and bank
;
;=============== VRAM write main =======================================
Write_attrib200
		LDY	  !VRAMbuf_offset2-1,X
		LDA	  !VRAMwte_buffer+0,Y
		STA	  !Screen_address     ; Set write address
		LDA	  !VRAMwte_buffer+2,Y
		AND	  #00FFH
		STA	  !DMA_0+5	      ; Set DMA data length
		LDA	  !VRAMwte_buffer+3,Y
		STA	  <00H		      ; Set attribute data
		LDY	  #00000001B	      ; DMA trigger data
		STY	  !DMA_burst	      ; Start DMA channel #0
		DEX
		BNE	  Write_attrib200
;-----------------------------------------------------------------------
		STX	  <VRAMbuf_pointer    ; Clear VRAM buffer pointer
		PLP
		RTS
;
;=======================================================================
VRAMbuf_offset2 BYTE	  00H,04H,08H,0CH,10H,14H,18H,1CH
;
;************************************************************************
;*		 Pert mode change					*
;************************************************************************
;
		MEM8
		IDX8
Mode_change
		LDA	  <part_flag	      ; part mode change ?
		BEQ	  Mode_change300      ; no.
		DEC	  A		      ; start demo ?
		BNE	  Mode_change200      ; yes.
;
;=============== Part mode change ( game play ) ========================
Mode_change100
		LDA	  #00001001B	      ; BG mode 1 / BG3 prio.
		STA	  !Screen_size	      ; Set BG mode 1
		LDA	  #00010011B
		EOR	  <meter_switch
		STA	  !Through_screen     ; display BG1,BG2,BG3,OBJ
;-----------------------------------------------------------------------
		LDA	  !meter_addsub
		STA	  !2131H	      ; Color add Back,BG1,BG2
		LDA	  #11100000B
		STA	  !2132H	      ; Reset add color
;-----------------------------------------------------------------------
		LDA	  #00001010B
		TSB	  <HDMA_switch	      ; Set HDMA channel #1,#3
		RTS
;
;=============== Part mode change ( start demo ) =======================
Mode_change200
		LDA	  #00001001B	      ; BG mode 1 / BG3 prio.
		STA	  !Screen_size	      ; Set BG mode 1
		LDA	  #00010011B
		STA	  !Through_screen     ; display BG1,BG2,OBJ
;-----------------------------------------------------------------------
		LDA	  #00000010B
		TSB	  <HDMA_switch	      ; Set HDMA channel #1
		LDA	  #00001000B
		TRB	  <HDMA_switch	      ; Reset HDMA channel #3
		BRA	  Mode_change310
;
;=============== Not mode change =======================================
Mode_change300
		LDA	  #00001010B
		TRB	  <HDMA_switch	      ; Reset HDMA channel #1,#3
;-----------------------------------------------------------------------
Mode_change310	LDA	  <color_add_sw
		STA	  !2131H	      ; Set color add/sub switch
		LDA	  !const_color_R
		ORA	  #00100000B
		STA	  !2132H	      ; Set constant color red
		LDA	  !const_color_G
		ORA	  #01000000B
		STA	  !2132H	      ; Set constant color green
		LDA	  !const_color_B
		ORA	  #10000000B
		STA	  !2132H	      ; Set constant color blue
		RTS
;
;************************************************************************
;*		 Set IRQ timer ( set meter color )			*
;************************************************************************
;
		MEM8
		IDX8
Set_IRQ
		LDA	  <part_flag	      ; part mode change ?
		BEQ	  Set_IRQ300	      ; no.
		DEC	  A		      ; start demo ?
		BNE	  Set_IRQ200	      ; yes.
;
;=============== Set timer parameter ( game play ) =====================
Set_IRQ100
		MEM16
		REP	  #00100000B	      ; Memory 16 bit mode
;-----------------------------------------------------------------------
		LDA	  #00B0H
		STA	  !4207H	      ; Set H count timer
		LDA	  #0012H
		STA	  !4209H	      ; Set V count timer
		LDX	  #10110001B
		STX	  !4200H	      ; Enable timer
;-----------------------------------------------------------------------
		LDA	  #IRQ_routine1
		STA	  <IRQ_pointer	      ; Set IRQ pointer
;-----------------------------------------------------------------------
		SEP	  #00100000B	      ; memory 8 bit mode
		RTS
;
;=============== Set timer parameter ( start demo ) ====================
Set_IRQ200
		MEM16
		REP	  #00100000B	      ; Memory 16 bit mode
;-----------------------------------------------------------------------
		LDA	  #00C0H
		STA	  !4207H	      ; Set H count timer
		LDA	  <vertical_timer
		STA	  !4209H	      ; Set V count timer
		LDX	  #10110001B
		STX	  !4200H	      ; Enable timer
;-----------------------------------------------------------------------
		LDA	  #IRQ_routine5
		STA	  <IRQ_pointer	      ; Set IRQ pointer
;-----------------------------------------------------------------------
		SEP	  #00100000B	      ; memory 8 bit mode
		RTS
;
;=============== Hardware timer disable ================================
Set_IRQ300
		MEM8
		LDA	  #10000001B
		STA	  !4200H	      ; Disable timer
		RTS
;
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;\\\\\\\\\\\\\\\ IRQ routines \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;************************************************************************
;*		 IRQ routine entry					*
;************************************************************************
;
		MEM8
		IDX16
IRQ_entry
		SEP	  #00100000B	      ; Memory 8 bit mode
		REP	  #00010000B	      ; Index 16 bit mode
		PHA
		PHX
		PHB
		LDA	  #00H
		PHA
		PLB
;-----------------------------------------------------------------------
		LDA	  !Timer_status	      ; Clear IRQ flag
		JMP	  (!IRQ_pointer)
;
;=============== IRQ exit ==============================================
IRQ_exit
		PLB
		PLX
		PLA
		RTI
;
;************************************************************************
;*		 IRQ routine 1 ( change meter color 1 )			*
;************************************************************************
;
		MEM8
		IDX16
IRQ_routine1
		BIT	  !Blank_status	      ; H blank ?
		BVC	  IRQ_routine1	      ; no.
;-----------------------------------------------------------------------
		LDA	  !meter_color_R
		STA	  !2132H	      ; Set add color red
		LDA	  !meter_color_G
		STA	  !2132H	      ; Set add color green
		LDA	  !meter_color_B
		STA	  !2132H	      ; Set add color blue
;-----------------------------------------------------------------------
		LDX	  #001CH
		STX	  !4209H	      ; Set V count timer low
		LDX	  #IRQ_routine2
		STX	  <IRQ_pointer	      ; Set IRQ pointer
;-----------------------------------------------------------------------
		PLB
		PLX
		PLA
		RTI
;
;************************************************************************
;*		 IRQ routine 2 ( change gradation mode )		*
;************************************************************************
;
		MEM8
		IDX16
IRQ_routine2
		BIT	  !Blank_status	      ; H blank ?
		BVC	  IRQ_routine2	      ; no.
;-----------------------------------------------------------------------
		LDA	  <color_addsub
		STA	  !2131H	      ; color sub Back,BG1,BG2
		LDA	  #11100000B
		STA	  !2132H	      ; Reset add color
;-----------------------------------------------------------------------
		LDX	  #002FH
		STX	  !4209H	      ; Set V count timer low
		LDX	  #IRQ_routine3
		STX	  <IRQ_pointer	      ; Set IRQ pointer
;-----------------------------------------------------------------------
		PLB
		PLX
		PLA
		RTI
;
;************************************************************************
;*		 IRQ routine 3 ( change screen mode )			*
;************************************************************************
;
		MEM8
		IDX16
IRQ_routine3
		LDA	  #00000111B	      ; Acc = BG mode 7
IRQ_routine3_1	BIT	  !Blank_status	      ; H blank ?
		BVC	  IRQ_routine3_1      ; no.
;-----------------------------------------------------------------------
		STA	  !Screen_size	      ; Set BG mode 7
;;;;		LDA	  #00010001B
;;;;		STA	  >Through_screen     ; display BG1,OBJ
;-----------------------------------------------------------------------
		LDX	  #0056H
		STX	  !4209H	      ; Set V count timer low
		LDX	  #IRQ_routine4
		STX	  <IRQ_pointer	      ; Set IRQ pointer
;-----------------------------------------------------------------------
		PLB
		PLX
		PLA
		RTI
;
;************************************************************************
;*		 IRQ routine 4 ( Set my car air )			*
;************************************************************************
;
		MEM8
		IDX16
IRQ_routine4
		BIT	  !Blank_status	      ; H blank ?
		BVC	  IRQ_routine4	      ; no.
;-----------------------------------------------------------------------
		LDA	  <spot_switch
		STA	  !2131H	      ; color sub BG1
		LDA	  #11100000B
		STA	  !2132H	      ; Reset add color
		LDA	  !spot_color_B
		STA	  !2132H	      ; Set add color
;-----------------------------------------------------------------------
		LDX	  #IRQ_exit
		STX	  <IRQ_pointer	      ; Set IRQ pointer
;-----------------------------------------------------------------------
		PLB
		PLX
		PLA
		RTI
;
;************************************************************************
;*		 IRQ routine 5 ( change screen mode )			*
;************************************************************************
;
		MEM8
		IDX16
IRQ_routine5
		LDA	  #00000111B	      ; Acc = BG mode 7
IRQ_routine5_1	BIT	  !Blank_status	      ; H blank ?
		BVC	  IRQ_routine5_1      ; no.
;-----------------------------------------------------------------------
		STA	  !Screen_size	      ; Set BG mode 7
		LDA	  #00010001B
		STA	  !Through_screen     ; display BG1,OBJ
;-----------------------------------------------------------------------
		LDX	  #IRQ_exit
		STX	  <IRQ_pointer	      ; Set IRQ pointer
;-----------------------------------------------------------------------
		PLB
		PLX
		PLA
		RTI
;
;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;\\\\\\\\\\\\\\\  Utility routines \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
;************************************************************************
;*		 Clear OAM						*
;************************************************************************
;
		MEM16
		IDX16
Clear_OAM
		PHP
		REP	  #00110000B	      ; Memory,Index 16 bit mode
;-----------------------------------------------------------------------
		LDA	  #8080H
		STA	  !OAM_main+0
		STZ	  !OAM_main+2
;
		LDA	  #512-4-1	      ; Acc = number of bytes
		LDX	  #OAM_main+0	      ; IX = source address
		LDY	  #OAM_main+4	      ; IY = destination address
		MVN	  #00H,#00H		; block move
;-----------------------------------------------------------------------
		LDA	  #0FFFFH
		STA	  !OAM_sub+0
;
		LDA	  #32-2-1	      ; Acc = number of bytes
		LDX	  #OAM_sub+0	      ; IX = source address
		LDY	  #OAM_sub+2	      ; IY = destination address
		MVN	  #00H,#00H	      ; block move
;-----------------------------------------------------------------------
		STZ	  <OAM_mainptr	      ; Clear OAM main pointer
		MEM8
		SEP	  #00100000B	      ; Memory 8 bit mode
		STZ	  <OAM_subptr	      ; Clear OAM sub pointer
		LDA	  #00000011B
		STA	  <OAM_submask	      ; Initial OAM sub mask pattern
;-----------------------------------------------------------------------
		PLP
		RTS
;
;************************************************************************
;*		 Start transfer DMA					*
;************************************************************************
;
		MEM16
		IDX16
Start_DMA
		PHP
		REP	  #00110000B	      ; Memory,Index 16 bit mode
		PHY
		STA	  <temp_pointer	      ; Set DMA parameter address
;-----------------------------------------------------------------------
		MEM8
		IDX8
		SEP	  #00110000B	      ; Memory,Index 8 bit mode
		LDY	  #06H
Start_DMA_10	LDA	  (<temp_pointer),Y
		STA	  !DMA_0,Y	      ; Set DMA parameter
		DEY
		BPL	  Start_DMA_10
;-----------------------------------------------------------------------
		LDA	  #00000001B
		STA	  !DMA_burst	      ; Start DMA channel #0
;-----------------------------------------------------------------------
		IDX16
		REP	  #00010000B	      ; Index 16 bit mode
		PLY
		PLP			      ; Rsetore mode
		RTS
;
;************************************************************************
;*		 Return subroutine long					*
;************************************************************************
;
Return_long	NOP
		RTL
;
;************************************************************************
;*		Software Specification					*
;************************************************************************
;
		ORG	  0FFC0H
;
		ASCII	  'F-ZERO                '
		BYTE	  02H		      ; Cartridge Type
		BYTE	  09H		      ; ROM Size
		BYTE	  01H		      ; RAM Size
		BYTE	  02H,01H	      ; Maker Code
		BYTE	  00H		      ; Version No.
		WORD	  0FFFFH	      ; ComplementCheck
		WORD	  00000H	      ; Check Sum

;************************************************************************
;*		 Interrupt vector					*
;************************************************************************
;
;=============== native mode vector ====================================

		WORD	  0
		WORD	  0
		WORD	  not_use	      ; COP
		WORD	  not_use	      ; BRK
		WORD	  not_use	      ; Abort
		WORD	  NMI_entry	      ; NMI
		WORD	  0FFFFH	      ; ( Reserved )
		WORD	  IRQ_entry	      ; IRQ
;
;=============== emulation mode vector =================================

		WORD	  0
		WORD	  0
		WORD	  not_use	      ; COP
		WORD	  0FFFFH	      ; ( reserved )
		WORD	  not_use	      ; Abort
		WORD	  not_use	      ; NMI
		WORD	  Program_entry	      ; Reset
		WORD	  not_use	      ; IRQ/BRK
;
		END
