;$$TABS=12 $$MAKE="casm -A %s.asm -O%s -CCQS"
;
; Fastport.Asm - Patch AddPort, FindPort, and RemPort to support hashed port names.
;
; written for CAPE-68K

	exeobj
	include	"lvo.asm"
	include	"strucdef.asm"


hash_size	equ	32	; MUST be power of two. The larger this is, the
			;faster the routines will be (and the more memory
			; the list will use).
hash_and	equ	(hash_size-1)*16

start:	move.l	4,a6	; execbase
	move.l	#end_code-start_code,d2 ; size
	move.l	d2,d0	; size
	moveq	#0,d1	; memory type
	jsr	_LVOAllocMem(a6)
	move.l	d0,a0
	lea	start_code(pc),a1
	subq	#1,d2
copy_lp:	move.b	(a1)+,(a0)+
	dbra	d2,copy_lp
	move.l	d0,a0
	jmp	(a0)

start_code:
; code that gets moved - must be relocatable
; on entry, a6=execbase
	jsr	_LVOForbid(a6)	; don't let anyone bother us
				; while modifying execbase!
	
; initialize hash chains:
	lea	hash_list(pc),a0
	move.l	a0,a5
	moveq	#hash_size-1,d0
init_loop:	NEWLIST	a0
	lea	16(a0),a0
	dbra	d0,init_loop

; now, add each port to our list
	move.l	eb_PortList+LH_HEAD(a6),d3
scanloop:	move.l	d3,a2
	move.l	(a2),d3
	beq.s	done_scan
; now, compute hash function!
	move.l	ln_Name(a2),a0	; string
	moveq	#0,d0		; hash value
hash_loop:	move.b	(a0)+,d1
	beq.s	got_hash
	add.b	d1,d0
	addx	d0,d0
	bra.s	hash_loop
got_hash:	and	#hash_and,d0
	lea	hash_list(pc),a0
	add	d0,a0
	move.l	a2,a1
	ADDHEAD
	bra.s	scanloop
done_scan:	move.l	a6,a1
	move	#_LVOAddPort,a0
	lea	my_addport(pc),a2
	move.l	a2,d0
	jsr	_LVOSetFunction(a6)

;	move	#_LVORemPort,a0
;	lea	my_remport(pc),a2
;	move.l	a2,d0
;	jsr	_LVOSetFunction(a6)
	
	move	#_LVOFindPort,a0
	lea	my_findport(pc),a2
	move.l	a2,d0
	jsr	_LVOSetFunction(a6)
	jsr	_LVOPermit(a6)
	move.l	a5,eb_PortList(a6)	; so can dump hash chain
	moveq	#0,d0		; ret code
	rts

my_findport:
	move.l	a1,a0
	moveq	#0,d0
1$:	move.b	(a0)+,d1
	beq.s	2$
	add.b	d1,d0
	addx	d0,d0
	bra.s	1$
2$:	and	#hash_and,d0
	lea	hash_list(pc),a0
	add	d0,a0
	addq.b	#1,$127(a6)			; forbid()
	jsr	_LVOFindName(a6)
	subq.b	#1,$127(a6)
	rts


my_addport:
	lea	mp_MSGLIST(a1),a0
	NEWLIST	a0
	move.l	ln_Name(a1),a0
	moveq	#0,d0
1$:	move.b	(a0)+,d1
	beq.s	2$
	add.b	d1,d0
	addx	d0,d0
	bra.s	1$
2$:	and	#hash_and,d0
	lea	hash_list(pc),a0
	add	d0,a0
	addq.b	#1,$127(a6)			; forbid()
	ADDHEAD
	subq.b	#1,$127(a6)			; permit()
	rts

hash_list:	ds.b	hash_size*16
	dc.l	$31415927			; end marker for dumper
end_code:
	end
