Optimized LZ Deformation - RetroKoH/S1Fixed GitHub Wiki

(Original Guide by MarkeyJester)
Commit: 0e09d5a
Source: SSRG Thread

Labyrinth Zone... as if it wasn't slow enough due to the underwater gameplay, right? Well, what if we could reduce some of the atrocious lag that bogs it down even further?

The major excessive lag that happens at the beginning of Labyrinth Zone is more than likely due to the inclusion of decompressing Nemesis data as part of its PLC system (A given, considering how slow Nemesis decompression is). The lag in general throughout the level via the wave effect, however, is caused by unoptimized code.

MarkeyJester provides some optimization ideas, along with this implementation shown below. The original code, written by MarkeyJester, has been adapted to modern disassemblies by Malachi. Go to _inc/DeformLayers.asm and find Deform_LZ: We are going to replace ALL of it with this:

; ---------------------------------------------------------------------------
; Labyrinth Zone background layer deformation code
; Optimised by MarkeyJester; Adapted to the modern disassembly by Malachi
; ---------------------------------------------------------------------------

; ||||||||||||||| S U B	R O U T	I N E |||||||||||||||||||||||||||||||||||||||


Deform_LZ:
		moveq	#7,d0									; prepare multiplication 100 / 2 for BG scrolling
		move.w	(v_scrshiftx).w,d4						; load horizontal movement distance (Since last frame)
		ext.l	d4										; extend to long-word signed
		asl.l	d0,d4									; align as fixed point 16, but divide by 2 for BG
		move.w	(v_scrshifty).w,d5						; load vertical movement distance (Since last frame)
		ext.l	d5										; extend to long-word signed
		asl.l	d0,d5									; align as fixed point 16, but divide by 2 for BG
		bsr.w	BGScroll_XY								; rev01 scrolling	; ''
		move.w	(v_bgscreenposy).w,(v_bgscrposy_vdp).w	; set BG V-scroll position
		lea	(v_hscrolltablebuffer).w,a1					; load H-scroll buffer
		move.w	(v_screenposx).w,d0						; load FG X position
		add.w	d7,d0
		neg.w	d0										; reverse
		swap	d0										; send to upper word
		move.w	(v_bgscreenposx).w,d0					; load BG X position
		add.w	d7,d0
		neg.w	d0										; reverse
		moveq	#0,d3									; clear d3
		move.b	(v_lz_deform).w,d3						; load wave-scroll timer
		addi.w	#$80,(v_lz_deform).w					; increase wave-scroll timer
		move.w	#224,d2									; prepare water-line count
		move.w	(v_waterpos1).w,d1						; load water line position
		sub.w	(v_screenposy).w,d1						; minus FG Y position
		bmi.s	.water									; if the screen is already underwater, branch
		cmp.w	d2,d1									; is the water line below the screen?
		ble.s	.nowater								; if not, branch
		move.w	d2,d1									; set at maximum
.nowater:
		sub.w	d1,d2									; subtract from water-line count
		add.b	d1,d3									; advance scroll wave timer to correct amount
		subq.b	#1,d1									; decrease above water count
		bcs.s	.water									; if finished, branch
.abovewater:
		move.l	d0,(a1)+								; save scroll position to buffer
		dbf	d1,.abovewater								; repeat for all above water lines
.water:
		subq.b	#1,d2									; decrease below water count
		bcs.s	.finish									; if finished, branch
		move.w	d0,d1									; copy BG position back to d1
		swap	d0										; move FG position back to lower word in d0
		move.w	d3,d4									; copy sroll timer for BG use
		add.b	(v_screenposy+1).w,d3					; add FG Y position
		add.b	(v_bgscreenposy+1).w,d4					; add BG Y position
		add.w	d3,d3									; multiply by word size (2)
		add.w	d4,d4									; ''
		lea	DLZ_WaveBG(pc),a3							; load beginning of BG wave data
		adda.w	d4,a3									; advance to correct starting point
		move.b	(a3),d4									; get current position byte
		asr.b	#2,d4									; get only the position bits
		ext.w	d4										; extend to word
		add.w	d4,d1									; adjust BG's current position
		lea	DLZ_WaveFG(pc,d3.w),a2						; load correct starting point of FG wave data
		move.b	(a2),d4									; get current position byte
		asr.b	#2,d4									; get only the position bits
		ext.w	d4										; extend to word
		add.w	d4,d0									; adjust FG's current position
.belowwater:
		add.w	(a2)+,d0								; alter FG horizontal position
		move.w	d0,(a1)+								; save to scroll buffer
		add.w	(a3)+,d1								; alter BG horizontal position
		move.w	d1,(a1)+								; save to scroll buffer
		dbf		d2,.belowwater							; repeat for all below water lines
.finish:
		rts												; return
; ---------------------------------------------------------------------------
; Deformation conversion documentation and macro
; IIII IIAA AAAA AAAA
; I = initial value
; A = accumulator
.dlzrip_I	:= 0
dlzripple macro data
	if "data"<>""
	dc.w (.dlzrip_I&$3F)<<10|(data-.dlzrip_I)&$3FF
.dlzrip_I	:= data
	shift
	dlzripple ALLARGS
	endif
	endm
; ===========================================================================
; FG ripple data
DLZ_WaveFG:
.dlzrip_I	:= 0
	rept 2
	dlzripple  1, 1, 2, 2, 3, 3, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple -1,-1,-2,-2,-3,-3,-3,-3,-2,-2,-1,-1, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  1, 1, 2, 2, 3, 3, 3, 3, 2, 2, 1, 1, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	dlzripple  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
	endr
; ===========================================================================
; BG ripple data
DLZ_WaveBG:
.dlzrip_I	:= -1
	rept 4
	dlzripple  0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2
	dlzripple  2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
	dlzripple  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2
	dlzripple  2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
	dlzripple  0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3
	dlzripple -3,-3,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4
	dlzripple -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-3
	dlzripple -3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-1,-1,-1,-1,-1
	endr
; ===========================================================================

The ripple effects applied for the BG are based on REV01 deformation, by the way. If you wish to use REV00 deformation for some reason, replace DLZ_WaveBG with this:

; ===========================================================================
; BG ripple data
DLZ_WaveBG:
.dlzrip_I	:= -1
	rept 4
	dlzripple  0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2
	dlzripple  2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
	dlzripple  4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2
	dlzripple  2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
	dlzripple  0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2,-3,-3,-3,-3,-3
	dlzripple -3,-3,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4
	dlzripple -4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-4,-3
	dlzripple -3,-3,-3,-3,-3,-3,-2,-2,-2,-2,-2,-1,-1,-1,-1,-1
	endr
; ===========================================================================

I'll try to add additional information on the changes made later.