;:ts=8 INCLUDE "exec/types.i" INCLUDE "exec/ables.i" INCLUDE "exec/memory.i" ABSEXECBASE EQU 4 XREF _LVOAllocMem XREF _LVOFreeMem XDEF LoadSeg XDEF UnLoadSeg MAXNAMELEN EQU 128 HUNK_HEADER EQU 1011 ;------ LoadSeg ------------------------------------------------------ ; ; NAME ; LoadSeg - load a file into memory and relocate it ; ; SYNOPSIS ; success = LoadSeg(allocFunc, freeFunc, readFunc, ; d0 a0 a1 a2 ; readHandle, dataEnviron) ; d1 a6 ; ; actual = readFunc(readHandle, buffer, length) ; d0 d1 a0 d0 ; ; memory = allocFunc(size, flags) ; d0 d0 d1 ; ; freeFunc(memory, size) ; a1 d0 ; ; EXCEPTIONS ; This LoadSeg fails if resident or overlay hunks exist. ; ;--------------------------------------------------------------------- lsv_DataEnviron EQU 0 ; function argument passed in a6 lsv_ReadFunc EQU lsv_DataEnviron-4 lsv_FreeFunc EQU lsv_ReadFunc-4 lsv_AllocFunc EQU lsv_FreeFunc-4 lsv_ReadHandle EQU lsv_AllocFunc-4 lsv_Segment EQU lsv_ReadHandle-4 lsv_Name EQU lsv_Segment-MAXNAMELEN lsv_LINKSIZE EQU lsv_Name-4 ; ; d2 various temporaries ; d3 hunk relocation offset value ; d4 byte limit of current hunk ; d5 first hunk slot ; d6 last hunk slot ; a2 current hunk address ; a3 segment tail ; a4 hunk table ; a5 lsv structure ; a6 scratch data area ; LoadSeg: movem.l d2-d6/a2-a5,-(a7) link a6,#lsv_LINKSIZE move.l a6,a5 movem.l d1/a0/a1/a2,lsv_ReadHandle(a5) moveq #0,d6 move.l d6,lsv_Segment(a5) move.l d6,a4 ;-- ensure this is a valid load file bsr GetLong cmp.l #HUNK_HEADER,d0 bne lsFail ;-- handle resident library header by failing if it exists bsr GetLong tst.l d0 bne lsFail ;-- handle hunks bsr GetLong ; get table size bsr GetLong ; get first hunk slot move.l d0,d5 bsr GetLong ; get last hunk slot move.l d0,d6 ;-- allocate the temporary hunk table via Exec AllocMem addq.l #1,d0 ; last slot + 1 long words lsl.l #2,d0 ; in bytes moveq #0,d1 move.l ABSEXECBASE,a6 jsr _LVOAllocMem(a6) tst.l d0 beq lsFail move.l d0,a4 ;-- allocate the hunks themselves lsAllocHunks: move.w d5,d2 lsl.w #2,d5 lea 0(a4,d5.w),a2 lea lsv_Segment(a5),a3 lsAllocHunk: ;-- for each entry in this file cmp.w d6,d2 bgt.s lsLoadHunks ;-- allocate space for the hunk and cache pointer in the table bsr GetLong ; get size needed beq.s lsEmptyHunk bsr GetVector ; get memory move.l a0,(a2)+ ; cache pointer move.l a0,d0 ; convert lsr.l #2,d0 ; to BPTR move.l d0,(a3) ; and link to end of segment move.l a0,a3 ; new tail lsNextHunk: addq.w #1,d2 ; count up hunk bra.s lsAllocHunk lsEmptyHunk: clr.l (a2)+ bra.s lsNextHunk ;-- read in the load image lsLoadHunks: ; BUG FIX! Terminate the seglist clr.l (a3) moveq #-1,d4 ; byte limit: between hunks lsLoadHunk: ;-- perform GetLong-like function, but EOF is OK here subq.l #4,a7 move.l a7,a0 moveq #4,d0 move.l lsv_ReadHandle(a5),d1 movem.l lsv_ReadFunc(a5),a1/a6 jsr (a1) tst.l d0 ; check for EOF beq lsFreeHunk cmp.l #4,d0 bne lsFail ;-- switch on hunk type move.l (a7)+,d0 andi.l #$3fffffff,d0 sub.l #1000,d0 bmi lsFail cmp.l #HUNKSWITCHLIMIT,d0 bge lsFail add.w d0,d0 move.w lsSwitch(pc,d0.w),d0 jsr lsSwitch(pc,d0.w) bra.s lsLoadHunk lsSwitch: dc.w lssHunkName-lsSwitch dc.w lssHunkCode-lsSwitch dc.w lssHunkData-lsSwitch dc.w lssHunkBSS-lsSwitch dc.w lssHunkReloc32-lsSwitch dc.w lssHunkReloc16-lsSwitch dc.w lssHunkReloc8-lsSwitch dc.w lssHunkExt-lsSwitch dc.w lssHunkSymbol-lsSwitch dc.w lssHunkDebug-lsSwitch dc.w lssHunkEnd-lsSwitch dc.w lssHunkHeader-lsSwitch dc.w lssHunkCont-lsSwitch dc.w lssHunkOverlay-lsSwitch dc.w lssHunkBreak-lsSwitch HUNKSWITCHLIMIT EQU (*-lsSwitch)/2 ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lssHunkName: bsr ReadName ; read name rts ; and ignore ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lssHunkCode: lssHunkData: ;-- get hunk size bsr GetLong ;-- get new byte limit lsl.l #2,d0 move.l d0,d4 subq.l #4,d4 ;-- get hunk base move.l 0(a4,d5.w),a2 ; get table entry addq.l #4,a2 ; skip next segment pointer addq.l #4,d5 ; bump hunk number ;-- load in the code move.l d0,d2 beq.s lsshdReturn move.l a2,a0 move.l lsv_ReadHandle(a5),d1 movem.l lsv_ReadFunc(a5),a1/a6 jsr (a1) cmp.l d2,d0 bne lssFail lsshdReturn: rts ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lssHunkBSS: ;-- get hunk size bsr GetLong ;-- get new byte limit move.l d0,d4 lsl.l #2,d4 subq.l #4,d4 ;-- get hunk base move.l 0(a4,d5.w),a2 ; get table entry addq.l #4,a2 ; skip next segment pointer addq.l #4,d5 ; bump hunk number ;-- clear the bss area move.l a2,a0 moveq #0,d1 move.w d0,d2 ; low word swap d0 ; high word bra.s lsshbssDBF lsshbssLoop: move.l d1,(a0)+ lsshbssDBF: dbf d2,lsshbssLoop dbf d0,lsshbssLoop rts ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lssHunkReloc32: bsr GetLong move.w d0,d2 beq.s lsshrReturn bsr GetLong cmp.l d6,d0 bgt.s lssFail lsl.w #2,d0 move.l 0(a4,d0.w),d3 ; get table entry addq.l #4,d3 ; skip next segment pointer subq.w #1,d2 lsshrRelocLoop: bsr GetLong ;-- ensure within hunk bmi.s lssFail cmp.l d4,d0 bgt.s lssFail add.l d3,0(a2,d0.l) ; add base to offset dbf d2,lsshrRelocLoop bra.s lssHunkReloc32 lsshrReturn: rts ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lssHunkSymbol: bsr ReadName ; flush symbol name tst.l d0 ; check symbol length beq.s lsshsDone ; end of symbol hunk if zero bsr GetLong ; flush symbol value bra.s lssHunkSymbol lsshsDone: rts ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lssHunkDebug: bsr GetLong move.w d0,d2 bra.s lsshdDBF lsshdLoop: bsr GetLong lsshdDBF: dbf d2,lsshdLoop rts ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lssHunkEnd: moveq #-1,d4 ; flag end in limit rts ; (it's OK to see EOF now) ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lssFail: lssHunkReloc16: lssHunkReloc8: lssHunkExt: lssHunkHeader: lssHunkCont: lssHunkOverlay: lssHunkBreak: moveq #0,d4 ; flag error addq.l #4,a7 ; pop switch return address ; fall thru to lsFreeHunk ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . lsFreeHunk: move.l a4,d0 beq.s lsCheckOK ;-- free the temporary hunk table via Exec FreeMem move.l d6,d0 ; recover last slot addq.l #1,d0 ; last slot + 1 long words lsl.l #2,d0 ; in bytes move.l a4,a1 move.l ABSEXECBASE,a6 jsr _LVOFreeMem(a6) ;-- check for error lsCheckOK: cmp.l #-1,d4 beq.s lsOK ;-- unload the segment move.l lsv_Segment(a5),d1 move.l lsv_FreeFunc(a5),a1 move.l lsv_DataEnviron(a5),a6 bsr UnLoadSeg moveq #0,d0 bra.s lsReturn lsOK: ;-- return list head BPTR as result move.l lsv_Segment(a5),d0 lsReturn: move.l a5,a6 unlk a6 movem.l (a7)+,d2-d6/a2-a5 rts lsFail: moveq #0,d4 bra.s lsFreeHunk ; - - - GetLong - - - - - - - - - - - - - - - - - - - - - - - - - - - ; ; INPUT ; a4 readHandle ; a4 readFunc ; ; RESULT ; d0 next longword in stream ; ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GetLong: subq.l #4,a7 move.l a7,a0 moveq #4,d0 move.l lsv_ReadHandle(a5),d1 movem.l lsv_ReadFunc(a5),a1/a6 jsr (a1) cmp.l #4,d0 bne.s gFail move.l (a7)+,d0 rts ; - - - ReadName - - - - - - - - - - - - - - - - - - - - - - - - - - ; ; INPUT ; a5 lsv structure ; ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ReadName: bsr.s GetLong lsl.l #2,d0 beq.s rnReturn cmp.l #MAXNAMELEN,d0 bge.s rnFail lea lsv_Name(a5),a0 move.l d0,-(a7) move.l lsv_ReadHandle(a5),d1 movem.l lsv_ReadFunc(a5),a1/a6 jsr (a1) cmp.l (a7)+,d0 bne.s rnFail rnReturn: rts rnFail: addq.l #4,a7 bra.s lsFail ; - - - GetVector - - - - - - - - - - - - - - - - - - - - - - - - - - ; ; INPUT ; d0 vector size (without size prefix), in longwords, with memory ; flags CHIP and FAST in bits 30 and 31 ; ; RESULT ; a0 vector ; ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - GetVector: move.l d0,d1 lsl.l #2,d0 addq.l #4,d0 move.l d0,-(a7) addq.l #4,d0 rol.l #3,d1 and.l #6,d1 ; mask to MEMF_FAST+MEMF_CHIP move.l lsv_AllocFunc(a5),a1 move.l lsv_DataEnviron(a5),a6 jsr (a1) tst.l d0 bne.s gvCacheSize gFail: addq.l #8,a7 bra lsFail gvCacheSize: move.l d0,a0 move.l (a7)+,(a0) addq.l #4,a0 rts ;------ UnLoadSeg ---------------------------------------------------- ; ; UnLoadSeg(segment, freeFunc, dataEnviron) ; d1 a1 a6 ; ; freeFunc(memory, size) ; a1 d0 ; ; EXCEPTIONS ; ;--------------------------------------------------------------------- UnLoadSeg: movem.l d2/a2,-(a7) move.l d1,d2 move.l a1,a2 bra.s usNext usLoop: ;-- free this hunk move.l (a1),d2 ; cache next segment move.l -(a1),d0 ; get size addq.l #4,d0 jsr (a2) usNext: lsl.l #2,d2 ; get next segment beq.s ulDone move.l d2,a1 bra.s usLoop ulDone: movem.l (a7)+,d2/a2 rts end