;TOSAAAACDICAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPPPNMHO

	incdir	'ups:'
	include	'ups.i'
	incdir	'include:'
	include	'exec/exec.i'
	include	'exec/ports.i'
	include	'exec/libraries.i'
	include	'dos/dosextens.i'
	include	'libraries/commodities.i'
	include	'utility/tagitem.i'
	include	'libs/exec.i'
	include	'libs/commodities.i'

GetProgramName		equ	-576
FilePart		equ	-870
MatchPatternNoCase	equ	-972
ParsePatternNoCase	equ	-966


	SECTION	SetFunction,code_p

	movem.l	d0-d7/a0-a6,-(a7)
	bsr.s	start
	movem.l	(a7)+,d0-d7/a0-a6
	rts

start	sub.l	a1,a1
	move.l  4,a6
	jsr	FindTask(a6)
	move.l	d0,a4
	move.l	d0,task
	tst.l	pr_CLI(a4)
	bne.s   fromCLI
	lea	pr_MsgPort(a4),a0
	jsr	WaitPort(A6)
	lea	pr_MsgPort(a4),a0
	jsr	GetMsg(A6)
	move.l	d0,returnMsg
fromCLI	jsr	start2
	tst.l	returnMsg		; Is there a message?
	beq.s	exitToDOS		; if not, skip...
	move.l	4,a6
        jsr	Forbid(a6)  	        ; note! No Permit needed!
	move.l	returnMsg,a1
	jsr	ReplyMsg(a6)
exitToDOS
	rts

returnMsg dc.l	0

	SECTION	SetFunctionMain,code_p

start2	move.l	4,a6
;	lea	upsname,a1
;	jsr	FindTask(a6)
;	tst.l	d0
;	beq.w	.exit1
;	move.l	d0,upstask
	lea	cxname,a1
	move.l	#36,d0
	jsr	OpenLibrary(a6)
	tst.l	d0
	beq.w	.exit1
	move.l	d0,cxbase
;	jsr	CreateMsgPort(a6)
;	tst.l	d0
;	beq.w	.exit2
;	move.l	d0,repport
	jsr	CreateMsgPort(a6)
	tst.l	d0
	beq.w	.exit3
	move.l	d0,cxport
	moveq	#-1,d0
	jsr	AllocSignal(a6)
	cmp.b	#-1,d0
	beq.w	.exit35
	moveq	#1,d1
	lsl.l	d0,d1
	move.l	d0,signal
	move.l	d1,exitbits
	move.l	cxport,a0
	clr.l	d1
	move.b	MP_SIGBIT(a0),d1
	moveq	#1,d0
	lsl.l	d1,d0
	move.l	d0,cxbits
	move.l	cxbase,a6
	clr.l	d0
	lea	newbroker,a0
	jsr	CxBroker(a6)
	tst.l	d0
	beq.w	.exit4
	move.l	d0,broker
	move.l	d0,a0
	moveq	#1,d0
	jsr	ActivateCxObj(a6)
	move.l	4,a6
	lea	upsportname,a1
	jsr	FindPort(a6)
	tst.l	d0
	beq.w	.exit5
	move.l	d0,upsport
	move.l	#umAllocUPS,d7
	lea	cxname2,a0
	bsr.w	SendMessage
	lea	patcher,a0
	move.l	#umInstall,d7
	bsr.w	SendMessage
	tst.l	d0
	bne.w	.exit6

.loop	move.l	exitbits,d0
	or.l	cxbits,d0
	jsr	Wait(a6)
.loop2	and.l	exitbits,d0
	tst.l	d0
	bne.w	.exit6
	move.l	cxport,a0
	jsr	GetMsg(a6)
	tst.l	d0
	beq.s	.eloop2
	move.l	d0,-(a7)
	move.l	d0,a0
	move.l	cxbase,a6
	jsr	CxMsgType(a6)
	cmp.l	#CXM_COMMAND,d0
	bne.s	.skip
	move.l	(a7)+,a0
	jsr	CxMsgID(a6)
	cmp.l	#CXCMD_DISABLE,d0
	beq.s	.disabl
	cmp.l	#CXCMD_ENABLE,d0
	beq.s	.enable
	cmp.l	#CXCMD_KILL,d0
	beq.s	.exit7
	bra.s	.skip
.disabl	move.l	broker,a0
	clr.l	d0
	jsr	ActivateCxObj(a6)
	bra.s	.skip
.enable	move.l	broker,a0
	moveq	#1,d0
	jsr	ActivateCxObj(a6)
.skip	move.l	4,a6
.eloop2	bra.w	.loop


.exit7	clr.l	done
	move.l	4,a6
	move.l	#umRemove,d7
	lea	patcher,a0
	bsr.s	SendMessage
.exit6	move.l	4,a6
	move.l	#umFreeUPS,d7
	lea	cxname2,a0
	bsr.s	SendMessage
.exit5	move.l	cxbase,a6
	move.l	broker,a0
	jsr	DeleteCxObjAll(a6)
.exit4	move.l	4,a6
	move.l	signal,d0
	jsr	FreeSignal(a6)
.exit35	move.l	4,a6
	move.l	cxport,a0
	jsr	DeleteMsgPort(a6)
.exit3	;move.l	4,a6
;	move.l	repport,a0
;	jsr	DeleteMsgPort(a6)
.exit2	move.l	4,a6
	move.l	cxbase,a1
	jsr	CloseLibrary(a6)
.exit1	rts


SendMessage
	move.l	a6,-(a7)
	move.l	4,a6
	lea	message,a4
	move.l	a0,um_A0(a4)
	move.l	a1,um_A1(a4)
	move.l	d0,um_D0(a4)
	move.l	d1,um_D1(a4)
	or.l	#umNoFree,d7
	move.l	d7,um_Command(a4)
	movem.l	d1-d7/a0-a6,-(a7)
	jsr	CreateMsgPort(a6)
	movem.l	(a7)+,d1-d7/a0-a6
	tst.l	d0
	beq.w	.exit
	move.l	d0,repport
	move.l	repport,MN_REPLYPORT(a4)
	move.w	#um_SIZEOF,MN_LENGTH(a4)
	move.l	a4,a1
	move.l	upsport,a0
	jsr	PutMsg(a6)
	move.l	repport,a0
	clr.l	d1
	move.b	MP_SIGBIT(a0),d1
	moveq	#1,d0
	lsl.l	d1,d0
	jsr	Wait(a6)
	move.l	repport,a0
	jsr	GetMsg(a6)
	move.l	d0,-(a7)
.loop	move.l	repport,a0
	jsr	GetMsg(a6)
	tst.l	d0
	bne.s	.loop
	move.l	(a7)+,a4
	move.l	um_A0(a4),a0
	move.l	um_A1(a4),a1
	move.l	um_D0(a4),d0
	move.l	um_D1(a4),d1
	movem.l	d0-d7/a0-a6,-(a7)
	move.l	repport,a0
	jsr	DeleteMsgPort(a6)
	movem.l	(a7)+,d0-d7/a0-a6
.exit	move.l	(a7)+,a6
	rts


MsgExit	tst.l	done
	beq.s	.no
	movem.l	d0-d7/a0-a6,-(a7)
	move.l	4,a6
	move.l	task,a1
	move.l	exitbits,d0
	jsr	Signal(a6)
	movem.l	(a7)+,d0-d7/a0-a6
.no	rts





	SECTION	Data,data_p
ver	dc.b	'$VER: SetFunction patcher for Ultimate Patch System.',0
cxname	dc.b	'commodities.library',0
upsname	dc.b	'Ultimate Patch System',0
	cnop	0,4
;upstask	dc.l	0
cxbase	dc.l	0
repport	dc.l	0
cxbits	dc.l	0
exitbits
	dc.l	0
signal	dc.l	0
broker	dc.l	0
done	dc.l	1
task	dc.l	0
oldfunc	dc.l	0
newbroker
	dc.b	NB_VERSION,0
	dc.l	cxname2
	dc.l	cxtitle
	dc.l	cxdescr
	dc.w	NBU_UNIQUE,0
	dc.b	0,0
cxport	dc.l	0
	dc.w	0

cxname2	dc.b	'SetFunction',0
cxtitle	dc.b	'SetFunction Patcher V1.0',0
cxdescr	dc.b	'  by Goran Mitrovic in 1995.',0
upsportname
	dc.b	'Ultimate Patch System',0
mask	dc.b	'#?.library',0
	cnop	0,4
upsport	dc.l	0

message	blk.b	um_SIZEOF


patcher	blk.b	32
	dc.l	pfsControlLong
	dc.l	0			; pointer to next patcher
	dc.l	0			; pointer to prev patcher
	dc.l	UPSMainVersion		; minimum version of UPS to start
	dc.l	UPSMainVersion		; version of UPS which was used
					; while patcher was developed
	dc.l	PatcherName		; pointer to name of patcher
	dc.w	0,0			; version
	dc.l	CoderName		; pointer to name of programmer
	dc.l	ver			; pointer to $VER: string
	dc.l	PatcherIDString		; listview entry
	dc.l	pfsDisableable		; flags
	dc.l	0			; status of flags
execbase
	dc.l	0			; exec base
intbase	dc.l	0			; intuition base
gadtbase
	dc.l	0			; gadtools base
dosbase	dc.l	0			; dos base
gfxbase	dc.l	0			; graphics base
ccxbase	dc.l	0			; commodities base
laybase	dc.l	0			; layers base
upsbase	dc.l	0			; UPS lib base
	dc.l	0			; pointer to init routine
	dc.l	MsgExit			; pointer to exit routine
	dc.l	0			; pointer to prefs routine
	dc.l	0			; pointer to cx keys to call prefs rout
	dc.l	Resources		; pointer to structure of requested
    					; opened resources
	dc.l	Patch1			; pointer to structure for patches
	dc.l	pls1			; pointer to pls structure
	dc.l	0			; pointer to main UPS msg port
	dc.l	0			; pointer to rexx port
	dc.l	0			; pointer to pxs structure
semaphore
	dc.l	0
	dc.l	0,0
	dc.l	pfsControlLong
	dc.l	patcher			; pointer to the beginning of struct

CoderName
	dc.b	'Goran Mitrovic',0
PatcherName
PatcherIDString
	dc.b	'SetFunction',0				; 25
	cnop	0,4


Resources
	dc.l	0			; pointer to next entry
	dc.l	0			; pointer to previous entry
	dc.l	rt_Library		; type of resource
	dc.l	100			; resource id
	dc.l	0			; flags
	dc.l	res1name		; pointer to name of resource
res1base
	dc.l	0			; base of opened resource
	dc.l	0			; version, if needed
	blk.l	8			; ...to put in data regs
	dc.l	0			; user open rout for user type
	dc.l	0			; user close rout for user type
	dc.l	0			; pointer to name for user type
	dc.l	0,0

res1name
	dc.b	'exec.library',0
	cnop	0,4


Patch1
	dc.l	0			; pointer to next patch
	dc.l	0			; pointer to prev patch
	dc.l	30000			; priority, less runs first
	dc.l	patcher			; pointer to parent Patcher
	dc.l	Patch1ID		; listview entry
	dc.l	Patch1purpose		; pointer to purpose string
	dc.l	100			; id of resource to be patched
	dc.l	mpsDisableable		; flags
	dc.l	0			; status of flags
	dc.l	-420			; offset to change
	dc.l	setfunction		; pointer to new routine
	dc.l	0			; pointer to old routine
	dc.l	0			; pointer to pns structure
	dc.l	0			; notified when enabled/disabled
	dc.l	0			; install rout for user type
	dc.l	0			; uninstall rout for user type
	dc.l	0			; pointer to init routine
	dc.l	0			; pointer to exit routine
	dc.l	pls1			; pointer to pls structure
	dc.l	0,0,0,0


Patch1ID
	dc.b	'SetFunction',0				; 27
	even
Patch1purpose
	dc.b	'replacement',0				; 16
	cnop	0,4



pls1	dc.l	0			; pointer to next link
	dc.l	0			; pointer to prev link
	dc.l	pls1ID			; listview string
	dc.l	0			; pointer to prefs routine
	dc.l	plsDisableable		; flags
	dc.l	0			; status
	dc.l	Patch1
	dc.l	0

pls1ID	dc.b	'Main Entry',0				; 27
	cnop	0,4

list	dc.l	0


	SECTION	PatchCode,code_p


setfunction
	movem.l	d0-d7/a0-a6,-(a7)
	movem.l	d0/a0/a1,-(a7)
	move.l	4,a6

	cmp.l	4,a1
	bne.w	.ok2
	cmp.w	#-420,a0
	beq.s	.aa

.ok2	movem.l	d0-d7/a0-a6,-(a7)
	move.l	dosbase,a6
	move.l	LN_NAME(a1),-(a7)
	move.l	#mask,d1
	move.l	#destmask,d2
	move.l	#1024,d3
	jsr	ParsePatternNoCase(a6)
	move.l	#destmask,d1
	move.l	(a7)+,d2
	jsr	MatchPatternNoCase(a6)
	tst.b	d0
	beq.s	.no
	bra.s	.ok
.no	movem.l	(a7)+,d0-d7/a0-a6
	bra.s	.aa
.ok	movem.l	(a7)+,d0-d7/a0-a6
;	move.l	semaphore,a0
;	move.w	(a0),d0
;	tst.w	d0
	bra.s	New
.aa	movem.l	(a7)+,d0/a0/a1
	movem.l	(a7)+,d0-d7/a0-a6
	rts

New	movem.l	(a7)+,d0/a0/a1
	move.l	list,a2
.loop1	cmp.l	#0,a2
	beq.s	.eloop1
	move.l	sf_Offset(a2),d1
	cmp.w	d1,a0
	bne.w	.cont1
	cmp.l	sf_Base(a2),a1
	bne.s	.cont1
	cmp.l	sf_Old(a2),d0
	beq.w	RestOld
.cont1	move.l	sf_Next(a2),a2
	bra.s	.loop1
.eloop1	movem.l	d0-d7/a0/a1/a3-a6,-(a7)
	move.l	#sf_SIZEOF,d0
	move.l	#MEMF_PUBLIC|MEMF_CLEAR,d1
	jsr	AllocVec(a6)
	move.l	d0,a2
	movem.l	(a7)+,d0-d7/a0/a1/a3-a6
	cmp.l	#0,a2
	beq.w	.exit
	clr.l	d1
	move.w	a0,d1
	ext.l	d1
	move.l	d1,sf_Offset(a2)
	move.l	a1,sf_Base(a2)
	move.l	d0,sf_New(a2)
;	moveq	#6,d2
;	mulu.w	d1,d2
	move.l	a1,a3
;	adda.l	d2,a3
	adda.l	d1,a3
	addq.l	#2,a3
	move.l	(a3),sf_Old(a2)
	move.l	(a3),-(a7)
	move.l	#umMakeEasyPatch,d7
	move.l	LN_NAME(a1),libname
	move.w	LIB_VERSION(a1),libver+2
	move.l	d1,offset
	move.l	d0,patch
	movem.l	d1-d7/a0-a6,-(a7)
	sub.l	a1,a1
	jsr	FindTask(a6)
	movem.l	(a7)+,d1-d7/a0-a6
	move.l	d0,a3
	movem.l	d0-d7/a0-a6,-(a7)
	move.l	dosbase,a6
	move.l	#taskname,d1
	move.l	#1023,d2
	jsr	GetProgramName(a6)
	tst.b	d0
	beq.s	.task
	move.l	#taskname,d1
	jsr	FilePart(a6)
	move.l	d0,idstr
	bra.s	.notask	
.task	move.l	LN_NAME(a3),idstr
.notask	movem.l	(a7)+,d0-d7/a0-a6
	lea	taglist,a0
	lea	patcher,a1
	movem.l	d0-d7/a1-a6,-(a7)
	jsr	SendMessage
	movem.l	(a7)+,d0-d7/a1-a6
	move.l	a0,sf_Patch(a2)
	cmp.l	#0,a0
	bne.s	.lab1
	move.l	a2,a1
	jsr	FreeVec(a6)
	bra.s	.exit2
.lab1	tst.l	list
	beq.s	.lab2
	move.l	list,a3
	move.l	a2,sf_Prev(a3)
	move.l	a3,sf_Next(a2)
.lab2	move.l	a2,list
.exit2	move.l	(a7)+,oldfunc
.exit	movem.l	(a7)+,d0-d7/a0-a6
	move.l	oldfunc,d0
	addq.l	#4,a7
	rts

RestOld	move.l	sf_New(a2),-(a7)
	move.l	sf_Patch(a2),a0
	move.l	#umFreeEasyPatch,d7
	movem.l	d0-d7/a0-a6,-(a7)
	jsr	SendMessage
	movem.l	(a7)+,d0-d7/a0-a6
	tst.l	sf_Next(a2)
	beq.s	.lab1
	move.l	sf_Next(a2),a3
	move.l	sf_Prev(a2),sf_Prev(a3)
.lab1	tst.l	sf_Prev(a2)
	beq.s	.lab2
	move.l	sf_Prev(a2),a3
	move.l	sf_Next(a2),sf_Next(a3)
	bra.s	.lab3
.lab2	move.l	sf_Next(a2),list
	move.l	a2,a1
	jsr	FreeVec(a6)
.lab3	move.l	(a7)+,oldfunc
	movem.l	(a7)+,d0-d7/a0-a6
	move.l	oldfunc,d0
	addq.l	#4,a7
	rts


taglist	dc.l	umTagResourceType,rt_Library
	dc.l	umTagResourceName
libname	dc.l	0
	dc.l	umTagResourceVersion
libver	dc.l	0
;	dc.l	umTagResourceID,100
	dc.l	umTagPatchPri,20
	dc.l	umTagPatchPurposeString
	dc.l	purpose
	dc.l	umTagPatchIDString
idstr	dc.l	0
	dc.l	umTagPatchOffset
offset	dc.l	0
	dc.l	umTagPatchDisableable,1
	dc.l	umTagPatchFullPatch,1
	dc.l	umTagPatch
patch	dc.l	0
	dc.l	umTagPatchNotifyDisable,0
	dc.l	umTagPatchInit,0
	dc.l	umTagPatchExit,0
	dc.l	TAG_DONE,0

purpose	dc.b	'replacement',0

 STRUCTURE sf,0
    APTR  sf_Next
    APTR  sf_Prev
    APTR  sf_Old
    APTR  sf_New
    APTR  sf_Patch
    APTR  sf_Base
    LONG  sf_Offset
    LABEL sf_SIZEOF


	SECTION	taskname,bss_p

taskname
	ds.b	1024
destmask
	ds.b	1024
