home *** CD-ROM | disk | FTP | other *** search
- opt o+,ow-
- ;*************************************************
- ;** AllocP32 **
- ;** Version 2.01 **
- ;**---------------------------------------------**
- ;** © 1997 Andreas Kleinert **
- ;** © 1997 THOR-Software, Thomas Richter **
- ;** rewritten in assembly language with the **
- ;** friendly permission of A. Kleinert **
- ;*************************************************
-
- include INC:exec_lib.asm ;exec defines
- include INC:macros.asm ;macro sets
-
- section main_code,code
-
- ;FOLD Main structure
- ;*************************************************
- ;** Main structure **
- ;** used by the resident code **
- ;*************************************************
- rsreset
- mn_OldAllocMem: rs.l 1 ;AllocMem Vector
- mn_OldFreeMem: rs.l 1 ;FreeMem Vector
- mn_SysBase: rs.l 1 ;ExecBase
- mn_LayersBase: rs.l 1 ;Start address of layers in the ROMs
- mn_LayersEnd: rs.l 1 ;End address of layers in the ROMs
- mn_len: rs.b 0
- ;ENDFOLD
- ;FOLD Start
- ;*************************************************
- ;** Start **
- ;** main program, patch exec and detach **
- ;** does not check for arguments **
- ;*************************************************
- Start:
- move.l ExecBase,a6
-
- lea BssBase,a5
-
- jsr Forbid(a6)
- move.l a6,mn_SysBase(a5)
-
- bsr.s FindLayers ;locate layers.library
-
- move.l #NewAllocMem,d0
- move.l a6,a1 ;Library
- lea AllocMem,a0
- move.l (a1,a0.l),mn_OldAllocMem(a5)
- jsr SetFunction(a6) ;install patch
- move.l d0,mn_OldAllocMem(a5) ;Save back old pointer
-
- move.l #NewFreeMem,d0
- move.l a6,a1
- lea FreeMem,a0
- jsr SetFunction(a6)
- move.l d0,mn_OldFreeMem(a5)
-
- lea Start(pc),a0
- clr.l -4(a0) ;unlink the resident segment
-
- jsr Permit(a6)
- moveq #0,d0 ;that's all, folks!
- rts
- ;ENDFOLD
- ;FOLD FindLayers
- ;*************************************************
- ;** FindLayers **
- ;** the layers library memory allocation is **
- ;** broken and not compatible to this patch **
- ;** we filter all layers.calls out for this **
- ;** reason **
- ;** This routine determinates the region in **
- ;** the ROMs where layers is located **
- ;*************************************************
- FindLayers:
- saveregs d5-d7/a3-a4
-
- lea LayersName,a1
- move.l mn_SysBase(a5),a6
- jsr FindResident(a6)
- tst.l d0
- beq.s .alertexit
-
- move.l d0,mn_LayersBase(a5) ;$46F660
- movea.l mn_SysBase(a5),a0 ;$46F63C,a0
- movea.l $12C(a0),a4
- addi.l #$40000,d0
- move.l d0,mn_LayersEnd(a5) ;$46F664
- moveq #$7D,d7
- lsl.l #3,d7
- moveq #0,d6
- moveq #0,d5
- movea.l a4,a3
- bra.s .inloop
- .cmpnow:
- move.l (a4),d0
- cmp.l mn_LayersBase(a5),d0
- bls.s .tolow
- cmp.l mn_LayersEnd(a5),d0
- bcc.s .tolow
- move.l d0,mn_LayersEnd(a5)
- .tolow:
- addq.l #4,a4
- addq.l #1,d6
- .next:
- tst.l (a4)
- bne.s .cmpnow
- move.l d6,d7
- moveq #0,d6
- movea.l a3,a4
- addq.l #1,d5
- .inloop
- cmp.l d7,d5
- ble.s .next
- bra.s .exit
-
- .alertexit:
- saveregs d7/a5
- move.l $114(a6),a5
- move.l #$0103000f,d7
- jsr Alert(a6)
- loadregs
- .exit:
- loadregs
- rts
- ;ENDFOLD
-
- dc.b "$VER: AllocP32 2.01",0 ;Version ID
- LayersName:
- dc.b "layers.library",0
-
- section resident_code,code
- ;FOLD NewAllocMem
- ;*************************************************
- ;** NewAllocMem **
- ;** this is the new AllocMem vector **
- ;** a6=ExecBase, d0=bytesize, d1=req.ments **
- ;** **
- ;** no need to patch AllocVec separately, **
- ;** it calls this vector anyways. **
- ;*************************************************
- NewAllocMem:
- saveregs d2-d3/a2/a5
-
- lea BssBase,a5
- move.l d0,d2
- move.l $10(a7),a0 ;get calling PC
- move.l d1,d3 ;safe back size & reqments
- move.l mn_OldAllocMem(a5),a2 ;get old vector
-
- cmp.l mn_LayersBase(a5),a0
- blo.s .nolayers
- cmp.l mn_LayersEnd(a5),a0 ;if called from layers, use ordinary memory (no way to fix it!)
- blo.s .islayers
- .nolayers:
-
- ;now try to get memory in 32 byte blocks.
- ;it's actually not required that the memory is
- ;aligned to 32 byte boundaries, it is only
- ;required that one part of it is in the
- ;cache of the MC and another part is in the
- ;cache of the PPC. Since cache lines of the PPC
- ;are 32 bytes wide, rounding the size to the
- ;next multiple of 32 WOULD be enough, if there
- ;wouldn't be this nasty "feature" of the
- ;layers.library - we aren't allowed there
- ;to do any rounding and must precisely
- ;return the memory block requested. This is
- ;due to the feature of layers to request one
- ;big block of memory, but returning it
- ;in small snippets afterwards. THIS IS
- ;ILLEGAL DUE TO THE RKRM RULES, but CBM didn't
- ;care about it. MungWall and MemSniff have
- ;similar troubles with layers for just the
- ;same reason.
- ;Therefore, we must really ADJUST the memory
- ;returned to 32 byte boundaries.
-
- moveq #8+24+31,d0 ;eight bytes for magic cookie and block start,
- ;24 bytes for proper alignemt
- ;31 bytes for alignment of the length to the
- ;next 32 byte boundary
- add.l d2,d0 ;get the size
- and.b #$e0,d0 ;round to next 32 byte boundary
- bsr.s _Allocate ;now try to get the memory
- tst.l d0 ;got some?
- beq.s .exit ;nope!
-
- moveq #31,d1 ;for rounding
- move.l d0,a0 ;store address here
- add.l d1,d0 ;round to next
- and.b #$e0,d0 ;32 bytes block
- move.l d0,a1 ;result is here
- move.l a0,(a0)
- move.l a0,(a1)+ ;store "real" address here (a1 and a0 might be the same, never mind)
- ;for later lookup and
- ;as "magic cookie"
- move.l #'AP32',(a1)+ ;store "magic cookie" itself
- move.l a1,d0 ;this is the address we return as result
- bra.s .exit
-
- .islayers:
- ;registers are still fine
- bsr.s _Allocate ;Allocate the old style
-
- .exit:
- loadregs
- rts
- ;ENDFOLD
- ;FOLD _Allocate
- ;*************************************************
- ;** _Allocate **
- ;** Get memory. bytesize in d0, reqments in d1 **
- ;** this part is identical to AllocP **
- ;** *a2 is the pointer to the old AllocMem **
- ;** vector **
- ;*************************************************
- _Allocate:
- saveregs d2-d3
-
- move.l d1,d3 ;no expunge?
- bmi.s .tryonce ;yes, so try only once
- ;Check if this is an Expunge-Call
- cmp.l #$ffffff00,d0
- bhs.s .tryonce ;yes, try only once (to expunge!)
-
- ;remember well: We DO NOT need to round the size
- ;here, this is done by the exec function internally
- ;you are GUARANTEED to get memory aligned to
- ;8 byte boundaries and of a size divisible by 8
-
- move.l d0,d2
- jsr (a2) ;try to get memory
- tst.l d0 ;got it ?
- bne.s .exit ;yes, so fine and exit
-
- ;if not: The above memory allocation may have started a flush
- ;operation, but since everything happend in the Forbid() mode
- ;above, some memory-free handlers might not have had a chance
- ;to run. That happens AT LEAST HERE (multitasking!), so
- ;we should try again. Call it an exec-feature!
-
- ;We DO NOT flush the memory with trying to allocate a
- ;memory block of size ~0, since this will flush ALL
- ;libraries & devices which is propably not necessary.
-
- move.l d2,d0
- move.l d3,d1 ;get parameters
- jsr (a2)
- tst.l d0
- bne.s .exit ;now fine ?
-
- ;seems that this hasn't helped yet. So, now let's try it
- ;the hard way: Remove ALL the stuff from memory by
- ;trying the impossible: Public memory of size ~0
-
- moveq #-1,d0
- moveq #1,d1
- jsr (a2) ;get ALL of it!
-
- ;no chance that this has worked, but at least, the
- ;memory is clean now!
- ;We try again for a last time and give up if that hasn't
- ;helped.
-
- move.l d2,d0
- move.l d3,d1 ;get parameters
- .tryonce:
- jsr (a2) ;try it a last time
-
- ;if this fails, the user has to take care about it!
- .exit:
- loadregs
- rts
- ;ENDFOLD
- ;FOLD NewFreeMem
- ;*************************************************
- ;** NewFreeMem **
- ;** FreeMem replacement *a6=SysBase **
- ;** *a1=Memory d0=size **
- ;*************************************************
- NewFreeMem:
- saveregs a2-a3/a5
-
- lea BssBase,a5
-
- move.l d0,d1
- beq.s .exit ;size=0 -> exit gracefully
- move.l $c(a7),a0 ;get calling PC
- move.l a1,d1
- beq.s .exit ;address =0 -> exit gracefully
- move.l mn_OldFreeMem(a5),a2 ;get old FreeMem vector
- move.l a1,a3 ;save memory address
-
- cmp.l mn_LayersBase(a5),a0
- blo.s .nolayers
- cmp.l mn_LayersEnd(a5),a0 ;if called from layers, use ordinary memory (no way to fix it!)
- blo.s .islayers
- .nolayers:
-
- cmp.l #'AP32',-(a3) ;check for the magic cookie
- bne.s .islayers ;if not, we never allocated this memory
-
- move.l -(a3),a0 ;get base address of this memory
-
- ;and now the same algorithm to
- ;find the size we used
- ;for allocation
-
- moveq #8+24+31,d1 ;eight bytes for magic cookie and block start,
- ;24 bytes for proper alignemt
- ;31 bytes for alignment of the length to the
- ;next 32 byte boundary
- add.l d0,d1 ;get the size
- and.b #$e0,d1 ;round to next 32 byte boundary
-
- cmp.l (a0),a0 ;is the base setup properly?
- bne.s .islayers ;if not, free it the old way
-
- move.l d1,d0 ;and the calculated size
- move.l a0,a1 ;if, use the base address
- clr.l 4(a3) ;clear cookie explicitly
- ;to avoid later confusion
-
- .islayers: ;the registers are still fine here...
- jsr (a2) ;call the old vector
- .exit:
- loadregs
- rts
- ;ENDFOLD
-
-
- section resident_bss,bss
- BssBase:
- ds.b mn_len ;main structure placed here
-
-
-