; ; dynArea.s ; ; The handling of the dynamic area itself ; ; © 1994-1998 Straylight ; ;----- Licensing note ------------------------------------------------------- ; ; This file is part of Straylight's Dynamite ; ; Dynamite 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, or (at your option) ; any later version. ; ; Dynamite 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 Dynamite. If not, write to the Free Software Foundation, ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ;----- Standard header ------------------------------------------------------ GET libs:header GET libs:swis GET libs:stream ;----- External dependencies ------------------------------------------------ GET sh.wSpace ;----- Main code ------------------------------------------------------------ AREA |Dynamite$$Code|,CODE,READONLY ; --- da_findPage --- ; ; On entry: R2 == address of the page ; ; On exit: R0 == page number ; ; Use: Finds the page number of the page with the address given. EXPORT da_findPage da_findPage ROUT STMFD R13!,{R1,R7-R9,R14} ;Stack the link LDR R14,dyn_machine ;Load the machine type CMP R14,#&A3 ;RISC OS 3? BCS %10da_findPage ;Yes -- jump ahead then LDR R9,dyn_pageCount ;Load number of pages-1 MOV R14,#&164 ;Find CAM map (RO 2 and 3!) ADD R9,R14,R9,LSL #2 ;Last valid entry MOV R8,R2,LSL #4 ;The address of interest << 4 SUB R7,R14,#4 ;We're pre-indexing 00da_findPage CMP R7,R9 ;Have we finished? LDRNE R1,[R7,#4]! ;Load out the entry TEQNE R8,R1,LSL #4 ;Is this a match? BNE %00da_findPage ;No -- keep on looking TEQ R8,R1,LSL #4 ;Was that a match? SUBEQ R7,R7,R14 ;Yes -- get offset from base MOVEQ R0,R7,LSR #2 ;And turn into page number MOVNE R0,#-1 ;Otherwise return -1 LDMFD R13!,{R1,R7-R9,PC}^ ;Return to caller ; --- We are on RISC OS 3 --- 10da_findPage MOV R1,#0 ;Start at this page MOV R14,#-1 ;Get a terminator STMDB R13!,{R1,R2,R3,R14} ;Store that in block MOV R0,R13 ;Point to the block SWI OS_FindMemMapEntries ;Find the page number LDR R0,[R13],#16 ;Load the page number LDMFD R13!,{R1,R7-R9,PC}^ ;Return to caller LTORG ; --- da_addPages --- ; ; On entry: R0 == number of pages to add ; R12 == workspace address ; ; On exit: Possible error returned ; ; Use: Increases the size of the dynamic area by the number of ; pages given in R0 EXPORT da_addPages da_addPages ROUT STMFD R13!,{R0-R9,R14} ;Save some registers LDR R9,dyn_machine ;What machine are we on? CMP R9,#&A5 ;Is it a RISC PC? BGE %50da_addPages ;Yes -- do things differently MOVS R9,R0 ;Remember this value BEQ %10da_addPages ;Nothing to do -- return LDR R14,dyn_sprSize ;Get address of spr area size LDR R14,[R14] ;Get the size out LDR R1,dyn_areaSize ;Find our area size SUB R4,R14,R1 ;Find top of system sprites ADD R2,R4,#&01400000 ;Top of sprite area LDR R3,dyn_log2PageSize ;Find page size of machine MOV R5,R9,LSL R3 ;Find size in bytes LDR R3,dyn_pageSize ;Find real page size MOV R1,R5 ;We want this in R1 too MOV R0,#3 ;Change sprite area size SWI XOS_ChangeDynamicArea ;Yes... do it now! BVS %99da_addPages ;Error -- return ; --- Make sure system sprite size remains the same --- MOV R14,#&01400000 ;Get address of sprite area STR R4,[R14,#0] ;Get system sprite size ; --- Work out how big dynamite area is now --- LDR R14,dyn_areaSize ;Get the previous size RSB R8,R14,#&01800000 ;Put new blocks here ADD R14,R14,R5 ;The new size STR R14,dyn_areaSize ;Save this size back ; --- Now we need to map up the area --- SUB R13,R13,#16 ;Get me a mem map block MOV R14,#0 ;A nice 0 thing STR R14,[R13,#8] ;Protection level MOV R14,#-1 ;The terminator STR R14,[R13,#12] ;Put that in the block 00da_addPages SUB R8,R8,R3 ;Next page goes here BL da_findPage ;Find page number of R2 STR R0,[R13,#0] ;Store the page number STR R8,[R13,#4] ;Put that page here please MOV R0,R13 ;Point to the block SWI XOS_SetMemMapEntries ;Set mem map entries SUBS R9,R9,#1 ;Reduce page count ADD R2,R2,R3 ;Now move next page BGT %00da_addPages ;Keep doing that then ADD R13,R13,#16 ;Get the block back ; --- Phew! -- almost there --- CMP R4,#0 ;Is there a sprite area? MOVNE R4,#&01400000 ;Yes -- get its address MOV R14,#&1000 ;VDU driver workspace STR R4,[R14,#1364] ;And store as sprite area ptr 10da_addPages LDMFD R13!,{R0-R9,PC}^ ;Return to caller ; --- We are on a RISC PC --- 50da_addPages LDR R1,dyn_log2PageSize ;Get the log 2 page size MOV R1,R0,LSL R1 ;Work out increment LDR R0,dyn_areaHandle ;Load the area handle SWI XOS_ChangeDynamicArea ;And increase appropriately LDRVC R14,dyn_areaSize ;Load the old area size ADDVC R14,R14,R1 ;Apply our increment to it STRVC R14,dyn_areaSize ;And save it back again LDMVCFD R13!,{R0-R9,PC}^ ;Return to caller 99da_addPages LDMFD R13!,{R0-R9,R14} ;Load back registers ADR R0,da__noMem ;Point to error ORRS PC,R14,#V_flag ;Return with error da__noMem DCD 1 DCB "No pages left",0 ; --- da_removePages --- ; ; On entry: R0 == number of pages to remove ; ; On exit: -- ; ; Use: Removes the given number of pages from the dynamite ; area. If the number of pages to remove is greater than ; the actual number of pages allocated, as many as possible ; are removed EXPORT da_removePages da_removePages ROUT STMFD R13!,{R0-R10,R14} ;Stack some registers LDR R9,dyn_machine ;What machine are we on? CMP R9,#&A5 ;Is it a RISC PC? BGE %50da_removePages ;Yes -- do things differently MOV R9,R0 ;Remember this value LDR R8,dyn_areaSize ;Get my area size RSB R2,R8,#&01800000 ;The lowest page LDR R5,dyn_log2PageSize ;Get the page size MOV R7,R8,LSR R5 ;Number of dynamite pages CMP R9,R7 ;Are we in range? MOVGT R9,R7 ;No -- we are now CMP R9,#0 ;Are we removing 0 pages? BEQ %99da_removePages ;Yes -- return now LDR R14,dyn_sprSize ;Get address of spr area size LDR R14,[R14] ;Get the size out LDR R1,dyn_areaSize ;Find our area size SUB R10,R14,R1 ;Find top of system sprites ADD R6,R10,#&01400000 ;Top of sprite area SUB R14,R8,R9,LSL R5 ;The new dynamite size STR R14,dyn_areaSize ;Store this away nicely ; --- Now we need to map down the area --- LDR R3,dyn_pageSize ;Get the page size MOV R4,R9 ;Look after the page count SUB R13,R13,#16 ;Get me a mem map block MOV R14,#0 ;A nice 0 thing STR R14,[R13,#8] ;Protection level MOV R14,#-1 ;The terminator STR R14,[R13,#12] ;Put that in the block 00 BL da_findPage ;Find page number of R2 STR R0,[R13,#0] ;Store the page number STR R6,[R13,#4] ;Put that page here please MOV R0,R13 ;Point to the block SWI XOS_SetMemMapEntries ;Set mem map entries ADD R2,R2,R3 ;Now move next page ADD R6,R6,R3 ;Put the next one here SUBS R9,R9,#1 ;Reduce page count BGT %00da_removePages ;Keep doing that then ADD R13,R13,#16 ;Get the block back CMP R10,#0 ;Was there an area before BNE %10da_removePages ;Yes -- all ok then LDR R6,dyn_sprSize ;Get address of spr area size LDR R6,[R6] ;Get the size out MOV R7,#0 ;Sprite area header MOV R8,#16 MOV R9,#16 MOV R2,#&1400000 ;Point to sprite area STMIA R2,{R6-R9} ;Store the header 10 MOV R1,R4,LSL R5 ;We reduce by this amount RSB R1,R1,#0 ;Make it negative MOV R0,#3 ;Change sprite area size SWI XOS_ChangeDynamicArea ;Remove those damn pages B %99da_removePages ;Return to caller ; --- We're on a RISC PC --- 50 LDR R1,dyn_log2PageSize ;Get the log 2 page size MOV R1,R0,LSL R1 ;Work out increment RSB R1,R1,#0 ;Negate it nicely LDR R0,dyn_areaHandle ;Load the area handle SWI XOS_ChangeDynamicArea ;And increase appropriately LDR R14,dyn_areaSize ;Load the current size SUB R14,R14,R1 ;How much was it altered by? STR R14,dyn_areaSize ;And save that back 99 LDMFD R13!,{R0-R10,PC}^ ;Return to caller LTORG ; --- da_readSize --- ; ; On entry: -- ; ; On exit: R0 == size of area ; ; Use: Returns the size of the sprite area (including the ; dynamite area). EXPORT da_readSize da_readSize ROUT LDR R0,dyn_machine ;What machine are we on? CMP R0,#&A5 ;Is it a RISC PC? BGE %50da_readSize ;Yes -- do other things LDR R0,dyn_sprSize ;Get spr area size pointer LDR R0,[R0,#0] ;Load out the size MOVS PC,R14 ;And return to caller ; --- We're on a RISC PC --- 50da_readSize STMFD R13!,{R1,R14} ;Stack some registers MOV R0,#3 ;Read size of sprite area SWI XOS_ReadDynamicArea ;Read things out then MOV R0,R1 ;Put size in R0 LDMFD R13!,{R1,PC}^ ;Return to caller LTORG ; --- da_describe --- ; ; On entry: -- ; ; On exit: R0 == dynamic area number (3 == sprite area) ; R1 == size of area ; R2 == total free in area ; ; Use: Gives back som information on the dynamite area. EXPORT da_describe da_describe ROUT LDR R0,dyn_machine ;Load out the machine type CMP R0,#&A5 ;Is it a RISC PC? LDRGE R0,dyn_areaHandle ;Yes -- load dynamic area hnd MOVLT R0,#-1 ;No -- return a silly value LDR R1,dyn_areaSize ;Put area size in R1 LDR R2,dyn_heapSize ;And heap size in R2 SUB R2,R1,R2 ;Get size of unused area MOVS PC,R14 ;Return to caller LTORG ;----- That's all, folks ---------------------------------------------------- END