;************************************************************************
;*	    Super Famicom console driver  version 1.00			*
;*		    Programmed by Y.Nishida				*
;*						[ Aug.26, 1991 ]	*
;************************************************************************

		native
		extend

		include		PPUregs.h
		include		CPUregs.h
		include		sfxdos.h

CON_Driver	sect		rel
SFXDOS		group		CON_Driver

		dpage		DOS_variable

;=============== Cross Reference ========================================

		extern		Input_Keyboard
		extern		ASCII_char_data

;=============== Cross Definition =======================================

		global		Init_CON_Driver
		global		Input_Console
		global		Output_Console
		global		Input_String
		global		Print_String
		global		CON_Driver_NMI

;************************************************************************
;*	Initialize console driver					*
;*									*
;************************************************************************

		mem8
		idx16
Init_CON_Driver
		rep		#00010000B		; Index 16 bit mode
;------------------------------------------------------------------------
		ldx		#0000110100100000B
		stx		<space_character
		stz		<escape_command
;------------------------------------------------------------------------
		lda		#11001111B
		sta		cursor_flags		; Cursor display mode
		lda		#02H
		sta		<cursor_posx		; Set cursor home position x
		inc		a
		sta		<cursor_posy		; Set cursor home position y
;------------------------------------------------------------------------
		ldx		#00C4H
		stx		<cursor_addr		; Set cursor position VRAM address
		stx		<cursor_point		; Set cursor display VRAM address
;------------------------------------------------------------------------
		lda		#10000000B
		sta		Screen_contrast		; Blank screen
		jsr		Clear_Screen		; Clear Text VRAM emulation buffer
		jsr		Screen_initial		; Initialize BG screen
		jsr		Char_initial		; Initialize BG character
		jsr		Color_initial		; Initialize color palette
		lda		#00001111B
		sta		Screen_contrast		; Display screen
		rts

;************************************************************************
;*	Clear Text Video RAM emulation buffer				*
;*									*
;************************************************************************

		mem8
		idx16
Clear_Screen
		phb
		mem16
		rep		#00110000B		; Memory,Index 16 bit mode
;------------------------------------------------------------------------
		lda		<space_character
		sta		>Text_VRAM
		ldx		#(Text_VRAM&0FFFFH)+0
		ldy		#(Text_VRAM&0FFFFH)+2
		lda		#0800H-3
		mvn		#bank Text_VRAM,#bank Text_VRAM
;------------------------------------------------------------------------
		plb
		rts

;************************************************************************
;*	Move cursor left						*
;*									*
;************************************************************************

		mem8
Cursor_Left
		dec		<cursor_posx
		lda		<cursor_posx
		cmp		#1
		beq		Left_over$
		jmp		Locate_Cursor_2
;------------------------------------------------------------------------
Left_over$	lda		#29
		sta		<cursor_posx
		jmp		Cursor_Up

;************************************************************************
;*	Move cursor right						*
;*									*
;************************************************************************

		mem8
Cursor_Right
		inc		<cursor_posx
		lda		<cursor_posx
		cmp		#30
		beq		Right_over$
		jmp		Locate_Cursor_2
;------------------------------------------------------------------------
Right_over$	lda		#2
		sta		<cursor_posx
		jmp		Cursor_Down

;************************************************************************
;*	Move cursor up							*
;*									*
;************************************************************************

		mem8
Cursor_Up
		lda		<cursor_posy
		cmp		#3
		beq		Top_over$
		dec		<cursor_posy
		jmp		Locate_Cursor_2
;------------------------------------------------------------------------
Top_over$	jsr		Locate_Cursor_2
		mem16
		lda		#0003H

;************************************************************************
;*	Insert Line							*
;*									*
;************************************************************************

		mem16
		idx16
Insert_Line
		phb
		rep		#00110000B		; Memory,Index 16 bit mode
;------------------------------------------------------------------------
		tax
		lda		#1000000000000000B
		tsb		<cursor_point		; Cursor blink routine disable
;------------------------------------------------------------------------
		txa
		and		#001FH
		xba
		lsr		a
		lsr		a
		sta		<work0			; work0 = insert address
		sec
		lda		#07BFH
		sbc		<work0
		ldx		#(Text_VRAM&0FFFFH)+07BFH
		ldy		#(Text_VRAM&0FFFFH)+07FFH
		mvp		#bank Text_VRAM,#bank Text_VRAM
;------------------------------------------------------------------------
		ldx		#Text_VRAM&0FFFFH
		txa
		clc
		adc		<work0
		tay
		lda		#003FH
		mvn		#bank Text_VRAM,#bank Text_VRAM
;------------------------------------------------------------------------
		clc
		lda		<cursor_point
		adc		#8040H
		sta		<cursor_point
;------------------------------------------------------------------------
		plb
		rts

;************************************************************************
;*	Move cursor down						*
;*									*
;************************************************************************

		mem8
Cursor_Down
		lda		<cursor_posy
		cmp		#26
		beq		Bottom_over$
		inc		<cursor_posy
		jmp		Locate_Cursor_2
;------------------------------------------------------------------------
Bottom_over$	jsr		Locate_Cursor_2
		mem16
		lda		#0003H

;************************************************************************
;*	Delete Line							*
;*									*
;************************************************************************

		mem16
		idx16
Delete_Line
		phb
		rep		#00110000B		; Memory,Index 16 bit mode
;------------------------------------------------------------------------
		tax
		lda		#1000000000000000B
		tsb		<cursor_point		; Cursor blink routine disable
;------------------------------------------------------------------------
		txa
		and		#001FH
		xba
		lsr		a
		lsr		a
		sta		<work0			; Delete address
		adc		#Text_VRAM&0FFFFH
		tay
		adc		#0040H
		tax
		sec
		lda		#07BFH		
		sbc		<work0
		mvn		#bank Text_VRAM,#bank Text_VRAM
;------------------------------------------------------------------------
		sec
		lda		<cursor_point
		sbc		#8040H
		sta		<cursor_point
;------------------------------------------------------------------------
		plb
		rts

;************************************************************************
;*	Locate cursor							*
;*									*
;************************************************************************

		mem16
Locate_Cursor
		rep		#00100000B		; Memory 16 bit mode
		and		#1F1FH
		sta		<cursor_posx		; Set cursor position
		bra		Locate_Cursor_3
;------------------------------------------------------------------------
Locate_Cursor_2	rep		#00100000B		; Memory 16 bit mode
		lda		<cursor_posx
;------------------------------------------------------------------------
Locate_Cursor_3	and		#0FF00H				
		lsr		a
		lsr		a
		sta		<work0
		lda		<cursor_posx
		and		#00FFH
		asl		a
		ora		<work0		
		sta		<cursor_addr
		rts

;************************************************************************
;*	Input Console							*
;*									*
;************************************************************************

		mem8
		idx8
Input_Console
		lda		<cursor_flags
		and		#10000000B
		ora		#01001111B
		sta		<cursor_flags		; Cursor on
		jmp		Input_Keyboard

;************************************************************************
;*	Output Console							*
;*									*
;************************************************************************

		mem8
		idx8
Output_Console
		tax
		lda		#01000000B
		trb		<cursor_flags		; Cursor off
		lda		<escape_command
		beq		Skip$
		jmp		Escape_Sequence
;--------------------------------------------------------------------------
Skip$		cpx		#20H
		bcc		Control_code
		cpx		#7FH
		bcc		Output_Con_100
		ldx		#20H

;=============== Put character into VRAM ================================
Output_Con_100
		lda		<character_color
		xba
		txa
		rep		#00110000B
		ldx		<cursor_addr
		sta		>Text_VRAM,x
		sep		#00110000B
		jmp		Cursor_Right

;************************************************************************
;*	Put control code						*
;*									*
;************************************************************************

		mem8
		idx8
Control_code
		txa
		asl		a
		tax
		jmp		(Jump_table$,x)
;------------------------------------------------------------------------
Jump_table$
		word		Putchar_exit		; 00H
		word		Putchar_exit		; 01H
		word		Putchar_exit		; 02H
		word		Putchar_exit		; 03H
		word		Putchar_exit		; 04H
		word		Putchar_exit		; 05H
		word		Putchar_exit		; 06H
		word		Putchar_exit		; 07H
		word		Back_Space		; 08H
		word		H_Tab			; 09H
		word		Cursor_Down		; 0AH
		word		Cursor_Home		; 0BH
		word		Clear			; 0CH
		word		Carriage_Return		; 0DH
		word		Putchar_exit		; 0EH
		word		Putchar_exit		; 0FH
		word		Putchar_exit		; 10H
		word		Putchar_exit		; 11H
		word		Putchar_exit		; 12H
		word		Putchar_exit		; 13H
		word		Putchar_exit		; 14H
		word		Putchar_exit		; 15H
		word		Putchar_exit		; 16H
		word		Putchar_exit		; 17H
		word		Putchar_exit		; 18H
		word		Putchar_exit		; 19H
		word		Putchar_exit		; 1AH
		word		Start_Escape		; 1BH
		word		Cursor_Right		; 1CH
		word		Cursor_Left		; 1DH
		word		Cursor_Up		; 1EH
		word		Cursor_Down		; 1FH
;------------------------------------------------------------------------
Start_Escape	sta		<escape_command
		stz		<escape_counter
Putchar_exit	rts

;=============== Carriage return ========================================
Carriage_Return
		lda		#2
		sta		<cursor_posx
		jmp		Locate_Cursor_2

;=============== Horizontal tabulation ==================================
H_Tab
		lda		<cursor_posx
		sec
		adc		#6
		and		#11111000B
		clc
		adc		#2
		cmp		#30
		bcc		Skip$
		lda		#29
Skip$		sta		<cursor_posx
		jmp		Locate_Cursor_2

;=============== Clear Text =============================================
Clear
		jsr		Clear_Screen
		sep		#00110000B		; Memory,Index 8 bit mode

;=============== Cursor Home ============================================
Cursor_Home
		lda		#02H
		sta		<cursor_posx
		inc		a
		sta		<cursor_posy
		jmp		Locate_Cursor_2

;=============== Back space =============================================
Back_Space
		jsr		Cursor_Left
		mem16
		rep		#00110000B		; Memory,Index 16 bit mode
		ldx		<cursor_addr
		lda		<space_character
		sta		>Text_VRAM,x
		rts

;************************************************************************
;*	Put ASCII 							*
;*									*
;************************************************************************

		mem8
Putascii
		cmp		#7FH
		bcs		Exit$
		cmp		#20H
		bcs		Skip$
		pha
		lda		#'^'
		jsr		Output_Console
		sep		#00110000B		; Memory,Index 8 bit mode
		pla
		ora		#01000000B
Skip$		jsr		Output_Console
		sep		#00110000B		; Memory,Index 8 bit mode
Exit$		rts

;************************************************************************
;*	Print String							*
;*									*
;************************************************************************

		mem8
		idx16
Print_String
		rep		#00010000B		; Index 16 bit mode
		tax
;------------------------------------------------------------------------
Repeat$		lda		0000H,x
		beq		Exit$
		phx
		sep		#00010000B		; Index 8 bit mode
		jsr		Output_Console
		sep		#00100000B		; Memory 8 bit mode
		rep		#00010000B		; Index 16 bit mode
		plx
		inx
		bra		Repeat$
Exit$		rts

;************************************************************************
;*	Input String							*
;*									*
;************************************************************************

		mem8
		idx8
Input_String
		stz		<Line_buffer+0	; Clear length of string

;=============== Input main loop ========================================
Input_String_10
		jsr		Input_Console
		cmp		#20H			; Control code ?
		bcc		Input_String_20		; yes.
		cmp		#7FH			; Delete code ?
		beq		Input_String_30		; yes.
		bcs		Input_String_10
;------------------------------------------------------------------------
Input_String_11	ldx		<Line_buffer+0
		cpx		#62			; Input buffer full ?
		beq		Input_String_10		; yes.
		inx
		sta		<Line_buffer,x
		stx		<Line_buffer
		jsr		Putascii
		bra		Input_String_10

;=============== Control code check =====================================
Input_String_20
		cmp		#0DH
		beq		Input_String_41
		cmp		#03H
		beq		Input_String_40
		cmp		#08H
		bne		Input_String_11

;=============== Delete character ( back space ) ========================
Input_String_30
		ldx		<Line_buffer
		beq		Input_String_10
;------------------------------------------------------------------------
		lda		<Line_buffer,x
		dex
		stx		<Line_buffer
		cmp		#20H
		bcs		Skip$
		lda		#08H
		jsr		Output_Console
		sep		#00110000B		; Memory,Index 8 bit mode
Skip$		lda		#08H
		jsr		Output_Console
		sep		#00110000B		; Memory,Index 8 bit mode
		bra		Input_String_10

;=============== Exit input =============================================
Input_String_40
		stz		<Line_buffer
		jsr		Putascii		; Print ^C
		lda		#0DH
;-----------------------------------------------------------------------
Input_String_41	jsr		Output_Console		; Carriage Return
		sep		#00110000B		; Memory,Index 8 bit mode
		ldx		<Line_buffer
		lda		#00H
		sta		<Line_buffer+1,x
		rts

;************************************************************************
;*	Escape sequence							*
;*									*
;************************************************************************

		mem8
		idx8
Escape_Sequence
		txa
		ldy		<escape_counter
		bne		Esc_Sequence_30

;=============== Check ESC sequence command =============================
Esc_Sequence_10
		ldx		#3
Repeat$		cmp		Command_table$,x
		beq		Esc_Sequence_20
		dex
		bpl		Repeat$
;------------------------------------------------------------------------
		stz		<escape_command
		rts
;------------------------------------------------------------------------
Command_table$	ascii		'CGDI'

;=============== Set ESC sequence command ===============================
Esc_Sequence_20
		txa
		asl		a
		inc		a
		sta		<escape_command

;=============== Jump command process ===================================
Esc_Sequence_30
		iny
		sty		<escape_counter
		ldx		<escape_command
		dex
		jmp		(Jump_table$,x)
;------------------------------------------------------------------------
Jump_table$	word		ESC_Color
		word		ESC_Locate
		word		ESC_Delete_Line
		word		ESC_Insert_Line

;************************************************************************
;*	Set text color							*
;************************************************************************

		mem8
		idx8
ESC_Color
		dey
		beq		Exit$
;------------------------------------------------------------------------
		sec
		sbc		#30H
		and		#00000011B
		asl		a
		asl		a
		sta		<work0
		lda		<character_color
		and		#11110011B
		ora		<work0
		sta		<character_color
		stz		<escape_command
Exit$		rts

;************************************************************************
;*	Locate cursor							*
;************************************************************************

		mem8
		idx8
ESC_Locate
		dey
		beq		First$
		dey
		beq		Second$
;------------------------------------------------------------------------
Third$		ldy		#24
		jsr		Set_position$
		clc
		adc		#03H
		xba
		lda		<escape_buffer
		stz		<escape_command
		jmp		Locate_Cursor
;------------------------------------------------------------------------
Second$		ldy		#28
		jsr		Set_position$
		inc		a
		inc		a
		sta		<escape_buffer
First$		rts
;------------------------------------------------------------------------
Set_position$	sty		<work0
		sec
		sbc		#20H
		bcs		Skip$
		lda		#0
		rts
Skip$		cmp		<work0
		bcc		Return$
		tya
		dec		a
Return$		rts

;************************************************************************
;*	Delete line							*
;************************************************************************

		mem8
ESC_Delete_Line
		stz		<escape_command
		lda		<cursor_posy
		jmp		Delete_Line

;************************************************************************
;*	Insert line							*
;************************************************************************

		mem8
ESC_Insert_Line
		stz		<escape_command
		lda		<cursor_posy
		jmp		Insert_Line

;************************************************************************
;*	BG screen initialize						*
;*									*
;************************************************************************

		mem8
		idx16
Screen_initial
		sep		#00100000B		; memory 8 bit mode
		rep		#00010000B		; Index 16 bit mode

;=============== PPU initialize =========================================
Screen_init_10
		stz		Screen_mode		; Set BG screen mode #0
		stz		Screen_mosaic		; Disable mosaic
		lda		#01111100B
		sta		BG_scrn_base+0		; Set BG1 screen base address
		lda		#00000111B
		sta		BG_char_base+0		; Set BG1 character base address
;------------------------------------------------------------------------
		lda		#00000001B
		sta		Through_screen+0	; Set through main
		stz		Through_screen+1	; Set through sub
		stz		Through_window+0	; Set window through main
		stz		Through_window+1	; Set window through sub
;------------------------------------------------------------------------
		stz		BG_scroll_H+0
		stz		BG_scroll_H+0		; Set BG1 scroll H
		stz		BG_scroll_V+0
		stz		BG_scroll_V+0		; Set BG1 scroll V
;------------------------------------------------------------------------
		stz		Window_control+0
		stz		Window_control+1
		stz		Window_control+2
;------------------------------------------------------------------------
		lda		#10000000B
		sta		VRAM_step		; Set VRAM step

;=============== BG1 screen initialize ==================================
Screen_init_20
		mem16
		rep		#00100000B		; Memory 16 bit mode
;------------------------------------------------------------------------
		lda		#7C00H
		sta		VRAM_address
		lda		#Screen_DMA
		jmp		DMA_Transfer

;=============== DMA parameters =========================================

Screen_DMA	byte		00000001B		; DMA control parameter
		byte		18H			; B bus address
		byte		low  Text_VRAM		; data address low
		byte		high Text_VRAM		; data address high
		byte		bank Text_VRAM		; data bank
		word		0800H			; data length

;************************************************************************
;*	BG character initialize						*
;*									*
;************************************************************************

		mem16
Char_initial
		rep		#00100000B		; memory 16 bit mode
;------------------------------------------------------------------------
		lda		#7800H
		sta		VRAM_address
		lda		#Character_DMA
		jmp		DMA_Transfer

;=============== DMA parameters =========================================

Character_DMA	byte		00000001B		; DMA control parameter
		byte		18H			; B bus address
		byte		low  ASCII_char_data	; data address low
		byte		high ASCII_char_data	; data address high
		byte		bank ASCII_char_data	; data bank
		word		0800H			; data length

;************************************************************************
;*	Initialize color palette					*
;*									*
;************************************************************************

		mem8
		idx8
Color_initial
		sep		#00110000B		; Memory,Index 8 bit mode
;------------------------------------------------------------------------
		lda		#00000010B
		sta		Window_color_sw		; Set color switch
		stz		Color_addsub_sw		; Set color add sub switch
		lda		#11100000B
		sta		Constant_color		; Set constant color
;------------------------------------------------------------------------
		stz		Color_address		; Set Color generator address
		mem16
		rep		#00100000B		; Memory 16 bit mode
		lda		#Color_DMA
		jmp		DMA_Transfer

;=============== DMA parameters ========================================

Color_DMA	byte		00000000B		; DMA control parameter
		byte		22H			; B bus address
		byte		low  Color_data		; data address low
		byte		high Color_data		; data address high
		byte		bank Color_data		; data bank
		word		0040H			; data length

;=============== Color data =============================================

Color_data	word		0,0000001111100000B,0,0
		word		0,0111111111100000B,0,0
		word		0,0000001111111111B,0,0
		word		0,0111111111111111B,0,0

		word		0,0,0000001111100000B,0
		word		0,0,0111111111100000B,0
		word		0,0,0000001111111111B,0
		word		0,0,0111111111111111B,0

;************************************************************************
;*	Transfer data by DMA channel #0					*
;*									*
;************************************************************************

		mem8
		idx8
DMA_Transfer
		sta		<work0			; Set Address of DMA parameter
		sep		#00110000B		; Memory,Index 8 bit mode
;------------------------------------------------------------------------
		ldy		#06H
Repeat$		lda		(<work0),y
		sta		DMA_channel0,y		; Set parameter to DMA #0
		dey
		bpl		Repeat$
;------------------------------------------------------------------------
		lda		#00000001B
		sta		MDMA_start		; Start DMA #0
		rts

;************************************************************************
;*	Console Driver NMI routine					*
;*									*
;************************************************************************

		mem8
		idx8
CON_Driver_NMI
		jsr		Cursor_Blink
		jsr		Text_Transfer
		rts

;************************************************************************
;*	Text transfer ( Text VRAM emulation )				*
;*									*
;************************************************************************

		mem16
		idx8
Text_Transfer
		rep		#00100000B		; Memory 16 bit mode
		ldx		#10000000B
		stx		VRAM_step		; Set VRAM auto inc mode
		lda		#7C00H
		sta		VRAM_address		; Set VRAM address
;------------------------------------------------------------------------
		lda		#1801H
		sta		DMA_channel0+0		; Set DMA control & B bus address
		lda		#Text_VRAM&0FFFFH
		sta		DMA_channel0+2		; Set A bus address
		ldx		#bank Text_VRAM
		stx		DMA_channel0+4		; Set A bus bank
		lda		#0800H
		sta		DMA_channel0+5		; Set number of bytes
		ldx		#00000001B
		stx		MDMA_start		; 
;------------------------------------------------------------------------
		sep		#00100000B		; Memory 8 bit mode
		rts

;************************************************************************
;*		Cursor blink						*
;************************************************************************

		mem8
		idx16
Cursor_Blink
		rep		#00010000B		; Index 16 bit mode
		ldx		<cursor_point
		bpl		Cursor_Blink_10
;------------------------------------------------------------------------
		sep		#00010000B		; Index 8 bit mode
		rts

;=============== Check cursor move ======================================
Cursor_Blink_10
		lda		<cursor_flags
		and		#11000000B
		cmp		#11000000B		; Cursor on mode ?
		bne		Cursor_Blink_60		; no. ( clear cursor )
;------------------------------------------------------------------------
		lda		<cursor_flags
		bit		#00100000B		; Cursor display now ?
		bne		Cursor_Blink_30		; yes.

;=============== Cursor not display now =================================
Cursor_Blink_20
		cpx		<cursor_addr		; Cursor move ?
		beq		Check_counter$		; no.
;------------------------------------------------------------------------
Cursor_move$	lda		>Text_VRAM+1,x
		and		#11101111B
		sta		>Text_VRAM+1,x		; Cursor off
		ldx		<cursor_addr
		stx		<cursor_point
		bra		Cursor_Blink_40
;------------------------------------------------------------------------
Check_counter$	inc		a
		bit		#00001111B
		bne		Cursor_Blink_50
		bra		Cursor_Blink_40

;=============== Cursor display now =====================================
Cursor_Blink_30
		cpx		<cursor_addr		; Cursor move ?
		beq		Check_counter$		; no.
;------------------------------------------------------------------------
		lda		>Text_VRAM+1,x
		and		#11101111B
		sta		>Text_VRAM+1,x		; Cursor off
		ldx		<cursor_addr
		stx		<cursor_point
		bra		Cursor_Blink_40
;------------------------------------------------------------------------
Check_counter$	inc		a
		bit		#00011111B
		bne		Cursor_Blink_50
		bra		Cursor_Blink_60

;=============== Cursor display ========================================= 
Cursor_Blink_40
		lda		>Text_VRAM+1,x
		ora		#00010000B
		sta		>Text_VRAM+1,x		; Cursor on
		lda		#11100000B
;------------------------------------------------------------------------
Cursor_Blink_50	sta		<cursor_flags
		sep		#00010000B		; Index 8 bit mode
		rts

;=============== Clear cursor ===========================================
Cursor_Blink_60
		lda		>Text_VRAM+1,x
		and		#11101111B
		sta		>Text_VRAM+1,x		; Cursor off
;------------------------------------------------------------------------
		lda		<cursor_flags
		and		#11000000B
		sta		<cursor_flags
		sep		#00010000B		; Index 8 bit mode
		rts

		end
