;-----------------------------------------------------------------------------
; File name:	UKEX.S				Revised:	1999.03.11
; Revised by:	Ulf Ronald Andersson		Ported:		1991.03.22
; Released as:	FREEWARE			Version:	4.7
; File purpose:	Extend ALT-keys and ease user def'd keyboard loading
;-----------------------------------------------------------------------------
;
;	Revision history:
;
; Revision 4.0:	Re-edited for DEVPAC_2 compatibility, and to increase
; - " - 	efficiency, both on disk and in runtime RAM.
; - " - 	Extended to allow triple language keyboard swaps.
; - " - 	Enhanced with TOS independent TOS identification.
; - " - 	Enhanced with faster interrupt routines.
; - " - 	Enhanced to release <ALT> <CONTROL> combinations,
; - " - 	except for the 3 special commands shown below:
; - " -		XBRA protocol is now used for all vectors.
;
; Revision 4.1:	Deactivated ALT-tables are now default, ALT-CTRL-A activates
;
; Revision 4.2:	Improved method of cancelling command characters from buffers
; - " -		New method guarantees compatibility with ALL old TOS (pre 1.4)
; - " -		Tested error free under ST TOS 1.4, TOS 1.7 & KAOS 1.4.2.
; - " -		UKEX uses modern OS standard, should work under any newer TOS,
; - " -		but has problems with commands under TOS 2.06 & MultiTOS.
;
; Revision 4.3: Re-edited for DEVPAC_3 compatibility.
; - " - 	Stack handling improved for compatibility with latest TOS.
; - " -		UKEX now runs error_free under TOS 2.06 and MultiTOS.
; - " -		A new command is added to reload key tables without rebooting.
;
; Revision 4.4: Defaults settings & XBRA installation changed.
; - " - 	Defaults are altered to swedish layouts, with active ALT-keys.
; - " -		XBRA installation is altered  for MagiX compatibility.
;
; Revision 4.5: Command sequence changed to <ALT><CONTROL><R_SHIFT>.
; - " -		The etv_timer routine is now removed (faster system).
;
;
; Revision 4.6: Keyboard commands replaced by cookie interface
; - " -		The VBI routine is now removed (faster system).
;
; Revision 4.7:	Equipped with improved keyboard tables for the
; - " -		Swedish keyboards.
;-----------------------------------------------------------------------------
;	Cookie commands:
;
;  <A> Activates UKEX normal keyboard, or toggles ALT-handling.
;  <S> Swaps UKEX normal keyboard with ALT keyboard
;  <Q> Quits UKEX normal keyboard, to use BIOS keys.
;  <L> Load new UKEX keyboard tables from current directory.
;
;-----------------------------------------------------------------------------
;
	include	tos\URAn_SYS.S
	include	tos\URAn_DOS.S
	include	tos\URAn_XB.S
	include	tos\URAn_JAR.S
;
;-----------------------------------------------------------------------------
;
	TEXT
	opt	a+
	opt	o+
;
;-----------------------------------------------------------------------------
;
start:
	bra	install
;
;-----------------------------------------------------------------------------
;
	XB_define	nu_ikbd_vec,'UKEX'
	XB_donext_d	nu_ikbd_vec(pc)
UKEXcode:
	move	SR,-(sp)
	move.l	kb_iorec_p(pc),a0
	move	io_tail_ix(a0),d1	;tail index
	cmp	old_tail_ix(pc),d1	;test if changed
	beq.s	.return
	or	#$0700,SR
	move	io_tail_ix(a0),d1	;tail index
	move	d1,old_tail_ix		;save tail index at old_tail_ix
	cmp	io_head_ix(a0),d1
	beq.s	.return
	move.l	kbshift_p(pc),a1
	move.b	(a1),d2			;get kbshifts
	btst	#3,d2			;ALT ?
	beq.s	.return			;if 0, return
	move.l	io_buffer_p(a0),a2	;get address of io-buffer
	move	(a2,d1),d0		;get 1'st word for this key = key code
	and	#$7F,d0			;mask key code
	btst	#2,d2			;CONTROL ?
	bne.s	.return			;If so, skip translation
	move.l	ALT_vector(pc),a1	;get translation table
	tst.b	ALT_inhibit
	bne.s	.return
	and.b	#$13,d2			;test SHIFT l/r and CapsL
	beq.s	.goon			;if none go use 1'st ALT-table
	add	#128,a1			;set second table (ALT&SHIFT)
	and.b	#3,d2			;Shift pressed ?
	bne.s	.goon			;If so, go use 2'nd ALT-table
	add	#128,a1			;use third ALT-table (ALT&CAPS)
.goon:
	move.b	(a1,d0),d0		;translate
	beq.s	.return			;but leave NUL's untranslated
	move	d0,2(a2,d1)		;store char code
.return:
	move	(sp)+,SR
	rts
;
;-----------------------------------------------------------------------------
;
commander:
	move.l	(savptr).w,savptr_save
	move.l	sp,entry_sp_save
	lea	extra_stack_1,sp
	move.l	sp,(savptr).w
	lea	extra_stack_2,sp
	movem.l d0-d2/a0-a2,-(sp)
	bsr.s	commandsub
	movem.l (sp)+,d0-d2/a0-a2
	move.l	savptr_save,(savptr).w
	move.l	entry_sp_save,sp
	rts
;
;-----------------------------------------------------------------------------
;
commandsub:
	cmp	#'Q',d0
	beq.s	Q_command
	cmp	#'A',d0
	beq.s	A_command
	cmp	#'S',d0
	beq.s	S_command
	cmp	#'L',d0
	beq.s	L_command
	bra.s	no_command
;
;'A' reActivates normal tables (after using ROM or externals)
;If already active, toggles ALT handling off/on
A_command:
	lea	ALT_inhibit,a0
	tst.b	DEF_inhibit-ALT_inhibit(a0)
	bne.s	Activate
	tst.b	(a0)
	seq	(a0)
Activate:
	move.l	DEF_vector,a0
	xbios	Keytbl,(a0),128(a0),256(a0)
	sf	DEF_inhibit
	rts
;
;
Q_command: ;ESC Quits normal tables to use ROM (ALT tables remain as before)
	st	DEF_inhibit-kbd_comd(a0)
	xbios	Bioskeys
no_command:
	rts
;
;
L_command:
	move.l	#def_fname_s,def_fpath_p
	bsr	load_def_table
	move.l	#alt_fname_s,alt_fpath_p
	bsr	load_alt_table
	rts

;
;
S_command: ;'S' Swaps normal tables with ALT-tables
	lea	DEF_vector,a0
	lea	ALT_vector,a1
	move.l	(a1),d1
	move.l	(a0),(a1)
	move.l	d1,(a0)
	move.l d1,a0		;a0 -> new normal key table
	move.l	$76(a0),$00(a0)
	CLR	$76(a0)
	CLR.l	$78(a0)
	CLR.l	$7C(a0)
	CLR.b	$00(a0)
	move.l	$0F6(a0),$080(a0)
	CLR	$0F6(a0)
	CLR.l	$0F8(a0)
	CLR.l	$0FC(a0)
	CLR.b	$080(a0)
	move.l	$176(a0),$100(a0)
	CLR	$176(a0)
	CLR.l	$178(a0)
	CLR.l	$17C(a0)
	CLR.b	$100(a0)
;Here both tables have the normalized format, but the newly activated
;normal table may have holes after ALT-usage, so swap those codes
	move.l	DEF_vector,a0
	move.l	ALT_vector,a1
	move	#$180,d2
swapalt_l1:
	move.b	(a0)+,d1
	bne.s	swapalt_l2
	move.b	(a1),-(a0)
	move.b	d1,(a1)
	addq	#1,a0
swapalt_l2:
	addq	#1,a1
	dbra	d2,swapalt_l1
;Here both tables are normalized, with ALT-inhibiting NUL's swapped to ALT-table,
;but TOS won't give normalized key codes for all ALT-keys, so rearrange table
Rearr_ALT:
	move.l ALT_vector,a0		; rearrange ALT-Codes
	move	$00(a0),$76(a0)
	move.l	$02(a0),$78(a0)
	move.l	$06(a0),$7C(a0)
	move.l	$0A(a0),$00(a0)
	move	$080(a0),$0F6(a0)
	move.l	$082(a0),$0F8(a0)	; same for ALT SHIFT
	move.l	$086(a0),$0FC(a0)
	move.l	$08A(a0),$080(a0)
	move	$100(a0),$176(a0)
	move.l	$102(a0),$178(a0)	; same for ALT CAPS
	move.l	$106(a0),$17C(a0)
	move.l	$10A(a0),$100(a0)
	bra	Activate
;
;
load_def_table:
	gemdos	Fopen|_ind,def_fpath_p,!
	move	d0,handle
	bmi.s	.no_file
	gemdos	Fread,handle,#384,DEF_table
	gemdos	Fclose,handle
.no_file:
	tst.l	d0
	rts
;
;
load_alt_table:
	gemdos	Fopen|_ind,alt_fpath_p,!
	move	d0,handle
	bmi.s	.no_file
	gemdos	Fread,handle,#384,ALT_table
	gemdos	Fclose,handle
.no_file:
	rts
;
;
entry_sp_save:	dc.l	0	;for interrupt command handler
savptr_save:	dc.l	0	;for interrupt calls to XBIOS
keytbl_ptp:	dc.l	0	;-> table of 3 ptrs to keytables
kbshift_p:	dc.l	0	;-> OS variable for kbshift
DEF_vector:	dc.l	0	;-> Default UKEX keytables
ALT_vector:	dc.l	0	;-> Alternate UKEX keytables
kb_iorec_p:	dc.l	0	;-> keyboard iorec structure
old_tail_ix:	dc.w	-1
kbd_comd:	dc.w	0
DEF_inhibit:	dc.b	0	;Default is ON
ALT_inhibit:	dc.b	0	;Default is ON (Rev 4.4)
handle:	dc.w	0
;
def_fpath_p:	dc.l	def_fauto_s
def_fauto_s:
	dc.b	'A:\AUTO\'		;patched to real boot drive
def_fname_s:
	dc.b	'DEF*.KBD',NUL
	even
;
alt_fpath_p:	dc.l	alt_fauto_s
alt_fauto_s:
	dc.b	'A:\AUTO\'		;patched to real boot drive
alt_fname_s:
	dc.b	'ALT*.KBD',NUL
	even
;
;-----------------------------------------------------------------------------
;	Here lie the built-in keyboard tables of UKEX.
;
DEF_table:
	incbin	KBD_DEF\def_swe.kbd
;
ALT_table:
	incbin	KBD_DEF\alt_swe.kbd
;
;----------------------------------------------------------------------------
;
UKEX_cookie;
	dc.l	'UKEX'
	dc.w	0
	dc.w	$0407
	dc.w	$0407
	dc.l	commander
	dc.b	'QASL'
	dc.b	NUL
	even
;
;----------------------------------------------------------------------------
;	Resident cookie jar routines & data
;
	_uniref	reset_old_jar
	make	JAR_links
;
;-----------------------------------------------------------------------------
;	The resident program will end here,
;	but the two new stacks use this area.
;
extra_base	= *
		rsreset
		rs.b	256
extra_stack_1	= (*+__RS)
		rs.b	256
extra_stack_2:	= (*+__RS)
extra_size	= __RS
;
;	The following code only exists during installation,
;	since it is overlaid by the commander stacks.
;
install:
	move.l	4(sp),a5	;a5 -> basepage
	lea	pgm_len,a0
	lea	install,a1
	move.l	a1,d0
	sub.l	a5,d0		;* calculate length
	add.l	#extra_size,d0
	move.l	d0,(a0)
	move.l	(a0),d0
	add.l	#$1000,d0
	lea	(a5,d0.l),sp
	gemdos	Mshrink!_ind,#0,a5,d0
	gemdos	Cconws,initmess_s(pc)
;
	gemdos	Super,!
	move.l	d0,-(sp)
;
	lea	UKEX_cookie(pc),a0
	make_cookie	#'UKEX',a0
	bmi	error_exit
;
	move	(_bootdev).w,d1
	add	#'A',d1
	move.b	d1,def_fauto_s
	move.b	d1,alt_fauto_s
;
	gemdos	Super,()
;
	move.l	#def_fauto_s,def_fpath_p
	bsr	load_def_table
	bpl.s	.got_def_tab
	move.l	#def_fname_s,def_fpath_p
	bsr	load_def_table
.got_def_tab:
	move.l	#alt_fauto_s,alt_fpath_p
	bsr	load_alt_table
	bpl.s	.got_alt_tab
	move.l	#alt_fname_s,alt_fpath_p
	bsr	load_alt_table
.got_alt_tab:
	lea	DEF_vector,a1
	lea	DEF_table,a0
	move.l	a0,(a1)+
	lea	ALT_table,a0
	move.l	a0,(a1)
	bsr	Rearr_ALT
	xbios	Iorec,#1
	move.l	d0,kb_iorec_p
	xbios	Keytbl,?,?,?
	move.l	d0,keytbl_ptp
	bsr	Activate
;
	gemdos	Super,!
	move.l	d0,-(sp)
;
;*********; Here starts TOS identification/adaption
	move.l	(_sysbase).w,a0
	move.l	os_selfbeg_p(a0),a0
	move.l	$24(a0),a1	;->kbshift variable in modern TOS >= 1.2
	cmp	#$0102,2(a0)	;check OS version
	bhs.s	insta_OS
;this is an init of kbshift_p, valid for TOS <= TOS 1.02
	move.l	keytbl_ptp,a1
	subq	#1,a1		;NB: This assumes Kbshift stored at Keytbl-1.
;				;NB: All early TOS have Kbshift data there !!!
insta_OS:
	move.l	a1,kbshift_p
	gemdos	Super,()
;
	gemdos	Cconws,Activation_s(pc)
	xbios	Kbdvbase
	move.l	d0,a1		;* a1 = addr(kbdvbase)
	XB_install	nu_ikbd_vec,32(a1)
	gemdos	Ptermres,pgm_len(pc),#0
;
;
error_exit:
	move.l	d0,d7
	gemdos	Super,()
	lea	Refusal_s(pc),a3
	cmp	#E_ACCDN,d7		;old cookie had same name ?
	beq.s	.disp_error
	lea	ram_failure_s(pc),a3
.disp_error:
	gemdos	Cconws,(a3)
	gemdos	Cconws,prompt_s(pc)
	gemdos	Crawcin
	gemdos	Pterm,d7
;
;
;----------------------------------------------------------------------------
;	non-resident cookie jar routines
;
	make	JAR_links
;
;-----------------------------------------------------------------------------
;
;
pgm_len:	dc.l	0
;
;
Activation_s:
	dc.b	"________ UKEX 4.7  activated ! ________",CR,LF
	dc.b	CR,LF
	dc.b	NUL
;
initmess_s:
	dc.b	CR,LF
	dc.b	"---------------- UKEX -----------------",CR,LF
	dc.b	"Version 4.7  developed   Sep 1998 by:  ",CR,LF
	dc.b	"	Ulf Ronald Andersson            ",CR,LF
	dc.b	"	H”ders V„g 7                    ",CR,LF
	dc.b	"	S-145 70  Norsborg              ",CR,LF
	dc.b	"	Sweden                          ",CR,LF
	dc.b	"	                                ",CR,LF
	dc.b	"	mailto:dlanor@oden.se           ",CR,LF
	dc.b	"	http://www.oden.se/~dlanor/     ",CR,LF
	dc.b	CR,LF
	dc.b	NUL
;
Refusal_s:
	dc.b	"________ UKEX already active ! ________",CR,LF
	dc.b	"Sorry, I will not risk installing UKEX,",CR,LF
	dc.b	"when it seems to be installed already. ",CR,LF
	dc.b	"---------------------------------------",CR,LF
	dc.b	NUL
;
ram_failure_s:
	dc.b	"_______ Cookie creation failed ! ______",CR,LF
	dc.b	"Allocation of RAM for new cookie jar",CR,LF
	dc.b	"failed, so installation was aborted.",CR,LF
	dc.b	"---------------------------------------",CR,LF
	dc.b	NUL
;
prompt_s:
	dc.b	CR,LF
	dc.b	"Please press a key to continue...",CR,LF
	dc.b	CR,LF
	dc.b	NUL
	even
;
;
;-----------------------------------------------------------------------------
	end
;-----------------------------------------------------------------------------
;End of file:	UKEX.S
;-----------------------------------------------------------------------------
