Hamazing/source/framework/framework_dos.asm
chrisly42 9c48c11cd1 Big "squashed" update to latest version of Framework.
- Bugfix: WaitForFrame was completely broken. Now also caters for race-condition that would have waited one extra frame.
- Bugfix: InitPart would overwrite innocent memory (reported by Gigabates and Losso)
- Bugfix: Palette LERP had wrong bias.
- Removed extra paths in include statement, use default include paths instead
- Added Raspberry Casket no-jitter background calc mode (FW_MUSIC_PLAYER_CHOICE = 6)
- Updated Raspberry Casket to V2.0 presto branch (WIP)
- Removed fw_FrameCounterLong, use fw_FrameCounter-2 for debug purposes
- Support for blue noise palette LERPing (like in Is Real). Provide your own blue noise table (4 KB), stuff it into fw_BlueNoiseTablePtr, set FW_PALETTE_LERP_SUPPORT to 2
- Music tick routine is now replaceable during runtime (fw_MusicTickRoutine)
- Support for softints and audio interrupts
- LMB exit can also be disabled dynamically when using FW_LMB_EXIT_SUPPORT = 2 and fw_DisableLMBExit != 0
- Added LSP Micro support and LSP Nano (custom format that uses note pitches instead of periods)
- Minor other things
2024-09-15 17:43:33 +02:00

868 lines
25 KiB
NASM

;--------------------------------------------------------------------
; 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_FrameCounter-2(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_FrameCounter-2(a6),a0,fw_MusicFrameCount-2(a6)
ELSE
PUTMSG 10,<"%d: *** Executing next part %p">,fw_FrameCounter-2(a6),a0
ENDC
jsr (a0)
IF FW_MUSIC_SUPPORT
PUTMSG 10,<"%d: *** Part finished at music frame %d",10>,fw_FrameCounter-2(a6),fw_MusicFrameCount-2(a6)
ELSE
PUTMSG 10,<"%d: *** Part finished",10>,fw_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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_FrameCounter-2(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