;============================================================================== ; rombase.asm: Apply the patches for ROM_BASE and calculator detection ; routines. ; ; $Id: rombase.asm,v 1.2 2004/07/15 13:16:31 Olivier Exp $ ; ; - GhostBuster for TI89 Titanium - ; Copyright (C) 2004 Olivier Armand ; and Kevin Kofler ; ; 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; if not, write to the Free Software Foundation, Inc., 59 Temple ; Place - Suite 330, Boston, MA 02111-1307, USA. ; ; In addition, as a special exception, Olivier Armand and Kevin Kofler give ; permission to link the code of this program with the ttunpack decompression ; library by the TI-Chess Team, and distribute linked combinations including ; the two. You must obey the GNU General Public License in all respects for ; all of the code used other than the ttunpack decompression library. If you ; modify this program, you may extend this exception to your version of the ; program, but you are not obligated to do so. If you do not wish to do so, ; delete this exception statement from your version. ; ;============================================================================== ; ROM_BASE has changed to $800000 on TI89 Titanium. ; PatchRomBase() corrects the uses of it, and some calculator detection routines ; that are now broken. xdef PatchRomBase ; #include "patch.h" ; 1) "and.l/andi.l #$600000,reg" will be replaced by "and.l/andi.l #$e00000,reg" ; ; 2) The only calculator detection routine which needs to be patched is: ; and.l/andi.l #$600000,dn ; instructions (CALC_DETECT_GAP bytes max) ; cmp.l/cmpi.l #$200000/$400000,dn ; bne/beq/.s/.w Label or sne/seq dn ; "and.l/andi.l #$600000,dn" is replaced by "and.l/andi.l #$e00000,dn" , ; and if the register is compared to $200000, $200000 is replaced by ; $400000 and the test of the following instruction is inverted. CALC_DETECT_GAP equ 28 ;input: a0.l = points to the first byte of the program's code ; a1.l = points to the byte just after the program's code ;ouput: d0.w = number of patches applied PatchRomBase: ; bra * pea (a2) moveq #0,d0 ; number of patches applied suba.l a2,a2 ; address of the instruction following the ; last "and #$600000" + CALC_DETECT_GAP (none) \CalcDPatchLoop: move.w -2(a0),d1 ; opcode move.w d1,d2 cmp.l #$600000,(a0) bne.s \TstCmpVal andi.w #%1111000111111111,d1 ; and.l #,dn ? cmp.w #%1100000010111100,d1 beq.s \IsAnd andi.w #%1111111111111000,d2 ; andi.l #,dn ? cmp.w #%0000001010000000,d2 bne.s \NextWord \IsAnd: move.l #$e00000,(a0)+ ; replace $600000 by $e00000 move.l a0,a2 ; address of the instruction following the last add.w #CALC_DETECT_GAP,a2 ; "and #$600000" + CALC_DETECT_GAP addq.w #1,d0 ; one more patch bra.s \NextWord2 \TstCmpVal: cmp.l #$200000,(a0) bne.s \NextWord cmp.l a2,a0 bhi.s \NextWord ; the gap is > CALC_DETECT_GAP andi.w #%1111000111111111,d1 ; cmp.l #,dn ? cmp.w #%1011000010111100,d1 beq.s \IsCmp andi.w #%1111111111111000,d2 ; cmpi.l #,dn ? cmp.w #%0000110010000000,d2 bne.s \NextWord \IsCmp: addq.w #4,a0 ; next instruction move.w (a0),d1 ; opcode move.w d1,d2 andi.w #%1111111000000000,d1 cmp.w #%0110011000000000,d1 ; bne/beq/.s/.w ? beq.s \IsTest andi.w #%1111111011111000,d2 cmp.w #%0101011011000000,d2 ; sne/seq dn bne.s \NextWord2 \IsTest move.l #$400000,-4(a0) ; replace $200000 by $400000 bchg.b #8,(a0) ; invert the test (bne becomes beq, etc.) addq.w #1,d0 ; one more patch \NextWord: addq.l #2,a0 \NextWord2: cmp.l a0,a1 bhi \CalcDPatchLoop move.l (a7)+,a2 rts