*****************************************************************************
**                                                                         **
** ModuleChange - Adapt original play routines                             **
**                                                                         **
** Project: Eagleplayer 2.04                                               **
** Authors: Jan Blumenthal & Henryk Richter                                **
** Start  : 1993/01/09                                                     **
** $Header$                                                                **
**                                                                         **
*****************************************************************************
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program (See the included file COPYING);
** if not, write to the Free Software Foundation, Inc.,
** 675 Mass Ave, Cambridge, MA 02139, USA.
**
*****************************************************************************

	if umbautest
MaxUmbauBytes 	= 200
		incdir	"include:"
		include	"misc/eagleplayer.i"

		rsreset
		rs.b	EPG_SizeOf
UB_MerkZahler	rs.w	1
UB_MerkPuffer	rs.b	MaxUmbauBytes+10
PufferEnd	rs.b	0


		move.l	PufferAdr(pc),a5
		move.l	#UB_TestData,EPG_Arg1(a5)
		move.l	#20,EPG_Arg2(a5)
		move.l	#UB_Tabelle,EPG_Arg3(a5)
		move.l	#1,EPG_Arg4(a5)
		move.l	#-2,EPG_Arg5(a5)
		move.l	#5,EPG_ArgN(a5)
		bsr.w	EPP_ModuleChange
		move.l	#UB_TestData,EPG_Arg1(a5)
		move.l	#20,EPG_Arg2(a5)
		move.l	#UB_Tabelle,EPG_Arg3(a5)
		move.l	#1,EPG_Arg4(a5)
		move.l	#-2,EPG_Arg5(a5)
		move.l	#5,EPG_ArgN(a5)
		bsr.w	EPP_ModuleRestore
		illegal
	endif

*---------------------------------------------------------------------------*
*---------------------------- Module-Umbauroutine --------------------------*
*---- Input:								----*
*----	Arg1 = Startadresse						----*
*----	Arg2 = Length							----*
*----	Arg3 = Umbautabelle						----*
*----	Arg4 = 1.b=1 Mehrmals eine Routine umbauen 2.b=2. Umbauroutine	----*
*----	       3.b=1 keine Suche nach Werten 4.b=1 Keine Suche nach Jmp ----*
*----	Arg5 = 1.w Kennbyte für Jump	|  2.w Kennbyte für Wert	----*
*---- Output:								----*
*----	Arg1 = Error							----*
*----	Arg2 = Anz der Umbauten						----*
*---------------------------------------------------------------------------*
EPP_ModuleChange:movem.l d1-a6,-(a7)
		move.l	PufferAdr2(pc),a5
	ifeq umbautest
		jsr	A5ClearCache(a5)
	endif
		move.l	EPG_ArgN(a5),d0
		sub.l	#5,d0
		bne.w	ErrorInArguments

		tst.b	EPG_Arg4+2(a5)
		bne.w	NotImplementedYet

		move.l	EPG_Arg3(a5),a1			;SuchTab(pc),a1
		move.l	EPG_Arg2(a5),d1
		bclr	#0,d1				;Lenght gerade machen
		move.l	a1,a2

		moveq	#0,d5				;UmbauZähler
.SuchSchleife:	sub.l	a3,a3				;a3 löschen
		tst.w	(a1)
		beq.w	UB_Ende
		move.w	(a1),a3				;Offset zur Tabelle
		add.l	a2,a3				;Adr der SuchTab

	*------ SuchTabelle in Module suchen ------*
		moveq	#0,d7
		move.w	2(a1),d7			;Lenght laden
		move.l	d7,d6
		move.l	EPG_Arg1(a5),a0			;Startadresse

		move.l	a0,a4				;ModuleAdr sichern
		move.l	a3,a6				;VergleichTabAdr Sichrn

		move.l	a4,d2				;StartAdr
		add.l	d1,d2				;Size dazuadden

		clr.w	UB_MerkZahler(a5)

	*---------- Suchtabelle durchtesten ----------*
	*-------------- offset/Jumps suchen ----------*
.FindNext:	move.w	(a3)+,d0
		tst.b	EPG_Arg4(a5)			;Suche nach Werten
		bne.s	.NoRelAdr

		cmp.w	EPG_Arg5(a5),d0			;Suche nach Offset ????
		bne.s	.NoRelAdr			;nein

	*---------- Adr für Offsets merken -----------*
		move.l	a1,-(a7)
		lea	UB_MerkZahler(a5),a1
		move.w	(a1),d0
		cmp.w	#MaxUmbauBytes,(a1)
		beq.w	UB_FatalError
		addq.w	#4,(a1)
		lea	UB_MerkPuffer(a5),a1
		lea	(a1,d0.w),a1
		move.l	a0,(a1)				;Adr merken
		moveq	#0,d0
		move.w	(a0),d0				;Offset aus Module laden
		ext.l	d0
		add.l	d0,(a1)				;Inhalt merken
		move.l	(a7)+,a1
		bra.b	.NoCMP

	*----------------- Werte suchen -----------------*
.NoRelAdr:	tst.b	EPG_Arg4+1(a5)			;Suche nach Jmps
		bne.s	.NoWert
		cmp.w	EPG_Arg5+2(a5),d0		;Kennbyte für Werte
		bne.s	.NoWert

	*-------------- Adr für Offsets merken -----------*
		move.l	a1,-(a7)
		lea	UB_MerkZahler(a5),a1
		move.w	(a1),d0
		cmp.w	#MaxUmbauBytes,(a1)
		beq.w	UB_FatalError
		addq.w	#2,(a1)
		lea	UB_MerkPuffer(a5),a1
		move.w	(a0),(a1,d0.w)			;Wert merken
		move.l	(a7)+,a1
		bra.b	.NoCMP

.NoWert:	cmp.w	(a0),d0
		bne.s	.NotFound
.NoCMP:		cmp.l	a0,d2				;ModuleEnde
		ble.s	.NextSuchTab
		addq.l	#2,a0
		dbf	d7,.FindNext

	*---- Die Merkzellen der Umbautabelle füllen ------*
		move.w	UB_MerkZahler(a5),d0
		beq.s	.NoMerk
		movem.l	d1/a1/a0,-(a7)
		move.l	d0,d1
		subq.w	#1,d1
		move.w	d6,d0
		addq.w	#1,d0
		add.w	d0,d0				;Length of SuchPrg ->d0
		lea	UB_MerkPuffer(a5),a1
		lea	(a6,d0.w),a0
.CopyMerkPu:	move.b	(a1)+,(a0)+
		dbf	d1,.CopyMerkPu
		movem.l	(a7)+,d1/a1/a0
		clr.w	UB_MerkZahler(a5)


	*-------------- Sub-Programm umbauen --------------*
.NoMerk:	addq.l	#1,d5				;Umbauzähler erhöhen
		sub.l	a3,a3
		move.w	4(a1),a3
		add.l	a2,a3				;Adr der ErsatzTab

	*----- JSR reinsetzen und rest auf nop setzen -----*
		move.w	#$4eb9,(a4)+			;jsr setzen
		move.l	a3,(a4)+			;EinSprungAdr setzen
		move.w	2(a1),d0			;Lenght der Testtab
		subq.w	#3,d0
		tst.w	d0
		blt.w	.SuchSchleife
.SetNop		move.w	#$4e71,(a4)+			;NOP`s setzen
		dbf	d0,.SetNop
		tst.b	EPG_Arg4+3(a5)
		beq.s	.NextSuchTab
		subq.l	#2,a4
		bra.s	.NotFound

.NextSuchTab	addq.l	#6,a1
		bra.w	.SuchSchleife

.NotFound:	move.l	a6,a3			;SuchTab wieder zurücksetzen
		addq.l	#2,a4

		cmp.l	a4,d2		;ModuleEnde ????
		ble.s	.NextSuchTab

		move.l	a4,a0			;Modul Adr um 1 erhöhen
		move.l	d6,d7			;Schleifenanzahl neu setzen
		clr.w	UB_MerkZahler(a5)
		bra.w	.FindNext

UB_Ende:	moveq	#0,d0			;Kein Error
		bra.s	UB_SetRegs

	*------------ Es ist ein Fehler aufgetreten ----------*
NotImplementedYet:moveq	#EPR_NotImplemented,d0
		bra.s	UB_SetRegs

	*------------ Es ist ein Fehler aufgetreten ----------*
UB_FatalError:	moveq	#EPR_BufferFull,d0
UB_SetRegs:	move.l	d0,EPG_Arg1(a5)
		move.l	d5,EPG_Arg2(a5)
	ifeq umbautest
		jsr	A5ClearCache(a5)
	endif
		movem.l	(a7)+,d1-a6
		rts


*---------------------------------------------------------------------------*
*---------------------------- Module-Restoreroutine ------------------------*
*---- Input:								----*
*----	Arg1 = Startadresse						----*
*----	Arg2 = Length							----*
*----	Arg3 = Umbautabelle						----*
*----	Arg4 = Flags							----*
*----	Arg5 = 1.w Kennbyte für Jump	|  2.w Kennbyte für Wert	----*
*---- Output:								----*
*----	Arg1 = Error							----*
*----	Arg2 = Anz der Umbauten						----*
*---------------------------------------------------------------------------*
EPP_ModuleRestore:movem.l d1-a6,-(a7)
		move.l	PufferAdr2(pc),a5
	ifeq umbautest
		jsr	A5ClearCache(a5)
	endif
		move.l	EPG_Argn(a5),d0
		subq.l	#5,d0
		bne.w	ErrorInArguments

		move.l	EPG_Arg1(a5),a0			;Startadr nach a0
		move.l	a0,d2
		move.l	EPG_Arg2(a5),d1
		add.l	d1,d2				;Endadresse nach d2
		moveq	#0,d5

	*----------- Suche die eingebauten Sprünge -----------*
.NextWord:	cmp.w	#$4eb9,(a0)+
		beq.s	.AbsJump

	*--------------- Ist das Ende erreicht ---------------*
.TestAufEnde:	cmp.l	a0,d2
		bls.s	UB_Ende
		bra.s	.NextWord


	;dc.w	Adr-SuchTab,Lenght,ErsatzSprung-SuchTab
.ABSjump:	move.l	EPG_Arg3(a5),a1			;SuchTabelle
.NextSuchTab:	moveq	#0,d0
		move.w	(a1),d0
		beq.s	.TestAufEnde			;noch ein Eintrag
		moveq	#0,d1
		move.w	4(a1),d1
		add.l	EPG_Arg3(a5),d1
		cmp.l	(a0),d1				;Adr in a0=Ersatzroutine
		beq.s	.JumpFound
		addq.l	#6,a1
		bra.s	.NextSuchTab



	*--------- Der umgebaute Sprung wurde gefunden -------*
.JumpFound:	subq.l	#2,a0
		moveq	#0,d1				;Length of Testroutine
		move.w	2(a1),d1
		add.l	EPG_Arg3(a5),d0
		move.l	d0,a1				;Suchroutine

		clr.w	UB_MerkZahler(a5)
		move.l	a1,a2
		move.l	d1,d0
		add.l	d0,d0
		addq.l	#2,d0
		add.l	d0,a2				;Adresse des Merkpuffer
		moveq	#0,d3				;Merkzahler

	*------- Testen, wie was zurück gechanged wird -------*
.Restore:	move.w	(a1)+,d4
		cmp.w	EPG_Arg5(a5),d4			;Folgt jetzt einjump
		beq.s	.Changejump

		cmp.w	EPG_Arg5+2(a5),d4		;Folgt jetzt ein Wert
		beq.s	.ChangeWert

.DochNicht:	move.w	d4,(a0)+
.ToRestoreDBF:	cmp.l	#MaxUmbaubytes,d3
		bhi.w	UB_FatalError
		dbf	d1,.Restore
		addq.l	#1,d5
		bra.s	.TestAufEnde


	*---------- Offset von Adressen zurücksetzen --------------*
.ChangeJump:	tst.b	EPG_Arg4(a5)
		bne.s	.DochNicht
		move.l	(a2)+,d0
		sub.l	a0,d0				;Offset berechnen
		move.w	d0,(a0)+
		addq.l	#4,d3
		bra.b	.ToRestoreDBF

	*---------- Offset von Adressen zurücksetzen --------------*
.ChangeWert:	tst.b	EPG_Arg4+1(a5)
		bne.s	.DochNicht
		move.w	(a2)+,(a0)+
		addq.l	#2,d3
		bra.b	.ToRestoreDBF






******************************************************************************
	if umbautest
PufferAdr2:
PufferAdr:	dc.l	Puffer
Puffer		ds.b	PufferEnd
ErrorInArguments:
		movem.l	(a7)+,d1-a6
		rts

UB_TestData:	nop
		moveq	#0,d0
		lea	UB_dort(pc),a0
		move.w	#345,d0
		rts
		lea	UB_dort+3(pc),a0
		move.w	#245,d0
		rts

UB_Dort:	dc.b	"hallo",0

UB_Tabelle:	dc.w	.Such1-UB_Tabelle,(.Such1End-.Such1)/2-1,.Such1Ersatz-UB_Tabelle
		dc.w	0

.Such1:		;lea	dort(pc),a0
		dc.w	$41fa,$ffff
		;move.w	#345,d0
		dc.w	$303c,$fffe
		rts
.Such1End:	dc.w	0,0,0
.Such1Ersatz:	rts

	endif
