;-------------------------------------------------------------------- ; Load, decrunch and run the given part ; ; Searches for the given file name on disk, allocates enough memory ; to load the compressed hunks, decrunches them (maybe in-place) ; relocates the hunks, executes an optional pre-launch hook ; and finally calls the loaded part. ; ; A part may have been preloaded using PreloadPart in which case the ; loading from disk is skipped and only the allocation and decrunching ; happens. ; ; Restores the framework base to the default after execution and ; frees all memory allocated. ; ; In : a0 = filename ; Trashes: probably all registers ; fw_ExecuteNextPart: PUTMSG 10,<10,"%d: *** Preparing to execute next part %s ***">,fw_FrameCounterLong(a6),a0 bsr.s fw_LoadNextPart PUSHM a0 bsr fw_CheckPrePartLaunchHook POPM IF FW_MUSIC_SUPPORT PUTMSG 10,<"%d: *** Executing next part %p at music frame %d">,fw_FrameCounterLong(a6),a0,fw_MusicFrameCount-2(a6) ELSE PUTMSG 10,<"%d: *** Executing next part %p">,fw_FrameCounterLong(a6),a0 ENDC jsr (a0) IF FW_MUSIC_SUPPORT PUTMSG 10,<"%d: *** Part finished at music frame %d",10>,fw_FrameCounterLong(a6),fw_MusicFrameCount-2(a6) ELSE PUTMSG 10,<"%d: *** Part finished",10>,fw_FrameCounterLong(a6) ENDC bsr fw_RestoreFrameworkBase bsr fw_DropCurrentMemoryAllocations rts ;-------------------------------------------------------------------- ; Load and decrunch given part ; ; Searches for the given file name on disk, allocates enough memory ; to load the compressed hunks, decrunches them (maybe in-place) ; and relocates the hunks. Part is not executed, stores the loading ; address of first (typically code) hunk in fw_LastLoadedPart(a6). ; Note that this also allocates BSS hunks if there any. ; ; This can be used for background loading the next part. ; See also PreloadPart for an alternative without decrunching. ; ; In : a0 = filename ; Out: a0 = loading address of first hunk ; Trashes: probably all registers ; fw_LoadNextPart: PUTMSG 10,<10,"%d: *** Loading next part %s ***">,fw_FrameCounterLong(a6),a0 clr.l fw_LastLoadedPart(a6) bsr fw_DropCurrentMemoryAllocations bsr fw_FindFile bsr fw_LoadAndDecrunchPart move.l a0,fw_LastLoadedPart(a6) rts ;-------------------------------------------------------------------- ; Wait until next part has been loaded (and decrunched) ; ; Can be used if a background task is used to load the next part to ; to ensure the loading and decrunching has finished. ; IF FW_MULTITASKING_SUPPORT fw_WaitForPartLoaded: tst.l fw_LastLoadedPart(a6) bne.s .done PUTMSG 10,<"%d: Part not yet fully loaded. Waiting.">,fw_FrameCounterLong(a6) .loop bsr fw_Yield tst.l fw_LastLoadedPart(a6) beq.s .loop .done rts ENDC ;-------------------------------------------------------------------- ; Check and execute the pre-part launch hook ; ; Internal function to execute a hook that is supposed to be called ; just before ExecuteNextPart starts the part after loading/decrunching. ; ; Hooks can be installed by writing fw_PrePartLaunchHook(a6). ; If this field is NULL, this function does nothing. ; fw_PrePartLaunchHook(a6) is cleared prior to executing the hook. ; fw_CheckPrePartLaunchHook: move.l fw_PrePartLaunchHook(a6),d0 beq.s .skip clr.l fw_PrePartLaunchHook(a6) move.l d0,a0 PUTMSG 10,<"Executing pre-part launch hook at %p">,a0 jmp (a0) .skip rts ;-------------------------------------------------------------------- ; Poor-man's multi disk check ; ; Waits for a disk-change, then re-initializes the loader and reads ; the new directory. This is currently untested and might not work ; well with multiple drives. ; ; In : d0.l = First four bytes of first filename on expected disk. ; IFEQ FW_HD_TRACKMO_MODE fw_NextDisk: move.l d0,fw_ExpectedFirstFileID(a6) bsr fw_TrackloaderWaitForDiskChange ;bra.b fw_InitDos ENDC ;-------------------------------------------------------------------- ; Initializes the trackloader and reads the disk directory fw_InitDos: IF FW_MULTITASKING_SUPPORT move.l fw_TrackloaderTask(a6),a1 move.b #-10,LN_PRI(a1) ; FIXME breaks things! Why? IFNE DEBUG_DETAIL lea .loadertask(pc),a0 move.l a0,LN_NAME(a1) ENDC ENDC tst.l fw_DirBuffer(a6) bne.s .hasmem move.l #FW_NUM_DIRECTORY_BLOCKS*512,d0 bsr fw_AllocFast move.l a0,fw_DirBuffer(a6) IFEQ FW_HD_TRACKMO_MODE move.l #'Plat',fw_ExpectedFirstFileID(a6) ; Standard ID for launcher, change ID to detect a second disk ENDC .hasmem .retry IFEQ FW_HD_TRACKMO_MODE bsr fw_TrackloaderDiskMotorOn ENDC move.l fw_DirBuffer(a6),a0 PUTMSG 10,<"Directory at %p">,a0 move.l #FW_DIRECTORY_ENTRIES_OFFSET,d0 ; second block move.l #FW_NUM_DIRECTORY_BLOCKS*512,d1 bsr fw_TrackloaderLoad IFEQ FW_HD_TRACKMO_MODE move.l fw_DirBuffer(a6),a0 move.l fw_ExpectedFirstFileID(a6),d0 cmp.l (a0),d0 bne.s .otherdisk rts .otherdisk PUTMSG 10,<"Wrong disk %lx">,(a0) move.w fw_CurrentDrive(a6),d0 addq.w #1,d0 move.w d0,fw_CurrentDrive(a6) cmp.w #4,d0 bne.s .retry move.w #ERROR_DISK,d0 bra fw_Error ELSE rts ENDC IFNE DEBUG_DETAIL .loadertask dc.b "Loadertask",0 even ENDC ;-------------------------------------------------------------------- ; Locates the DirEntry of a file on disk ; ; The DirEntry contains the meta-data for a file on disk ; (see framework.i). ; ; In : a0 = filename ; Out: a1 = Dir entry structure ; fw_FindFile: PUTMSG 10,<"Searching for %s...">,a0 move.l fw_DirBuffer(a6),a1 .restartloop moveq.l #0,d0 .loop move.b de_Name(a1,d0.w),d1 cmp.b (a0,d0.w),d1 bne.s .next addq.w #1,d0 tst.b d1 beq .foundit cmp.w #16,d0 beq .foundit bra.s .loop .next PUTMSG 40,<"%s did not match">,a1 .nextline tst.w de_Flags(a1) bpl.s .nextentry PUTMSG 40,<"NL"> lea de_NextHunk(a1),a1 bra.s .nextline .nextentry lea de_SIZEOF(a1),a1 tst.b de_Name(a1) beq.s .notfound PUTMSG 40,<"Next Entry %s">,a1 bra .restartloop .notfound PUTMSG 10,<"File %s not found">,a0 move.w #ERROR_FILE_NOT_FOUND,d0 bra fw_Error .foundit PUTMSG 10,<"Found %s at %p">,a1,a1 rts ;-------------------------------------------------------------------- ; Allocate and load a file (filename) from disk without decrunching ; ; Allocates sufficient memory and loads the possibly compressed file ; from the directory into this memory. File will be loaded to fast ; memory if crunched, otherwise memory allocation depends on the ; flags. Note that this call is not useful for DOS hunk files. ; ; In : a0 = filename ; Out: a0 = start of loaded file in a0 ; a1 = Dir entry structure of the file ; fw_LoadFile: bsr fw_FindFile move.w #DEFM_PACKMODE,d0 and.w de_Flags(a1),d0 bne.s fw_LoadPlainFileEntryToFast ;-------------------------------------------------------------------- ; Allocate and load a file via DirEntry from disk without decrunching ; ; Allocates sufficient memory and loads the possibly compressed file ; from the directory into this memory. File will be loaded to the ; type of memory specified in the DirEntry. ; Note that this call is not useful for DOS hunk files. ; ; In : a1 = Dir entry structure ; Out: a0 = start of loaded file in a0 ; a1 = Dir entry structure of the file ; fw_LoadPlainFileEntry: PUTMSG 10,<"%d: Loading plain file from offset %ld, size %ld">,fw_FrameCounterLong(a6),de_DiskOffset(a1),de_DiskLength(a1) tst.b de_Flags+1(a1) bpl.s fw_LoadPlainFileEntryToFast move.l de_DiskLength(a1),d0 move.l a1,-(sp) bsr fw_AllocChip bra.s fw_InternalLoadFileEntryToBuffer ;-------------------------------------------------------------------- ; Allocate and load a file via DirEntry from disk to fast mem ; ; Allocates sufficient memory and loads the possibly compressed file ; from the directory into this memory. File will be loaded to ; fast memory, if available. ; ; In : a1 = DirEntry ; Out: a0 = start of loaded file in a0 ; a1 = DirEntry of the file ; fw_LoadPlainFileEntryToFast: IFEQ FW_HD_TRACKMO_MODE fw_LoadReadOnlyPlainFileEntryToFast: ENDC move.l de_DiskLength(a1),d0 move.l a1,-(sp) bsr fw_AllocFast fw_InternalLoadFileEntryToBuffer: move.l (sp)+,a1 bsr fw_LoadFileToBuffer move.l de_DiskLength(a1),d0 rts IFNE FW_HD_TRACKMO_MODE fw_LoadReadOnlyPlainFileEntryToFast: move.l de_DiskLength(a1),d0 move.l fw_TrackBuffer(a6),a0 adda.l de_DiskOffset(a1),a0 fw_TrackloaderDiskMotorOff: rts ENDC ;-------------------------------------------------------------------- ; Load a file from disk and decrunch it ; ; Allocates sufficient memory and loads the possibly compressed file ; from the directory into this memory. File will be decompressed to ; chip or fast memory depending on its flags. ; Allocation may be slightly bigger if file is decrunchable in-place, ; but uses no additional memory for the compressed data in this case. ; ; Note that this call is not useful for DOS hunk files. ; ; In : a0: Filename ; Out: a0: Pointer to loaded buffer ; a1: Dir entry structure ; fw_LoadAndDecrunchFile: bsr fw_FindFile move.w #DEFM_PACKMODE,d0 and.w de_Flags(a1),d0 beq fw_LoadPlainFileEntry PUTMSG 10,<"File %s is crunched">,a1 IFEQ FW_HD_TRACKMO_MODE IF FW_ZX0_SUPPORT btst #DEFB_IN_PLACE,de_Flags(a1) bne.s .inplacedecrunch ENDC ENDC move.l a1,-(sp) ; dir entry move.l de_MemorySize(a1),d0 tst.b de_Flags+1(a1) bpl.s .usefast bsr fw_AllocChip bra.s .allocated .usefast bsr fw_AllocFast .allocated move.l a0,-(sp) ; target buffer IFEQ FW_HD_TRACKMO_MODE bsr fw_PushMemoryState move.l de_DiskLength(a1),d0 bsr fw_AllocFast move.l 4(sp),a1 ; dir entry bsr fw_LoadFileToBuffer move.l (sp),a2 ; target buffer bsr fw_DecrunchToBuffer move.l de_MemorySize(a1),d0 bsr fw_PopMemoryState ELSE move.l a0,a2 move.l 4(sp),a1 move.l fw_TrackBuffer(a6),a0 adda.l de_DiskOffset(a1),a0 bsr fw_DecrunchToBuffer move.l de_MemorySize(a1),d0 ENDC move.l (sp)+,a0 ; target buffer move.l (sp)+,a1 ; dir entry rts IFEQ FW_HD_TRACKMO_MODE IF FW_ZX0_SUPPORT .inplacedecrunch bsr.s fw_AllocInPlaceDecrunchBuffer PUSHM a0 bsr.s fw_LoadAndInPlaceDecrunchToBuffer POPM rts ENDC ENDC ;-------------------------------------------------------------------- ; Allocate buffer big enough to hold decrunched data + safety distance ; ; In : a1 = dir entry (preserved) ; Out: a0 = buffer ; fw_AllocInPlaceDecrunchBuffer: PUSHM a1 move.l de_MemorySize(a1),d0 addq.l #1,d0 and.w #-2,d0 add.l #FW_IN_PLACE_DECR_SAFE_DIST,d0 tst.b de_Flags+1(a1) bpl.s .usefast2 bsr fw_AllocChip bra.s .allocated2 .usefast2 bsr fw_AllocFast .allocated2 POPM rts ;-------------------------------------------------------------------- ; Loads a crunched file to the end of a pre-allocated buffer and decrunches it in-place ; ; In : a0 = target buffer (memory size of decrunched + safety distance) ; a1 = dir entry (preserved) ; Out: a0 = end of decrunched buffer ; fw_LoadAndInPlaceDecrunchToBuffer: move.l a0,-(sp) move.l de_DiskLength(a1),d0 addq.l #1,d0 and.w #-2,d0 lea FW_IN_PLACE_DECR_SAFE_DIST(a0),a0 move.l de_MemorySize(a1),d1 addq.l #1,d1 and.w #-2,d1 adda.l d1,a0 suba.l d0,a0 bsr fw_LoadFileToBuffer move.l (sp)+,a2 ; target buffer ;bra.s fw_DecrunchToBuffer ;-------------------------------------------------------------------- ; Decrunches the given file to the target buffer ; ; In : a0 = source buffer ; a1 = Dir entry structure ; a2 = target buffer ; Out: a0 = END of the buffer written ; a1 = Dir entry structure ; fw_DecrunchToBuffer: PUSHM a1/a2 move.w #DEFM_PACKMODE,d0 and.w de_Flags(a1),d0 IF FW_DOYNAX_SUPPORT cmp.w #DEFF_DOYNAX,d0 bne.s .nodoynax PUTMSG 10,<"%d: DoynaxDecrunch from %p (%ld) to %p (%ld)">,fw_FrameCounterLong(a6),a0,de_DiskLength(a1),a2,de_MemorySize(a1) move.l a2,a1 bsr doynaxdepack bra .decdone .nodoynax ENDC IF FW_ZX0_SUPPORT cmp.w #DEFF_ZX0,d0 bne.s .nozx0 PUTMSG 10,<"%d: ZX0Decrunch from %p (%ld) to %p (%ld)">,fw_FrameCounterLong(a6),a0,de_DiskLength(a1),a2,de_MemorySize(a1) move.l a2,a1 bsr zx0_decompress bra.s .decdone .nozx0 ENDC IF FW_LZ4_SUPPORT cmp.w #DEFF_LZ4,d0 bne.s .nolz4 move.l de_DiskLength(a1),d0 PUTMSG 10,<"%d: LZ4Decrunch from %p (%ld) to %p (%ld)">,fw_FrameCounterLong(a6),a0,d0,a2,de_MemorySize(a1) move.l a2,a1 bsr lz4_depack bra.s .decdone .nolz4 ENDC move.w #ERROR_INVALID_PARAMS,d0 bra fw_Error .decdone move.l a1,a0 POPM move.w #DEFM_DELTAMODE,d0 and.w de_Flags(a1),d0 beq.s .nodelta cmp.w #DEFF_DELTA8,d0 beq.s .delta8 move.w #ERROR_INVALID_PARAMS,d0 bra fw_Error .delta8 PUSHM a2 move.l de_MemorySize(a1),d0 beq.s .d8done PUTMSG 10,<"%d: Delta8 decoding %p %ld bytes">,fw_FrameCounterLong(a6),a2,d0 moveq.l #0,d1 subq.l #1,d0 .d8loop add.b (a2),d1 move.b d1,(a2)+ dbra d0,.d8loop swap d0 subq.w #1,d0 bcs.s .d8done swap d0 bra.s .d8loop .d8done POPM .nodelta PUTMSG 10,<"%d: Decrunching done">,fw_FrameCounterLong(a6) rts ;-------------------------------------------------------------------- ; Loads the file into the given buffer ; ; In : a0 = buffer (preserved) ; a1 = Dir entry structure (preserved) ; fw_LoadFileToBuffer: PUSHM a0-a3 move.l de_DiskOffset(a1),d0 move.l de_DiskLength(a1),d1 PUTMSG 10,<"%d: Loading file %p to buffer %p (%ld)">,fw_FrameCounterLong(a6),a1,a0,d1 bsr fw_TrackloaderLoad POPM rts ;-------------------------------------------------------------------- ; Loads and uncompresses the (LZ4) file into the given buffer ; ; Loads and decrunches the given LZ4 or LZ4 delta compressed file while ; loading it from disk -- needs no extra memory. ; ; In : a0 = target buffer ; a1 = Dir entry structure ; Out: a1 = end of decrunching pointer ; fw_TrackmoLoadAndDecrunchToBuffer: PUTMSG 10,<"%d: Trackmo Loading and Decrunching %p">,fw_FrameCounterLong(a6),a1 move.w #DEFM_PACKMODE,d0 and.w de_Flags(a1),d0 IF FW_TRACKMO_LZ4_SUPPORT|FW_TRACKMO_LZ4_DLT8_SUPPORT cmp.w #DEFF_LZ4,d0 bne.s .nolz4 move.l de_DiskOffset(a1),d0 move.l de_DiskLength(a1),d1 move.w #DEFM_DELTAMODE,d2 and.w de_Flags(a1),d2 IF FW_TRACKMO_LZ4_SUPPORT cmp.w #DEFF_NODELTA,d2 beq fw_TrackloaderLoadAndDecrunchLZ4 ENDC IF FW_TRACKMO_LZ4_DLT8_SUPPORT cmp.w #DEFF_DELTA8,d2 beq fw_TrackloaderLoadAndDecrunchLZ4Delta8 ENDC .nolz4 ENDC .error move.w #ERROR_INVALID_PARAMS,d0 bra fw_Error ;-------------------------------------------------------------------- ; Load and decrunch a part ; ; Reads, allocates, decrunches and relocates all hunks for the given ; directory entry. ; ; In : a1 = Dir entry structure ; Out: a0 = launch address of first hunk ; fw_LoadAndDecrunchPart: move.l d7,-(sp) PUTMSG 10,<"%d: Loading and Decrunching %p">,fw_FrameCounterLong(a6),a1 tst.b de_NumHunks(a1) bne.s .cont .b0rked move.w #ERROR_HUNKBROKEN,d0 bra fw_Error .cont move.l a1,a2 ; backup top of the dir entries lea fw_HunkPointers(a6),a3 .hunkallocloop moveq.l #0,d7 move.b de_HunkNum(a1),d7 lsl.w #2,d7 PUTMSG 30,<"HunkSize %lx">,de_MemorySize(a1) move.l de_MemorySize(a1),d0 beq.s .skipthat btst #DEFB_IN_PLACE,de_Flags(a1) beq.s .noinplace add.l #FW_IN_PLACE_DECR_SAFE_DIST,d0 .noinplace ; allocate hunk PUSHM a1-a3 tst.b de_Flags+1(a1) bpl.s .nochipmem bsr fw_AllocChip bra.s .gotmem .nochipmem bsr fw_AllocFast .gotmem POPM move.l a0,(a3,d7.w) .skipthat tst.w de_Flags(a1) bpl.s .hunksallocated lea de_NextHunk(a1),a1 bra.s .hunkallocloop .hunksallocated move.l a2,a1 ; start over .hunkloadloop moveq.l #0,d7 move.b de_HunkNum(a1),d7 PUTMSG 10,<"Hunk num %d">,d7 lsl.w #2,d7 moveq.l #DEFM_TYPE,d0 and.w de_Flags(a1),d0 cmp.w #DEFF_HUNK_CODE,d0 beq.s .codedata cmp.w #DEFF_HUNK_DATA,d0 beq.s .codedata cmp.w #DEFF_HUNK_BSS,d0 beq .justclear cmp.w #DEFF_HUNK_RELOC,d0 beq .reloc bra .b0rked .codedata move.w #DEFM_PACKMODE,d0 and.w de_Flags(a1),d0 beq .unpacked move.l fw_PreloadHunkPointers-fw_HunkPointers(a3,d7.w),d1 beq.s .loadpacked PUSHM a2-a3 move.l (a3,d7.w),a2 move.l d1,a0 clr.l fw_PreloadHunkPointers-fw_HunkPointers(a3,d7.w) PUTMSG 10,<"Decrunching packed data from preload buffer %p to %p">,a0,a2 bsr fw_DecrunchToBuffer POPM bra .clearmem .loadpacked IF FW_ZX0_SUPPORT btst #DEFB_IN_PLACE,de_Flags(a1) bne.s .inplacedecrunch ENDC IF FW_LZ4_SUPPORT IF FW_TRACKMO_LZ4_SUPPORT cmp.w #DEFF_LZ4,d0 beq .trackloadlz4 ELSE cmp.w #DEFF_LZ4,d0 beq.s .genericdecrunch ENDC ENDC IF FW_ZX0_SUPPORT cmp.w #DEFF_ZX0,d0 beq.s .genericdecrunch ENDC IF FW_DOYNAX_SUPPORT cmp.w #DEFF_DOYNAX,d0 beq.s .genericdecrunch ENDC bra .b0rked IF FW_ZX0_SUPPORT|FW_DOYNAX_SUPPORT|(FW_LZ4_SUPPORT&!FW_TRACKMO_LZ4_SUPPORT) .genericdecrunch bsr fw_PushMemoryState PUSHM a1-a3 bsr fw_LoadPlainFileEntryToFast POPM PUSHM a1-a3 move.l (a3,d7.w),a2 ; target buffer bsr fw_DecrunchToBuffer POPM bsr fw_PopMemoryState bra .clearmem ENDC IF FW_ZX0_SUPPORT .inplacedecrunch PUTMSG 10,<"%d: In-place loading and decrunching %ld bytes to %p (%d)">,fw_FrameCounterLong(a6),de_DiskLength(a1),a0,d7 PUSHM a1-a3 move.l (a3,d7.w),a0 bsr fw_LoadAndInPlaceDecrunchToBuffer POPM bra .clearmem ENDC IF FW_TRACKMO_LZ4_SUPPORT .trackloadlz4 move.l (a3,d7.w),a0 PUSHM a1-a3 PUTMSG 10,<"%d: LZ4 loading and decrunching %ld bytes to %p (%d)">,fw_FrameCounterLong(a6),de_DiskLength(a1),a0,d7 bsr fw_TrackmoLoadAndDecrunchToBuffer move.l a1,a0 POPM bra .clearmem ENDC .unpacked move.l fw_PreloadHunkPointers-fw_HunkPointers(a3,d7.w),d0 beq.s .loadunpacked move.l d0,a0 clr.l fw_PreloadHunkPointers-fw_HunkPointers(a3,d7.w) PUTMSG 10,<"Copying unpacked data from preload buffer %p">,a0 move.l de_DiskLength(a1),d0 subq.l #1,d0 bmi.s .clearunpacked lsr.w #2,d0 move.l (a3,d7.w),a2 .upcopyloop move.l (a0)+,(a2)+ dbra d0,.upcopyloop bra.s .clearunpacked .loadunpacked move.l (a3,d7.w),a0 bsr fw_LoadFileToBuffer .clearunpacked move.l de_MemorySize(a1),d0 move.l de_DiskLength(a1),d1 sub.l d1,d0 move.l (a3,d7.w),a0 adda.l d1,a0 bra .clearit .justclear move.l (a3,d7.w),a0 move.l de_MemorySize(a1),d0 bra .clearit .clearmem move.l (a3,d7.w),d0 add.l de_MemorySize(a1),d0 PUTMSG 10,<"%d: End of buffer %p, expected %p, memory size %ld">,fw_FrameCounterLong(a6),a0,d0,de_MemorySize(a1) sub.l a0,d0 ; bytes to clear .clearit tst.l d0 bmi fw_Error lsr.l #2,d0 beq.s .checknexthunk PUTMSG 10,<"Clearing %d longs at end of buffer %p">,d0,a0 subq.w #1,d0 moveq.l #0,d1 .clearloop move.l d1,(a0)+ dbra d0,.clearloop .checknexthunk tst.b de_Flags(a1) bpl .hunksloaded lea de_NextHunk(a1),a1 bra .hunkloadloop .reloc move.l fw_PreloadRelocHunkPointers-fw_HunkPointers(a3,d7.w),d0 beq.s .loadreloc move.l d0,a0 clr.l fw_PreloadRelocHunkPointers-fw_HunkPointers(a3,d7.w) PUTMSG 10,<"Doing Reloc from preloaded data %p">,a0 PUSHM a1 bsr .doreloc POPM bra.s .checknexthunk .loadreloc bsr fw_PushMemoryState PUSHM a1-a3 move.l a3,-(sp) bsr fw_LoadReadOnlyPlainFileEntryToFast move.l (sp)+,a3 bsr .doreloc POPM bsr fw_PopMemoryState bra .checknexthunk .hunksloaded bsr fw_FlushCaches move.l (sp)+,d7 move.l fw_HunkPointers(a6),a0 rts .doreloc move.l (a3,d7.w),a1 ; target-hunk PUTMSG 40,<"Relocating for target hunk %p (%d)">,a1,d7 .hunkrelloop move.w (a0)+,d0 beq.s .hunkrelocend move.w (a0)+,d1 ; source-hunk PUTMSG 50,<"%d offsets for hunk %d">,a0,d1 subq.w #1,d0 lsl.w #2,d1 move.l (a3,d1.w),d2 ; source_hunk offset .offsetsloop moveq.l #0,d1 move.w (a0)+,d1 ; offset add.l d1,d1 add.l d2,(a1,d1.l) ; patch offset into target-hunk dbra d0,.offsetsloop bra.s .hunkrelloop .hunkrelocend rts ;-------------------------------------------------------------------- ; Loads the next part into memory without decrunching or executing it ; ; Preloads a part that will be almost instantly executed when calling ; ExecuteNextPart (because only the decrunching will be done). ; ; This function is usually called from a background task with memory ; allocation direction flipped. Note that the filename given here and ; later to ExecuteNextPart must match exactly, otherwise, bad things ; will happen. ; ; In : a0 = filename ; fw_PreloadPart: IFEQ FW_HD_TRACKMO_MODE bsr fw_FindFile move.l d7,-(sp) PUTMSG 10,<"%d: Preparing loading and decrunching of %p">,fw_FrameCounterLong(a6),a1 tst.b de_NumHunks(a1) bne.s .cont .b0rked move.w #ERROR_HUNKBROKEN,d0 bra fw_Error .cont lea fw_PreloadHunkPointers(a6),a2 lea fw_PreloadRelocHunkPointers(a6),a3 .hunkloadloop moveq.l #0,d7 move.b de_HunkNum(a1),d7 PUTMSG 10,<"Hunk num %d">,d7 lsl.w #2,d7 moveq.l #DEFM_TYPE,d0 and.w de_Flags(a1),d0 cmp.w #DEFF_HUNK_CODE,d0 beq.s .codedata cmp.w #DEFF_HUNK_DATA,d0 beq.s .codedata cmp.w #DEFF_HUNK_BSS,d0 beq.s .ignorehunk cmp.w #DEFF_HUNK_RELOC,d0 bne .b0rked PUSHM a1-a3 bsr fw_LoadPlainFileEntryToFast POPM move.l a0,(a3,d7.w) bra.s .loaded .codedata PUSHM a1-a3 bsr fw_LoadPlainFileEntryToFast POPM move.l a0,(a2,d7.w) .loaded .ignorehunk tst.b de_Flags(a1) bpl .hunksloaded lea de_NextHunk(a1),a1 bra .hunkloadloop .hunksloaded move.l (sp)+,d7 ENDC rts