; FILE: Source:modules/AlertFix.ASM REV: 5 --- cool Alert fix for 040/060 ; ; AlertFix patch for BlizKick ("patch" Module) ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ; ; This patch fixes the problems with pending alerts & 680x0.library ; being resident in blizzppc flash. Also fixes two bugs in exec/Alert(). ; If NewAlert module is installed make the exec/Alert() call it too ; (meaning that AlertFix should come after NewAlert if both are used). ; ; ; V1.1 - 2nd Feb 2000 ; Fixed major bug from the code, it broke regular Alert() calls. Huh. ; ; V1.2 - 5th Feb 2000 ; Made it possible to plant AlertFix inside ROM. ; ; V1.3 - 11th Sep 2000 ; Now really properly disable MMU instead of 'moves' -hack. Should ; work with 68040 now, I hope. Added internal support for NewAlert ; module. Added fix for two exec/Alert() bugs. Now also patches ; '$104 = ThisTask' -write, was missing before, oops. No longer calls ; Supervisor thru execbase vector, but with direct jsr, should make ; the patch work better during serious error conditions. Now works ; with 68020 and 68030 too. ; ; ; Written by Harry "Piru" Sintonen. ; This source code is Public Domain. include "blizkickmodule.i" ; Some required... SECTION PATCH,CODE _DUMMY_LABEL BK_PTC ; Code is run with following incoming parameters: ; ; a0=ptr to ROM start (buffer) eg. $1DE087B8 ; a1=ptr to ROM start (ROM) eg. $00F80000 (do *not* access!) ; d0=ROM lenght in bytes eg. $00080000 ; a2=ptr to _FindResident routine (will search ROM buffer for resident tag): ; CALL: jsr (a2) ; IN: a0=ptr to ROM, d0=rom len, a1=ptr to resident name ; OUT: d0=ptr to resident (buf) or NULL ; a3=ptr to _InstallModule routine (can be used to plant a "module"): ; CALL: jsr (a3) ; IN: a0=ptr to ROM, d0=rom len, a1=ptr to module, d6=dosbase ; OUT: d0=success ; a4=ptr to _Printf routine (will dump some silly things (errormsg?) to stdout ;-) ; CALL: jsr (a4) ; IN: a0=FmtString, a1=Array (may be 0), d6=dosbase ; OUT: - ; d6=dosbase, a6=execbase ; ; Code should return: ; ; d0=true if succeeded, false if failed. ; d1-d7/a0-a6 can be trashed. a7 *must* be preserved! ;-) moveq #0,d7 cmp.w #37,($C,a0) ;requires V37+ rom image blo .exit lea (regs,pc),a5 movem.l d0/a0-a4,(a5) lea (.no020p,pc),a1 btst #1,($128+1,a6) AFB_68020 AttnFlags beq .err lea (.resname,pc),a1 movem.l (regs,pc),d0/a0 move.l (findresident,pc),a2 jsr (a2) lea (.nores,pc),a1 tst.l d0 beq .err move.l d0,a4 moveq #4,d2 move.l (RT_INIT,a4),a2 add.l a2,d2 move.l d2,_newalert_addr move.l d2,_backfromh1 ;test if inside rom bounds? move.l (rom_log,pc),d0 cmp.l d0,a2 blo.b .nofix add.l (rom_size,pc),d0 cmp.l d0,a2 bhs.b .nofix ; inside rom, so generate ram buffer address sub.l (rom_log,pc),a2 -$f80000 add.l (rom_phys,pc),a2 +buffer .nofix moveq #0,d3 cmp.l #'NewA',(-4,a2) is it our NewAlert patch? beq.b .na_cont yep, special handling then ; check validity of the alert.hook tag lea (.badres,pc),a1 cmp.l #$42B80000,(a2) bne .err cmp.w #$48E7,(4,a2) bne .err cmp.w #$242E,(8,a2) bne .err ; find 'clr.l (0).w' in alert.hook end move.w #1024/2,d0 .find subq.w #1,d0 beq .err addq.l #2,a2 cmp.l #$42B80000,(a2) 'clr.l (0).w' bne.b .find cmp.w #$70FF,(4,a2) 'moveq #-1,d0' bne.b .find move.l a2,d3 .na_cont ; find $0 and $100 accesses in Alert() lea (.badrom1,pc),a1 move.l (rom_phys,pc),a2 move.w #16384/2,d0 lea ($2000,a2),a2 .find2 subq.w #1,d0 beq .err addq.l #2,a2 cmp.l #$203C<<16|'HE',(a2) bne.b .find2 cmp.l #'LP'<<16|$B0B8,(4,a2) bne.b .find2 cmp.l #$21C00000,(12,a2) bne.b .find2 cmp.l #$41F80100,(16,a2) bne.b .find2 ; find Alert() DisplayAlert bsr lea (20,a2),a0 moveq #64,d0 .find3 subq.l #1,d0 beq .err addq.l #2,a0 cmp.w #$6100,(a0) 'bsr.w x' bne.b .find3 cmp.l #$4AAE0126,(4,a0) check for both bugged & beq.b .found3 bugfree 'tst.x IDNestCnt(a6)' cmp.l #$4A2E0126,(4,a0) bne.b .find3 .found3 move.l a0,d4 ; find VBR bug in Alert() moveq #64,d0 .find4 subq.l #1,d0 beq .err addq.l #2,a0 cmp.l #$21FC00F8,(a0) bne.b .find4 cmp.l #$002046FC,(6,a0) bne.b .find4 addq.l #8,a0 ; inside ram buffer, so generate rom address sub.l (rom_phys,pc),a0 -buffer add.l (rom_log,pc),a0 +$f80000 move.l a0,_privi_addr2 ; find Privilege violation exception code lea (.badrom2,pc),a1 move.l (rom_phys,pc),a3 move.w #8192/2,d0 .find5 subq.w #1,d0 beq .err addq.l #2,a3 cmp.l #$0CAF00F8,(a3) bne.b .find5 cmp.l #$0002660C,(6,a3) bne.b .find5 cmp.l #$2F7C00F8,(10,a3) bne.b .find5 cmp.l #$00024ED5,(16,a3) bne.b .find5 move.l a3,d5 ; find Supervisor 010+ code move.l (rom_phys,pc),a3 move.w #8192/2,d0 .find6 subq.w #1,d0 beq .err addq.l #2,a3 cmp.l #$007C2000,(a3) bne.b .find6 cmp.l #$518F40D7,(4,a3) bne.b .find6 cmp.l #$2F7C00F8,(8,a3) bne.b .find6 cmp.l #$00023F7C,(14,a3) bne.b .find6 ; inside ram buffer, so generate rom address sub.l (rom_phys,pc),a3 -buffer add.l (rom_log,pc),a3 +$f80000 move.l a3,_svptr1 move.l a3,_svptr2 ; finally ready for patching, ; install the patch code movem.l (regs,pc),d0/a0 lea (_AlertFix_module,pc),a1 move.l (installmodule,pc),a3 jsr (a3) ; find ourself movem.l (regs,pc),d0/a0 lea (_name,pc),a1 move.l (findresident,pc),a3 jsr (a3) lea (.plantfail,pc),a1 tst.l d0 beq .err move.l d0,a5 ; (RT_INIT,a5) gives us pointer to RT_INIT as logical address, ; a5 + RT_SIZE is pointer to data after RT structure (usually ; RT_INIT pos) in physical memory. move.l (RT_INIT,a5),a3 lea (RT_SIZE,a5),a5 tst.l d3 beq.b .skip_newalert btst #3,($128+1,a6) AFB_68040 AttnFlags beq.b .no040p_a ;lea (_ahook1-_init,a3),a1 ;move.l a1,(RT_INIT,a4) move.l a3,(RT_INIT,a4) lea (_ahook2-_init,a3),a1 move.l d3,a0 move.w #$4EB9,(a0)+ move.l a1,(a0)+ .no040p_a bra.b .no_newalert .skip_newalert ; okay, we got NewAlert, patch the exception ; handler to jump it directly. lea (_newalert-_init,a3),a1 move.l d4,a0 move.w #$4EB9,(a0)+ move.l a1,(a0)+ .no_newalert btst #3,($128+1,a6) AFB_68040 AttnFlags beq.b .no040p_b lea (_alert1-_init,a3),a1 move.w #$4EB9,(a2)+ move.l a1,(a2)+ lea (_alert2-_init,a3),a1 addq.l #6,a2 move.w #$4EB9,(a2)+ move.l a1,(a2)+ ; find the '$104=ThisTask' write lea (.badrom1,pc),a1 moveq #32,d0 .find7 subq.l #1,d0 beq.b .err addq.l #2,a2 cmp.l #$2A6E0114,(a2) 'move.l $114(a6),a5' bne.b .find7 lea (_alert3-_init,a3),a1 move.w #$4EB9,(a2)+ move.l a1,(a2)+ .no040p_b move.l d5,a0 lea (_privi-_init,a3),a1 move.l (2,a0),(_privi_addr1-_init,a5) move.w #$4EB9,(a0)+ move.l a1,(a0)+ moveq #1,d7 .err tst.l d7 bne.b .exit lea (.errh,pc),a0 move.l a1,-(sp) move.l sp,a1 move.l (printf,pc),a2 jsr (a2) addq.l #4,sp .exit move.l d7,d0 rts .resname dc.b 'alert.hook',13,10,0 .errh dc.b 'AlertFix: couldn''t %s!',10,0 .no020p dc.b 'find 68020 or better CPU',0 .nores dc.b 'find alert.hook',0 .badres dc.b 'patch alert.hook',0 .badrom1 dc.b 'patch Alert()',0 .badrom2 dc.b 'patch Supervisor()',0 .plantfail dc.b 'InstallModule(), add some EXTRESBUF',0 CNOP 0,2 _AlertFix_module BK_MOD BKMF_SingleMode,_end,(0)<<24+37<<16+NT_UNKNOWN<<8+(256-54),_name,_idstr,_init ; Singlemode on, ; never init this module, requires KS V37.x or better, module type NT_UNKNOWN, priority -54. _init ; this code will never be called directly! _ahook1 moveq #0,d0 sub.l a0,a0 bsr.b _write _backfromh1 EQU *+2 jmp $badc0de _ahook2 moveq #0,d0 sub.l a0,a0 bsr.b _write moveq #-1,d0 rts _alert1 addq.l #4,(sp) sub.l a0,a0 bsr.b _read cmp.l #'HELP',d0 beq.b .need_help cmp.l #'HELP',(0).w .need_help rts _alert3 move.l ($114,a6),a5 bra.b _alert3b _alert2 addq.l #6,(sp) sub.l a0,a0 move.l #'HELP',d0 bsr.b _write lea ($100).w,a0 move.l d7,d0 bsr.b _write addq.l #4,a0 _alert3b move.l a5,d0 ;bra.b _write fall thru to _write! ; IN: a0.l = address ; d0.l = data ; OUT: a0.l = address _write movem.l d1/a1/a5,-(sp) lea (.write,pc),a1 lea (runnommu_s,pc),a5 _svptr1 EQU *+2 jsr $badc0de movem.l (sp)+,d1/a1/a5 .write move.l d0,(a0) rts ; IN: a0.l = address ; OUT: a0.l = address ; d0.l = data _read movem.l d1/a1/a5,-(sp) lea (.read,pc),a1 lea (runnommu_s,pc),a5 _svptr2 EQU *+2 jsr $badc0de movem.l (sp)+,d1/a1/a5 rts .read move.l (a0),d0 rts _privi addq.l #2,(sp) _privi_addr1 EQU *+2 cmp.l #$badda7a,(4+2,sp) beq.b .ok _privi_addr2 EQU *+2 cmp.l #$badda7a,(4+2,sp) bne.b .ok move.l (4+2,sp),(sp) .ok rts _newalert addq.l #2,(sp) _newalert_addr EQU *+2 jsr $badc0de tst.b ($126,a6) rts ; IN: a1 = routine to run in supervisor, mmu disabled, end with rts ; d0/d2-d7/a0/a2-a4 = whatever you like ; a6 = execbase ; OUT: d1 = scratched ; d0/d2-d7/a0/a2-a4 = whatever you like ; runnommu_s ori.w #$700,sr movec tc,d1 move.l d1,-(sp) movec cacr,d1 move.l d1,-(sp) movec dtt1,d1 move.l d1,-(sp) movec dtt0,d1 move.l d1,-(sp) movec itt1,d1 move.l d1,-(sp) movec itt0,d1 move.l d1,-(sp) cpusha bc make sure the above is written cinva bc move.l #$00FFC000,d1 mark 32-bit: Cacheable, Writethrough movec d1,itt0 movec d1,itt1 movec d1,dtt1 move.l #$0000C040,d1 mark 24-bit-DMA: Cache-Inhibited, Precise Exception Model movec d1,dtt0 move.l #$80008000,d1 instcache + datacache movec d1,cacr moveq #0,d1 turn off possible MMU mapping pflusha movec d1,tc cpusha bc cinva bc jsr (a1) cpusha bc move.l (sp)+,d1 movec d1,itt0 move.l (sp)+,d1 movec d1,itt1 move.l (sp)+,d1 movec d1,dtt0 move.l (sp)+,d1 movec d1,dtt1 move.l (sp)+,d1 movec d1,cacr move.l (sp)+,d1 pflusha movec d1,tc cpusha bc cinva bc nop rte _name _idstr dc.b 'AlertFix.patchcode',0 CNOP 0,2 _end CNOP 0,2 regs rom_size ds.l 1 rom_phys ds.l 1 rom_log ds.l 1 findresident ds.l 1 installmodule ds.l 1 printf ds.l 1 SECTION VERSION,DATA dc.b '$VER: AlertFix_PATCH 1.3 (11.9.00)',0