chrisly42
9c48c11cd1
- 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
868 lines
25 KiB
NASM
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
|