View Page Source

Revision (current)
Last Updated by feos on 12/15/2015 6:36 PM
Back to Page

%%TAB Memory map

RAM

 $ffa172 - camera x  
 $ffa174 - camera y
 $ffa1d4 - RNG
 $fffc2a - config pointer. loads events for puppy love
 $fffc9a - reserved config pointer
 $fffc7b - puppy toss position. 0 causes 3 bounces, 2 causes 1 bounce.
 $fffc87 - puppy counter
 $fffc88+offset - speeds for puppies, offset = puppy counter

ROM 

 $25d482 - puppy speed table
 $275fea-$277b79 - approximate limits of puppy config table
 
%%TAB Lua

%%SRC_EMBED lua

gui.register(function()
	camx = memory.readword(0xffa172)
	camy = memory.readword(0xffa174)
	
	Objects()
	Bounce()
end)

function Objects()
	local base0 = 0xffa2ea
	for i=0,0x23 do
		local base = base0+i*0x6e
		local id = memory.readbyte(base)
		if id>0 and id~=0x82 then
			local hp = memory.readbytesigned(base+1)
			local x = memory.readword(base+2)-4096-camx
			local y = memory.readword(base+4)-4096-camy
			--local x = Clamp(x,0,310)
			--local y = Clamp(y,0,214)
			local dx = memory.readwordsigned(base+0x18)
			local dy = memory.readwordsigned(base+0x1a)
			local hitboxbase = memory.readlong(base+0x14)
			local x1 = memory.readbyte(hitboxbase+2)
			local x2 = memory.readbyte(hitboxbase+4)
			local y1 = memory.readbyte(hitboxbase+3)
			local y2 = memory.readbyte(hitboxbase+5)
			--PostRngRoll(base,x,y)
			if x1>0 and x2>0 and y1>0 and y2>0 then
				local of = 124
				x1 = x1+x-of
				x2 = x2+x-of
				y1 = y1+y-of
				y2 = y2+y-of
				gui.box(x1,y1,x2,y2,0,"green")
			end
			if hp>0 then
				gui.text(x,y-2,hp,"green")
			end
		end
	end
end

function Bounce()
	if memory.readbyte(0xffa515)==0x60
	then offset = 8
	else offset = 0 end
	local counter = memory.readbyte(0xfffc87)
	local a0 = 0xfffc88
	local d0 = SHIFT(memory.readbyte(a0+counter),-5)+offset
	local a3 = 0x25d482
	local vel = memory.readword(a3+d0)
	local bounce = 0
	if     vel == 0x200 then bounce = 3
	elseif vel == 0x3e0 then bounce = 1
	else                     bounce = 2
	end
	gui.text(0,0,string.format("next bounce: %d",bounce))
end

function Dump()
	for p=0x275fea,0x277b79 do
		local a = memory.readbyte(p)
		if a==0x62 then
			table.insert(bombs,string.format("%X",p))
		elseif a==8 then
			table.insert(goback,string.format("%X",p))
		elseif a==3 then
			table.insert(goforth,string.format("%X",p))
		end
	end
	print("bombs:")
	print(bombs)
	print("")
	print("goback:")
	print(goback)
	print("")
	print("goforth:")
	print(goforth)
	print("")
end

%%END_EMBED

%%TAB Dumps

Config table addresses that contain given objects.%%%
Generated by function Dump().

__Bombs__

276037, 276065, 2760B9, 276109, 276142, 276164, 276168, 27616C, 276170, 276174, 276178, 27617C, 276182, 2765DE, 276637, 276679, 2766F9, 276783, 276F85, 276FDD, 277040, 277086, 2770CA, 27715F

__GoBack__

27605E, 276060, 2760A8, 2760AA, 2760AC, 2760EB, 2760ED, 2760EF, 27612F, 276131, 276133, 276135, 2765A1, 2765A3, 2765B4, 2765F9, 2765FB, 2765FD, 276616, 276618, 276652, 276654, 276656, 276658, 27669A, 27669C, 27669E, 2766D3, 276720, 276722, 276724, 276726, 276799, 2767BB, 2767DD, 2767ED, 2767FF, 276821, 276F1B, 276F59, 276F5B, 276F9E, 276FA0, 276FA2, 276FA4, 277005, 277032, 277034, 277061, 277063, 277065, 27707A, 2770A9, 2770AB, 2770AD, 2770BE, 2770D9, 2770FB, 27711D, 27713F, 277161

__GoForth__

2760BE, 2761B3, 2761D9, 2761E3, 276203, 276211, 276266, 276275, 27629D, 2762AB, 2762BB, 2762DF, 276313, 27633D, 276363, 276394, 2763A6, 276402, 276416, 27644A, 27646C, 276494, 2764A3, 2764DB, 2764E9, 276545, 276559, 27658D, 27667E, 27684F, 27685E, 27686C, 2768A1, 2768B9, 276903, 276940, 276956, 276980, 2769B6, 2769C8, 2769E2, 276A0C, 276A4A, 276A83, 276A98, 276AA6, 276AD7, 276B07, 276B39, 276B6D, 276B9F, 276BD8, 276BED, 276C01, 276C39, 276C51, 276C83, 276CB7, 276CFC, 276D39, 276D4E, 276D68, 276D98, 276DB4, 276DE6, 276E17, 276E59, 276E94, 276ECB, 277045, 2771C0, 27720C, 277238, 277281, 2772C0, 277314, 27735D, 27736B, 2773B8, 277410, 27743C, 277485, 2774BE, 27750E, 277556, 277566, 2775B3, 277613, 27763F, 277688, 2776C1, 277711, 27775A, 27776E, 2777BB, 27781B, 277847, 277890, 2778C9, 277919, 277961, 277973, 2779C0, 277A20, 277A4C, 277A95, 277ACE, 277B1E, 277B69

%%TAB_END

! Puppy Love spawns

Actions are read consecutively from config tables, 30-32 spawn objects whose toss position is decided by the second digit, and type is read from the next byte.

Sometimes config pointer will jump back or forth, using reserved config pointer, and offset figured out from RNG. By manipulating the RNG you must be able to affect end pointer values.

 64 - force Psyclow up
 63 - force him down
 30-32 - do the spawn
 62 - bomb
 68 - globe
 70 - puppy
 03 - jump forth through config table
 08 - jump back through config table
 7a - end of batch, wait how player handles the objects
 2b,2d,0 - just skip

! Randomness

New RNG value only depends on the old one, so the only way to manipulate it is to force more or less of its calls.

It is called twice per object bounce (to figure out the sound and the flips), once or twice in a while by Peter (to do animation), a ton of times per Psycrow explosion feathers (13 times per frame), a bunch of times by letters of the new round.

So by dropping different puppies at different times you can skip some of these, resulting in RNG difference. Note that Psycrow freezes if scrolled a bit left, while Peter never stops poking the RNG, so it's also possible to delay puppy tosses and affect RNG differently.

 26:C2CE  48 E7  MOVEM.L {d0-a7}[[70 00]],-(SP)     
 26:C2D2  52 47  ADDQ.W  #1,D7                    
 26:C2D4  22 39  MOVE.L  ($00FFA1D4),D1           
 26:C2DA  24 01  MOVE.L  D1,D2                    
 26:C2DC  5E 82  ADDQ.L  #7,D2                    
 26:C2DE  D2 81  ADD.L   D1,D1                    
 26:C2E0  D2 81  ADD.L   D1,D1                    
 26:C2E2  26 01  MOVE.L  D1,D3                    
 26:C2E4  D2 81  ADD.L   D1,D1                    
 26:C2E6  D2 82  ADD.L   D2,D1                    
 26:C2E8  D2 83  ADD.L   D3,D1                    
 26:C2EA  23 C1  MOVE.L  D1,($00FFA1D4)           
 26:C2F0  24 01  MOVE.L  D1,D2                    
 26:C2F2  48 42  SWAP.W  D2                       
 26:C2F4  B5 41  EOR.W   D2,D1                    
 26:C2F6  CE C1  MULU.W  D1,D7                    
 26:C2F8  48 47  SWAP.W  D7                       
 26:C2FA  4C DF  MOVEM.L (SP)+,{a7-d0}[[00 0e]]     
 26:C2FE  4E 75  RTS