Jump to content

Pokemon B/W Lua scripts


Recommended Posts

5th Gen RNG Suite

fStBT.png

it displays stuff for copypasting in the console window!

-- General Parameters for current game and setup (english)
local game=0				-- 0 for white, 1 for black
local rng=0x02216244-0x20*game		-- PRNG Seed Location
local mtrng=0x02215374-0x20*game	-- Mersenne Twister Table Top
local mac=0x123456			-- MAC Address of Emulator
local pos_m=0x0224F92C-0x20*game	-- Map Position -> XYZ
local storage=0x02000200
local trackcgear=0 				-- 0 on, 1 off; disable for Standard Abuse, enable for Entralink Abuse
local research=0 				-- 0 on, 1 off; only enable for dev features (unneeded)

-- Setup Terminology abbreviations; from FractalFusion
local bnd,br,bxr=bit.band,bit.bor,bit.bxor
local rshift, lshift=bit.rshift, bit.lshift
local mdword=memory.readdwordunsigned
local mword=memory.readwordunsigned
local mbyte=memory.readbyteunsigned
local wdword=memory.writedword

-- Setup initial variables, rest of script detection will take care of them
local initl=0
local inith=0
local initm=0
local adv=0
local jump1=0
local jump2=0
local jump3=0
local jump4=0
local jump5=0
local jump6=0
local jump7=0
local jump8=0
local jump9=0
local jump10=0
local jump11=0
local jump12=0
local jump13=0
local jump14=0
local jump15=0
local jump16=0
local jump17=0
local jump18=0
local jump19=0
local jump20=0
local total=0
local last=0
local lastm=0
local lmtp=0
local steptable=0
local mtf=0
local mttrack=0
local nextmt=0
local second=0
local minute=0
local hour=0
local cgearoff=0
local cachevalue=0
local notrestored=0
local wasrestored=0

-- S frame detection function; works off of seeing how many times the lower half was advanced
-- Lua sucks and only allows 16 bit multiplication, so 32 bit multiplication can't be used
-- The lower seed is advanced as follows, if observed as a standalone 32 bit number:
-- SEED1 = (0x6C078965 * SEED1) + 0x00269EC3; from Kazo
function next(s)
local a=0x6C07*(s%65536)+rshift(s,16)*0x8965
local b=0x8965*(s%65536)+(a%65536)*65536+0x00269EC3
local c=b%4294967296
return c
end

-- To predict Mersenne advancement, it's a little harder. Copied and adapted pre-existing Lua
-- http://code.google.com/p/gocha-tas/source/browse/trunk/Scripts/mt19937.lua?r=117
-- Mersenne Twister: A random number generator
-- ported to Lua by gocha, based on mt19937ar.c
module("mt19937", package.seeall)

require "bit"

-- Period parameters
local N = 624
local M = 397
local MATRIX_A = 0x9908b0df   -- constant vector a
local UPPER_MASK = 0x80000000 -- most significant w-r bits
local LOWER_MASK = 0x7fffffff -- least significant r bits

local mt = {}     -- the array for the state vector
local mti = N + 1 -- mti==N+1 means mt[N] is not initialized

-- initializes mt[N] with a seed
function randomseed(s)
   s = bit.band(s, 0xffffffff)
   mt[1] = s
   for i = 1, N - 1 do
       -- s = 1812433253 * (bit.bxor(s, bit.rshift(s, 30))) + i
       s = bit.bxor(s, bit.rshift(s, 30))
       local s_lo = bit.band(s, 0xffff)
       local s_hi = bit.rshift(s, 16)
       local s_lo2 = bit.band(1812433253 * s_lo, 0xffffffff)
       local s_hi2 = bit.band(1812433253 * s_hi, 0xffff)
       s = bit.bor(bit.lshift(bit.rshift(s_lo2, 16) + s_hi2, 16),
           bit.band(s_lo2, 0xffff))
       -- s = bit.band(s + i, 0xffffffff)
       local s_lim = -bit.tobit(s)
       -- assumes i<2^31
       if (s_lim > 0 and s_lim <= i) then
           s = i - s_lim
       else
           s = s + i
       end
       mt[i+1] = s
       -- See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
       -- In the previous versions, MSBs of the seed affect
       -- only MSBs of the array mt[].
       -- 2002/01/09 modified by Makoto Matsumoto
   end
   mti = N
end

local mag01 = { 0, MATRIX_A }   -- mag01[x] = x * MATRIX_A  for x=0,1

-- generates a random number on [0,0xffffffff]-interval
function random_int32()
   local y

   if (mti >= N) then -- generate N words at one time
       local kk

       if (mti == N + 1) then -- if init_genrand() has not been called,
           mt19937.randomseed(5489) -- a default initial seed is used
       end

       for kk = 1, N - M do
           y = bit.bor(bit.band(mt[kk], UPPER_MASK), bit.band(mt[kk+1], LOWER_MASK))
           mt[kk] = bit.bxor(mt[kk+M], bit.rshift(y, 1), mag01[1 + bit.band(y, 1)])
       end
       for kk = N - M + 1, N - 1 do
           y = bit.bor(bit.band(mt[kk], UPPER_MASK), bit.band(mt[kk+1], LOWER_MASK))
           mt[kk] = bit.bxor(mt[kk+(M-N)], bit.rshift(y, 1), mag01[1 + bit.band(y, 1)])
       end
       y = bit.bor(bit.band(mt[N], UPPER_MASK), bit.band(mt[1], LOWER_MASK))
       mt[N] = bit.bxor(mt[M], bit.rshift(y, 1), mag01[1 + bit.band(y, 1)])

       mti = 0
   end

   y = mt[mti+1]
   mti = mti + 1



   return y
end

function random(...)
   -- local r = mt19937.random_int32() * (1.0/4294967296.0)
   local rtemp = mt19937.random_int32()
   local r = (bit.band(rtemp, 0x7fffffff) * (1.0/4294967296.0)) + (bit.tobit(rtemp) < 0 and 0.5 or 0)
   local arg = {...}
   if #arg == 0 then
       return r
   elseif #arg == 1 then
       local u = math.floor(arg[1])
       if 1 <= u then
           return math.floor(r*u)+1
       else
           error("bad argument #1 to 'random' (internal is empty)")
       end
   elseif #arg == 2 then
       local l, u = math.floor(arg[1]), math.floor(arg[2])
       if l <= u then
           return math.floor((r*(u-l+1))+l)
       else
           error("bad argument #2 to 'random' (internal is empty)")
       end
   else
       error("wrong number of arguments")
   end
end

-- Lua script begin!
while true do
wdword(storage,1)
-- setup every loop
seed2=mdword(rng+4)
seed1=mdword(rng)
adv=0
test=last
mtv=mdword(mtrng)
mtp=mdword(mtrng+0x9C0)
delay=mdword(0x02FFFC3C)
timehex=mdword(0x023FFDEC)
datehex=mdword(0x023FFDE8)
hour=string.format("%02X",(timehex%0x100)%0x40)				-- memory stores as decimal, but Lua reads as hex. Convert.
minute=string.format("%02X",(rshift(timehex%0x10000,8)))
second=string.format("%02X",(mbyte(0x02FFFDEE)))
year=string.format("%02X",(mbyte(0x02FFFDE8)))
month=string.format("%02X",(mbyte(0x02FFFDE9)))
day=string.format("%02X",(mbyte(0x02FFFDEA)))

-- display seeds every loop
gui.text(1,10,string.format("Current: %08X%08X",seed2,seed1))
gui.text(1,180,string.format("Initial: %08X%08X",inith,initl))
gui.text(1,170, string.format("M: %d, X: %d, Y: %d, Z: %d", mword(pos_m), mword(pos_m+0x6), mword(pos_m+0xE), mword(pos_m+0xA)))

-- Check to see if the RNG advanced from the last value
while seed1~=0 and seed2~=0 and delay > 2 do
	if adv>200 then -- RNG advanced a bunch, or the game/script was reset. Reset variables then stop loop.
		steptable=0
		adv  =0
		jump1=0
		jump2=0
		jump3=0
		jump4=0
		jump5=0
		jump6=0
		jump7=0
		jump8=0
		jump9=0
		jump10=0
		jump11=0
		jump12=0
		jump13=0
		jump14=0
		jump15=0
		jump16=0
		jump17=0
		jump18=0
		jump19=0
		jump20=0
		if mdword(storage)==1 and delay>3 and mdword(storage+0x4*2)~=0 then
			print(""..string.format("Restoring session. Please Wait..."))
			steptable=mdword(storage+0x4*1)				-- restore mt
			initm=mdword(storage+0x4*2)
			lastm=mdword(storage+0x4*7)
			randomseed(initm)
			i=624*steptable+1
			while i>0 do								-- restore internal mt frame
					nextmt=math.floor(random_int32())
					i=i-1	
			end

			mttrack=1									-- turn on tracking

			inith=mdword(storage+0x4*4)					-- restore PRNG
			initl=mdword(storage+0x4*3)

			cacheseed=mdword(storage+0x4*5)
			cachevalue=mdword(storage+0x4*6)
			lastm=mtv
			mtv=lastm
			lmtp=mtp

			if initm==0 or inith==0 or initl==0 then 
				print(""..string.format("Save state's session did not start with script.")) 
				print(""..string.format("Either load a valid save state or resume with this one."))
				initl=mdword(rng)						-- reset to session
				inith=mdword(rng+4)
				mttrack=0
				emu.pause()
				total=0
				steptable=0
				mtf=0
				lmtp=mtp
				steptable=0
			else
				print(""..string.format("PRNG: %08X%08X",inith,initl)) 
				print(""..string.format("MTRNG: %08X", initm))
				last=cacheseed
				total=cachevalue							-- restored frame
			end
			cgearoff=mdword(storage+0x4*8)			-- remember if c-gear was turned on or not
			notrestored=1
			wasrestored=1
		elseif initm==inith then
			print(""..string.format("Game Reset. Re-initializing."))
			total=0
			steptable=0
			mtf=0
			lmtp=mtp
			initl=mdword(rng)
			inith=mdword(rng+4)
			initm=mdword(mtrng)
			if inith>0x7FFFFFFF then wdword(storage+0x4*4,inith-0x100000000) else wdword(storage+0x4*4,inith) end  -- dumb storage problems, have to make sure they are recognized as the right number type before storage
			if initl>0x7FFFFFFF then wdword(storage+0x4*3,initl-0x100000000) else wdword(storage+0x4*3,initl) end
			if initm>0x7FFFFFFF then wdword(storage+0x4*2,initm-0x100000000) else wdword(storage+0x4*2,initm) end
			lastm=initm
			randomseed(initm)
			mttrack=1						-- enable mersenne tracking
			nextmt=random_int32()			-- get first untempered mersenne value, this is the value that will replace the MTRNG seed in the memory when the table is redone
			cgearenoff=0
			wasrestored=0

		print(""..string.format("Session Initial Seed: %08X%08X",inith,initl)) 
		--print(""..string.format("Next: %08X", nextmt)) -- debug

		-- see if initial seeding happened (high32=mtseed)
			mttrack=1					-- enable tracking
			print(""..string.format("Initial Seeding Detected. MTRNG Seed: %08X", initm))
		else	
			print(""..string.format("Foreign Save State Detected, or Restart didn't refresh. Reset again."))
			total=0
			steptable=0
			mtf=0
			lmtp=mtp
			initl=mdword(rng)
			inith=mdword(rng+4)
			initm=mdword(mtrng)
			if inith>0x7FFFFFFF then wdword(storage+0x4*4,inith-0x100000000) else wdword(storage+0x4*4,inith) end
			if initl>0x7FFFFFFF then wdword(storage+0x4*3,initl-0x100000000) else wdword(storage+0x4*3,initl) end
			if initm>0x7FFFFFFF then wdword(storage+0x4*2,initm-0x100000000) else wdword(storage+0x4*2,initm) end
			lastm=initm
			randomseed(initm)
			mttrack=0						-- disable mersenne tracking
			nextmt=random_int32()			-- get first untempered mersenne value, this is the value that will replace the MTRNG seed in the memory when the table is redone
			cgearenoff=0
			wasrestored=0
		end
		print(""..string.format(""))	-- Visual Line to separate.
		break 

	elseif test~=seed1 then 			-- RNG advanced at least once. Lets advance once and repeat the loop.
		test=next(test)
		adv=adv+1

	elseif test==seed1 then 
		if adv > 0 then 				-- Refresh Frame Advancement Table if there's more than one advancement this frame.
			jump20=jump19
			jump19=jump18
			jump18=jump17
			jump17=jump16
			jump16=jump15
			jump15=jump14
			jump14=jump13
			jump13=jump12
			jump12=jump11
			jump11=jump10
			jump10=jump9
			jump9=jump8
			jump8=jump7
			jump7=jump6
			jump6=jump5
			jump5=jump4
			jump4=jump3
			jump3=jump2
			jump2=jump1
			jump1=adv 
		end								
		break 							-- last frame's advanced RNG value matches the current. Stop loop.
	end
end


gui.text(180,10,string.format("%d/%d/%d",month,day,2000+year))					-- Display Date
gui.text(180,19,string.format("%02d:%02d:%02d",hour,minute,second,delay))		-- Display Time

-- Check to see if the MTRNG changed, only if tracking is enabled.
if mttrack==1 and notrestored == 0 then
	if (lmtp>mtp and delay > 50 and notrestored==0) or (lmtp==mtp and lastm~=mtv) then
			strmtv=string.format("%08X",mtv)		-- Mersenne Twister untempered is in one format while the memory is in another
			strnmt=string.format("%08X",nextmt)		-- Convert to a string hex so that they can be equated when their decimal isn't
		if strmtv~=strnmt  then 					-- New untempered table value isn't as predicted, so the c-gear was turned on!
			mttrack=1 
			-- print(strmtv,strnmt,string.format("%08X",lastm)) -- debug for bad initialize
			if wasrestored==1 then print(""..string.format("Earlier restoration may have failed. Double Check.")) print(""..string.format("If C-Gear was just turned on this frame, ignore.")) print(""..string.format("")) wasrestored=0 end
			-- mttrack=0
			--else 
			print(""..string.format("C-Gear turned on. Determining C-Gear Seed and restarting tracking.")) 
			steptable=1
			wdword(storage+0x4*1, steptable)
			-- Finding the C-Gear seed you hit
			-- Load Time Values
				hour=string.format("%02X",(timehex%0x100)%0x40)				-- Memory stores as decimal, but Lua reads as hex. Convert.
				minute=string.format("%02X",(rshift(timehex%0x10000,8)))
				second=string.format("%02X",(mbyte(0x02FFFDEE)))
				year=string.format("%02X",(mbyte(0x02FFFDE8)))
				month=string.format("%02X",(mbyte(0x02FFFDE9)))
				day=string.format("%02X",(mbyte(0x02FFFDEA)))
						ab=(month*day+minute+second)%256
						cd=hour
						cgd=delay%65536-1									-- Delay from a frame before is used.
						abcd=ab*0x100+cd
						efgh=(year+cgd)%0x10000
						tempcgear=(ab*0x1000000+cd*0x10000+efgh+mac)%0x100000000
				randomseed(tempcgear)
				trialseed=random_int32()
				tempcgearuntemp=string.format("%08X",trialseed)
				if strmtv~=tempcgearuntemp then
					second=second-1					-- Subtract a second to check a different set.
					if second < 0 then				-- Balaning minutes
						second=59
						minute=minute-1				
						if minute<0 then			-- Balancing Hours
							minute=59
							hour=hour-1
						end
					end
					ab=(month*day+minute+second)%256	-- Rebuild seed, try again.
					cd=hour
					abcd=ab*0x100+cd
					efgh=(year+cgd)%0x10000
					tempcgear=(ab*0x1000000+cd*0x10000+efgh+mac)%0x100000000
					randomseed(tempcgear)
					trialseed=random_int32()
					tempcgearuntemp=string.format("%08X",trialseed)
				end

				initm=tempcgear
				print(""..string.format("C-Gear Seed: %08X    Delay: %d",tempcgear,cgd))
				print(""..string.format(""))				-- Visual Blank Line
				cgearenabled=2
				wdword(storage+0x4*8,cgearenabled)					
				if initm>0x7FFFFFFF then wdword(storage+0x4*2,initm-0x100000000) else wdword(storage+0x4*2,initm) end
				i=0
				while i~=624 do								-- get the next untempered for the cgear
					nextmt=math.floor(random_int32())
					i=i+1
				end --end
		else												-- untempered is as predicted -> predict next one for when the time rolls around

			i=0
			while i~=624 do									-- do 624 iterations to build the remaining 623 and the first of the next.
				nextmt=math.floor(random_int32())
				i=i+1
			end
		--print(""..string.format("Next: %08X", nextmt)) 	-- debug



			steptable=steptable+1 							-- mersenne twister has a new table as the counter is reset to 0; tables++

			wdword(storage+0x4*1, steptable)				-- save state storage of table refreshes
		end
	end
gui.text(1,160,string.format("MTRNG Seed: %08X",initm))
gui.text(1,150,string.format("Frame: %d",mtf))
-- gui.text(1,38,string.format("next mt: %08X", nextmt)) -- debug
end


-- Advancement Tracking for the PRNG and Mersenne Twister
total=adv+total										-- total advancements = advancements on this frame + total advancements from previous frames
if total-cachevalue>200 then						-- check to see if we should refresh the cached value
	cachevalue=total
end
mtf=mtp+(steptable-1)*624							-- Mersenne Twister Frame = Pointer Value + (TableRefresh-1)*624 ; this accounts for the initial value of 0x270 which is actually zero

gui.text(1,19,string.format("Frame: %d", total))	-- Display PRNG Frame; total advancements since the initial seed

-- If the user specifies they want to use the C-Gear
if trackcgear==0 then											-- C-Gear Seed Generation Loop
	ab=(month*day+minute+second)%256							-- Build Seed
	cd=hour
	cgd=delay%65536+1
	abcd=ab*0x100+cd
	efgh=(year+cgd)%0x10000
	betaseed=ab*0x1000000+cd*0x10000+efgh						-- Seed before MAC applied
	cgearseed=betaseed+mac										-- Seed after MAC applied, return this value.
gui.text(1,130,string.format("Next C-Gear: %08X",cgearseed))	-- Display the C-Gear Seed of the next frame
gui.text(1,140,string.format("Delay: %d", delay))				-- Display Current Delay
elseif cgearenabled==2 then
	gui.text(1,130,string.format(" C-GEAR WAS TURNED ON: SEE NEW MTRNG SEED"))
end

-- If user specifies they want to see the frame advancement chart
if research==0 then									-- Display framebased advancement table
gui.text(1,37,string.format("%d", jump1)) gui.text(1,46,string.format("%d", jump2)) gui.text(1,55,string.format("%d", jump3)) gui.text(1,64,string.format("%d", jump4))
gui.text(1,73,string.format("%d", jump5)) gui.text(1,82,string.format("%d", jump6)) gui.text(1,91,string.format("%d", jump7)) gui.text(1,100,string.format("%d", jump8))
gui.text(1,109,string.format("%d", jump9)) gui.text(1,118,string.format("%d", jump10)) gui.text(20,37,string.format("%d", jump11)) gui.text(20,46,string.format("%d", jump12)) 
gui.text(20,55,string.format("%d", jump13)) gui.text(20,64,string.format("%d", jump14))	gui.text(20,73,string.format("%d", jump15))	gui.text(20,82,string.format("%d", jump16)) 
gui.text(20,91,string.format("%d", jump17)) gui.text(20,100,string.format("%d", jump18)) gui.text(20,109,string.format("%d", jump19)) gui.text(20,118,string.format("%d", jump20))
end

-- Set Up variables for next frame's pass
lmtp=mtp
last=seed1
lastm=mtv
if lastm>0x7FFFFFFF then wdword(storage+0x4*7,lastm-0x100000000) else wdword(storage+0x4*7,lastm) end
	wdword(storage+0x4*6,total)
			if seed1>0x7FFFFFFF then wdword(storage+0x4*5,seed1-0x100000000) else wdword(storage+0x4*5,seed1) end

notrestored=0
-- End Lua
emu.frameadvance() 
end

still may have some bugs to work out, however it's pretty much done

edit: Added C-Gear detection and it will properly track the frames if you turn on the C-Gear. It also tells you what C-Gear seed you hit in addition to delay in the Console. The value that seeds the MTRNG is displayed on the HUD (changed from only displaying the initial seed from the start of the game).

edit2: fixed bugs and allowed people to turn off the frame chart and C-Gear prediction. dubbed "research" and "trackcgear"

different from image: frame advancement chart is displayed only by turning on research mode, and it's more collapsed than above (changed). c-gear tracking and research is by default off

--

edit3: added save state support

old version without state support:

-- General Parameters for current game and setup(currently English White)
local rng=0x02216244			-- PRNG Seed Location
local mtrng=0x02215374			-- Mersenne Twister Table Top
local mac=0x123456				-- MAC Address of Emulator
local pos_m=0x0224F92C			-- Map Position -> XYZ
local trackcgear=1 			-- 0 on, 1 off; disable for Standard Abuse, enable for Entralink Abuse
local research=1 				-- 0 on, 1 off; only enable for dev features (unneeded)

-- Setup Terminology abbreviations; from FractalFusion
local bnd,br,bxr=bit.band,bit.bor,bit.bxor
local rshift, lshift=bit.rshift, bit.lshift
local mdword=memory.readdwordunsigned
local mword=memory.readwordunsigned
local mbyte=memory.readbyteunsigned

-- Setup initial variables, rest of script detection will take care of them
local initl=0
local inith=0
local initm=0
local adv=0
local jump1=0
local jump2=0
local jump3=0
local jump4=0
local jump5=0
local jump6=0
local jump7=0
local jump8=0
local jump9=0
local jump10=0
local jump11=0
local jump12=0
local jump13=0
local jump14=0
local jump15=0
local jump16=0
local jump17=0
local jump18=0
local jump19=0
local jump20=0
local total=0
local last=0
local lastm=0
local lmtp=0
local steptable=0
local mtf=0
local mttrack=0
local nextmt=0
local second=0
local minute=0
local hour=0
local cgearenabled=0

-- S frame detection function; works off of seeing how many times the lower half was advanced
-- Lua sucks and only allows 16 bit multiplication, so 32 bit multiplication can't be used
-- The lower seed is advanced as follows, if observed as a standalone 32 bit number:
-- SEED1 = (0x6C078965 * SEED1) + 0x00269EC3; from Kazo
function next(s)
local a=0x6C07*(s%65536)+rshift(s,16)*0x8965
local b=0x8965*(s%65536)+(a%65536)*65536+0x00269EC3
local c=b%4294967296
return c
end

-- To predict Mersenne advancement, it's a little harder. Copied and adapted pre-existing Lua
-- http://code.google.com/p/gocha-tas/source/browse/trunk/Scripts/mt19937.lua?r=117
-- Mersenne Twister: A random number generator
-- ported to Lua by gocha, based on mt19937ar.c
module("mt19937", package.seeall)

require "bit"

-- Period parameters
local N = 624
local M = 397
local MATRIX_A = 0x9908b0df   -- constant vector a
local UPPER_MASK = 0x80000000 -- most significant w-r bits
local LOWER_MASK = 0x7fffffff -- least significant r bits

local mt = {}     -- the array for the state vector
local mti = N + 1 -- mti==N+1 means mt[N] is not initialized

-- initializes mt[N] with a seed
function randomseed(s)
   s = bit.band(s, 0xffffffff)
   mt[1] = s
   for i = 1, N - 1 do
       -- s = 1812433253 * (bit.bxor(s, bit.rshift(s, 30))) + i
       s = bit.bxor(s, bit.rshift(s, 30))
       local s_lo = bit.band(s, 0xffff)
       local s_hi = bit.rshift(s, 16)
       local s_lo2 = bit.band(1812433253 * s_lo, 0xffffffff)
       local s_hi2 = bit.band(1812433253 * s_hi, 0xffff)
       s = bit.bor(bit.lshift(bit.rshift(s_lo2, 16) + s_hi2, 16),
           bit.band(s_lo2, 0xffff))
       -- s = bit.band(s + i, 0xffffffff)
       local s_lim = -bit.tobit(s)
       -- assumes i<2^31
       if (s_lim > 0 and s_lim <= i) then
           s = i - s_lim
       else
           s = s + i
       end
       mt[i+1] = s
       -- See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier.
       -- In the previous versions, MSBs of the seed affect
       -- only MSBs of the array mt[].
       -- 2002/01/09 modified by Makoto Matsumoto
   end
   mti = N
end

local mag01 = { 0, MATRIX_A }   -- mag01[x] = x * MATRIX_A  for x=0,1

-- generates a random number on [0,0xffffffff]-interval
function random_int32()
   local y

   if (mti >= N) then -- generate N words at one time
       local kk

       if (mti == N + 1) then -- if init_genrand() has not been called,
           mt19937.randomseed(5489) -- a default initial seed is used
       end

       for kk = 1, N - M do
           y = bit.bor(bit.band(mt[kk], UPPER_MASK), bit.band(mt[kk+1], LOWER_MASK))
           mt[kk] = bit.bxor(mt[kk+M], bit.rshift(y, 1), mag01[1 + bit.band(y, 1)])
       end
       for kk = N - M + 1, N - 1 do
           y = bit.bor(bit.band(mt[kk], UPPER_MASK), bit.band(mt[kk+1], LOWER_MASK))
           mt[kk] = bit.bxor(mt[kk+(M-N)], bit.rshift(y, 1), mag01[1 + bit.band(y, 1)])
       end
       y = bit.bor(bit.band(mt[N], UPPER_MASK), bit.band(mt[1], LOWER_MASK))
       mt[N] = bit.bxor(mt[M], bit.rshift(y, 1), mag01[1 + bit.band(y, 1)])

       mti = 0
   end

   y = mt[mti+1]
   mti = mti + 1



   return y
end

function random(...)
   -- local r = mt19937.random_int32() * (1.0/4294967296.0)
   local rtemp = mt19937.random_int32()
   local r = (bit.band(rtemp, 0x7fffffff) * (1.0/4294967296.0)) + (bit.tobit(rtemp) < 0 and 0.5 or 0)
   local arg = {...}
   if #arg == 0 then
       return r
   elseif #arg == 1 then
       local u = math.floor(arg[1])
       if 1 <= u then
           return math.floor(r*u)+1
       else
           error("bad argument #1 to 'random' (internal is empty)")
       end
   elseif #arg == 2 then
       local l, u = math.floor(arg[1]), math.floor(arg[2])
       if l <= u then
           return math.floor((r*(u-l+1))+l)
       else
           error("bad argument #2 to 'random' (internal is empty)")
       end
   else
       error("wrong number of arguments")
   end
end

-- Lua script begin!
while true do

-- setup every loop
seed2=mdword(rng+4)
seed1=mdword(rng)
adv=0
test=last
mtv=mdword(mtrng)
mtp=mdword(mtrng+0x9C0)
delay=mdword(0x02FFFC3C)
timehex=mdword(0x023FFDEC)
datehex=mdword(0x023FFDE8)
hour=string.format("%02X",(timehex%0x100)%0x40)				-- memory stores as decimal, but Lua reads as hex. Convert.
minute=string.format("%02X",(rshift(timehex%0x10000,8)))
second=string.format("%02X",(mbyte(0x02FFFDEE)))
year=string.format("%02X",(mbyte(0x02FFFDE8)))
month=string.format("%02X",(mbyte(0x02FFFDE9)))
day=string.format("%02X",(mbyte(0x02FFFDEA)))

-- display seeds every loop
gui.text(1,10,string.format("Current: %08X%08X",seed2,seed1))
gui.text(1,180,string.format("Initial: %08X%08X",inith,initl))
gui.text(1,170, string.format("M: %d, X: %d, Y: %d, Z: %d", mword(pos_m), mword(pos_m+0x6), mword(pos_m+0xE), mword(pos_m+0xA)))

-- Check to see if the RNG advanced from the last value
while seed1~=0 and seed2~=0 do
	if adv>200 then -- RNG advanced a bunch, or the game/script was reset. Reset variables then stop loop.
		print(""..string.format("Detected a reset or massive advancement. Re-initializing."))
		adv  =0
		total=0
		jump1=0
		jump2=0
		jump3=0
		jump4=0
		jump5=0
		jump6=0
		jump7=0
		jump8=0
		jump9=0
		jump10=0
		jump11=0
		jump12=0
		jump13=0
		jump14=0
		jump15=0
		jump16=0
		jump17=0
		jump18=0
		jump19=0
		jump20=0
		steptable=0
		mtf=0
		lmtp=mtp
		initl=mdword(rng)
		inith=mdword(rng+4)
		initm=mdword(mtrng)
		lastm=initm
		randomseed(initm)
		mttrack=0						-- disable mersenne tracking
		nextmt=random_int32()			-- get first untempered mersenne value, this is the value that will replace the MTRNG seed in the memory when the table is redone
		cgearenabled=0

		print(""..string.format("Session Initial Seed: %08X%08X",inith,initl)) 
		--print(""..string.format("Next: %08X", nextmt)) -- debug

		if initm==inith then			-- see if initial seeding happened (high32=mtseed)
			mttrack=1					-- enable tracking
			print(""..string.format("Initial Seeding Detected. MTRNG Seed: %08X", initm))
		else	
			print(""..string.format("Save State Detected. Unable to determine initial MTRNG"))
		end
		print(""..string.format(""))	-- Visual Line to separate.
		break 

	elseif test~=seed1 then 			-- RNG advanced at least once. Lets advance once and repeat the loop.
		test=next(test)
		adv=adv+1

	elseif test==seed1 then 
		if adv > 0 then 				-- Refresh Frame Advancement Table if there's more than one advancement this frame.
			jump20=jump19
			jump19=jump18
			jump18=jump17
			jump17=jump16
			jump16=jump15
			jump15=jump14
			jump14=jump13
			jump13=jump12
			jump12=jump11
			jump11=jump10
			jump10=jump9
			jump9=jump8
			jump8=jump7
			jump7=jump6
			jump6=jump5
			jump5=jump4
			jump4=jump3
			jump3=jump2
			jump2=jump1
			jump1=adv 
		end								
		break 							-- last frame's advanced RNG value matches the current. Stop loop.
	end
end


gui.text(180,10,string.format("%d/%d/%d",month,day,2000+year))					-- Display Date
gui.text(180,19,string.format("%02d:%02d:%02d",hour,minute,second,delay))		-- Display Time

-- Check to see if the MTRNG changed, only if tracking is enabled.
if mttrack==1 then
	if (lmtp>mtp and delay > 50) or (lmtp==mtp and lastm~=mtv) then
			strmtv=string.format("%08X",mtv)		-- Mersenne Twister untempered is in one format while the memory is in another
			strnmt=string.format("%08X",nextmt)		-- Convert to a string hex so that they can be equated when their decimal isn't
		if strmtv~=strnmt  then 						-- New untempered table value isn't as predicted, so the c-gear was turned on!
			mttrack=1 
			print(""..string.format("C-Gear turned on. Determining C-Gear Seed and restarting tracking."))
			steptable=1
			-- Finding the C-Gear seed you hit
			-- Load Time Values
				hour=string.format("%02X",(timehex%0x100)%0x40)				-- Memory stores as decimal, but Lua reads as hex. Convert.
				minute=string.format("%02X",(rshift(timehex%0x10000,8)))
				second=string.format("%02X",(mbyte(0x02FFFDEE)))
				year=string.format("%02X",(mbyte(0x02FFFDE8)))
				month=string.format("%02X",(mbyte(0x02FFFDE9)))
				day=string.format("%02X",(mbyte(0x02FFFDEA)))
						ab=(month*day+minute+second)%256
						cd=hour
						cgd=delay%65536-1									-- Delay from a frame before is used.
						abcd=ab*0x100+cd
						efgh=(year+cgd)%0x10000
						tempcgear=(ab*0x1000000+cd*0x10000+efgh+mac)%0x100000000
				randomseed(tempcgear)
				trialseed=random_int32()
				tempcgearuntemp=string.format("%08X",trialseed)
				if strmtv~=tempcgearuntemp then
					second=second-1					-- Subtract a second to check a different set.
					if second < 0 then				-- Balaning minutes
						second=59
						minute=minute-1				
						if minute<0 then			-- Balancing Hours
							minute=59
							hour=hour-1
						end
					end
					ab=(month*day+minute+second)%256	-- Rebuild seed, try again.
					cd=hour
					abcd=ab*0x100+cd
					efgh=(year+cgd)%0x10000
					tempcgear=(ab*0x1000000+cd*0x10000+efgh+mac)%0x100000000
					randomseed(tempcgear)
					trialseed=random_int32()
					tempcgearuntemp=string.format("%08X",trialseed)
				end

				initm=tempcgear
				print(""..string.format("C-Gear Seed: %08X    Delay: %d",tempcgear,cgd))
				print(""..string.format(""))				-- Visual Blank Line
				cgearenabled=1
				i=0
				while i~=624 do								-- get the next untempered for the cgear
					nextmt=math.floor(random_int32())
					i=i+1
				end
		else												-- untempered is as predicted -> predict next one for when the time rolls around

			i=0
			while i~=624 do									-- do 624 iterations to build the remaining 623 and the first of the next.
				nextmt=math.floor(random_int32())
				i=i+1
			end
		--print(""..string.format("Next: %08X", nextmt)) 	-- debug

			steptable=steptable+1 							-- mersenne twister has a new table as the counter is reset to 0; tables++
		end
	end
gui.text(1,160,string.format("MTRNG Seed: %08X",initm))
gui.text(1,150,string.format("Frame: %d",mtf))
-- gui.text(1,38,string.format("next mt: %08X", nextmt)) -- debug
end


-- Advancement Tracking for the PRNG and Mersenne Twister
total=adv+total										-- total advancements = advancements on this frame + total advancements from previous frames
mtf=mtp+(steptable-1)*624							-- Mersenne Twister Frame = Pointer Value + (TableRefresh-1)*624 ; this accounts for the initial value of 0x270 which is actually zero

gui.text(1,19,string.format("Frame: %d", total))	-- Display PRNG Frame; total advancements since the initial seed

-- If the user specifies they want to use the C-Gear
if trackcgear==0 then											-- C-Gear Seed Generation Loop
	ab=(month*day+minute+second)%256							-- Build Seed
	cd=hour
	cgd=delay%65536+1
	abcd=ab*0x100+cd
	efgh=(year+cgd)%0x10000
	betaseed=ab*0x1000000+cd*0x10000+efgh						-- Seed before MAC applied
	cgearseed=betaseed+mac										-- Seed after MAC applied, return this value.
gui.text(1,130,string.format("Next C-Gear: %08X",cgearseed))	-- Display the C-Gear Seed of the next frame
gui.text(1,140,string.format("Delay: %d", delay))				-- Display Current Delay
elseif cgearenabled==1 then
	gui.text(1,130,string.format(" C-GEAR WAS TURNED ON: SEE NEW MTRNG SEED"))
end

-- If user specifies they want to see the frame advancement chart
if research==0 then									-- Display framebased advancement table
gui.text(1,37,string.format("%d", jump1)) gui.text(1,46,string.format("%d", jump2)) gui.text(1,55,string.format("%d", jump3)) gui.text(1,64,string.format("%d", jump4))
gui.text(1,73,string.format("%d", jump5)) gui.text(1,82,string.format("%d", jump6)) gui.text(1,91,string.format("%d", jump7)) gui.text(1,100,string.format("%d", jump8))
gui.text(1,109,string.format("%d", jump9)) gui.text(1,118,string.format("%d", jump10)) gui.text(20,37,string.format("%d", jump11)) gui.text(20,46,string.format("%d", jump12)) 
gui.text(20,55,string.format("%d", jump13)) gui.text(20,64,string.format("%d", jump14))	gui.text(20,73,string.format("%d", jump15))	gui.text(20,82,string.format("%d", jump16)) 
gui.text(20,91,string.format("%d", jump17)) gui.text(20,100,string.format("%d", jump18)) gui.text(20,109,string.format("%d", jump19)) gui.text(20,118,string.format("%d", jump20))
end

-- Set Up variables for next frame's pass
lmtp=mtp
last=seed1
lastm=mtv

-- End Lua
emu.frameadvance() 
end

not adding the part that tracks battle RNG, for obvious reasons ;)

Edited by Kaphotics
typos, added black support
Link to comment
Share on other sites

i've been using this to watch the rng:

while true do
gui.text(1,185, string.format("%08X  %08X", memory.readdword(0x02216248), memory.readdword(0x02216244)))
emu.frameadvance()
end

lua is using windows' definition of a word when it runs, so you need to define a 32-bit value as a dword. also, for anyone who wants to try this out and isn't aware, the string.format method is really close to printf(), so you can use the variable definitins and other stuff for string.format(). for example, "%08X" is a capital letter hex value 8 digits large. "%08x" is the same thing but with lower case hex values, "%08u" is unsigned decimal, etc

Link to comment
Share on other sites

  • 1 month later...

I wonder... could the coordinate script maybe be used to create a world map of black and white? Something like: every time the coordinates change, save a new picture of the screen with the specified coordinates in the name? And then, by having some other script (maybe in LUA, or maybe in some completely other language) try to merge all these pictures together(i.e., grab the picture with the lowest X and Y, and then get the picture with the X and Y that are the second-lowest, and add that picture on top of the old one at X minus lowestX and Y minus lowestY, and so on.)

Link to comment
Share on other sites

  • 8 months later...

rng helper -- very old version. see first post for most up to date

PzWXH.png

-- RNG location for current game (English White)
local rng=0x02216244

-- setup terminology abbreviations
local rshift=bit.rshift
local mdword=memory.readdwordunsigned

-- setup initial variables = 0, rest of script detection will take care of them
local initl=0
local inith=0
local adv=0
local total=0
local last=0
local jump1=0

-- setup frame detection function
function next(s)
local a=0x6C07*(s%65536)+rshift(s,16)*0x8965
local b=0x8965*(s%65536)+(a%65536)*65536+0x00269EC3
local c=b%4294967296
return c
end

-- Lua script begin!
while true do

-- setup every loop
seed2=mdword(rng+4)
seed1=mdword(rng)
adv=0
test=last

-- display seeds every loop
gui.text(1,10,string.format("Current: %08X%08X",seed2,seed1))
gui.text(1,180,string.format("Initial: %08X%08X",inith,initl))
gui.text(180,10,string.format("Delay: %d", mdword(0x023FFC3C)))
gui.text(1,170, string.format("M: %d, X: %d, Y: %d, Z: %d", memory.readword(0x0224F92C), memory.readword(0x0224F932,2), memory.readword(0x0224F93A), memory.readword(0x0224F936))) -- copied from map coord Lua


-- check to see if the RNG advanced from the last value
while seed1~=0 and seed2~=0 do
	if adv>200 then -- RNG advanced a bunch. Reset script then stop loop.
		print(""..string.format("Detected a reset or massive advancement. Re-initializing."))
		adv  =0
		total=0
		jump1=0
		initl=mdword(rng)
		inith=mdword(rng+4)	
		print(""..string.format("Session Initial Seed: %08X%08X",inith,initl)) 
		break 

	elseif test~=seed1 then -- RNG advanced at least once. Lets advance once and repeat the loop.
		test=next(test)
		adv=adv+1
		jump1=adv

	elseif test==seed1 then break -- last frame's advanced RNG value matches the current. Stop loop.
	end
end

-- advancement tracking
total=adv+total
gui.text(1,19,string.format("Frame: %d", total))
gui.text(1,28,string.format("Jump: %d", jump1))
last=seed1

emu.frameadvance() 
end

main use is that it tracks RNG frames after keeping the seeds from the moment the script starts.

it grabs the initial seed when the game is reset, or the first seed it can find and keeps it stored as long as the script runs.

I may have it write the initial seeds it gets to somewhere so that upon loading a save state it can find and re-determine the frame (session preservation), but this was just for fun

Edited by Kaphotics
Link to comment
Share on other sites

Map Coordinates

poslua.png

White

while true do
gui.text(1,184, string.format("Map: %d, X: %d, Y: %d, Z: %d", memory.readword(0x0224F92C), memory.readword(0x0224F932,2), memory.readword(0x0224F93A), memory.readword(0x0224F936)))
emu.frameadvance()
end

Black

while true do
gui.text(1,184, string.format("Map: %d, X: %d, Y: %d, Z: %d", memory.readword(0x0224F90C), memory.readword(0x0224F912,2), memory.readword(0x0224F91A), memory.readword(0x0224F916)))
emu.frameadvance()
end

Download Link (English White)

Edited by Kaphotics
moved suite to top, map position to this post
Link to comment
Share on other sites

  • 1 month later...
  • 2 months later...

B2W2 Zonedata / Map Coordinates

uSbDT.png

Notes:

L toggles the raw zonedata display on/off. (default Q in DeSmuME)

local rshift, lshift=bit.rshift, bit.lshift
local md,mw,mb=memory.readdwordunsigned,memory.readwordunsigned,memory.readbyteunsigned
local gt,sf=gui.text,string.format
local table={}
local on,enbl,overprint,enblo=1,1,1,1

if mb(0x023FFE09)==0x00 then		-- Not "2" ~ Not B2/W2
  pos_m=md(0x02000024)+0x3461C
    zds=md(0x02000024)+0x3DFAC
owstart=md(0x02000024)+0x34E04
game=1
else
  pos_m=md(0x02000024)+0x36780
    zds=md(0x02000024)+0x41B2C
owstart=md(0x02000024)+0x36BE8
game=2
end

function main()
       table=joypad.get(1)
       if table.L then
               gt(0,0, "Toggling Display")
               enbl=0
       else
               if enbl==0 then on=(on+1)%2 enbl=1 end
       end

       if table.R then
               gt(0,0, "Printout")
               enblo=0
       else
               if enblo==0 then overprint=(overprint+1)%2 enblo=1 end
       end

       if on==0 then


	if game==2 then
		bike=rshift(mw(zds+2*15),10)%2
		 fly=rshift(mw(zds+2*15),13)%2
	else 
		bike=rshift(mb(zds+0x1F),2)%2
		 fly=rshift(mb(zds+0x1F),5)%2
end



               if bike==1 then
                       gt(159,110,sf("Bike - Enabled")) else
                       gt(159,110,sf("Bike - Disabled")) end
               if fly==1 then
                       gt(159,120,sf("Fly  - Enabled")) else
                       gt(159,120,sf("Fly  - Disabled")) end

               gt(1,50,sf("00-01: %04x",mw(zds+2*0)))        gt(80,50,sf("10-11: %04x",mw(zds+2*8)))       gt(159,50,sf("20-21: %04x",mw(zds+2*16)))
               gt(1,60,sf("02-03: %04x",mw(zds+2*1)))        gt(80,60,sf("12-13: %04x",mw(zds+2*9)))       gt(159,60,sf("22-23: %04x",mw(zds+2*17)))
               gt(1,70,sf("04-05: %04x",mw(zds+2*2)))        gt(80,70,sf("14-15: %04x",mw(zds+2*10)))      gt(159,70,sf("24-27: %08x",md(zds+2*18)))
               gt(1,80,sf("06-07: %04x",mw(zds+2*3)))        gt(80,80,sf("16-17: %04x",mw(zds+2*11)))      gt(159,80,sf("28-2B: %08x",md(zds+2*20)))
               gt(1,90,sf("08-09: %04x",mw(zds+2*4)))        gt(80,90,sf("18-19: %04x",mw(zds+2*12)))      gt(159,90,sf("2C-2F: %08x",md(zds+2*22)))
               gt(1,100,sf("0A-0B: %04x",mw(zds+2*5)))       gt(80,100,sf("1A-1B: %04x",mw(zds+2*13)))
               gt(1,110,sf("0C-0D: %04x",mw(zds+2*6)))       gt(80,110,sf("1C-1D: %04x",mw(zds+2*14)))
               gt(1,120,sf("0E-0F: %04x",mw(zds+2*7)))       gt(80,120,sf("1E-1F: %04x",mw(zds+2*15)))    
       end

if overprint==0 then 
	fcount=mb(0x4+owstart) ncount=mb(0x5+owstart) wcount=mb(0x6+owstart) tcount=mb(0x7+owstart)
	furnstart=0x8
	furnend=furnstart+0x14*fcount-1
	 npcstart=0x08+mb(0x04+owstart)*0x14
	 npcend= npcstart+0x24*ncount-1
	warpstart=0x08+mb(0x04+owstart)*0x14+mb(0x05+owstart)*0x24
	warpend=warpstart+0x14*wcount-1
	trigstart=0x08+mb(0x04+owstart)*0x14+mb(0x05+owstart)*0x24+mb(0x06+owstart)*0x14
	trigend=trigstart+0x16*tcount-1


	print(sf("Overworld Data [%d] @ 0x%08X",mw(zds+2*11),owstart))
	if fcount>0 then
		print(sf("[%d] Furniture Range: 0x%04X-0x%04X",fcount,furnstart,furnend)) else print(sf("[%d] No Furniture",fcount))
	end
	if ncount>0 then
		print(sf("[%d] NPC Range: 0x%04X-0x%04X",ncount,npcstart,npcend)) else print(sf("[%d] No NPCs",ncount))
	end
	if wcount>0 then
		print(sf("[%d] Warp Range: 0x%04X-0x%04X",wcount,warpstart,warpend)) else print(sf("[%d] No Warps",wcount))
	end
	if tcount>0 then
		print(sf("[%d] Trigger Range: 0x%04X-0x%04X",tcount,trigstart,trigend)) else print(sf("[%d] No Triggers",tcount))
	end
	if md(owstart)~=trigend-3 then print("Error in parsing, please be in game.") else print("Successful Parse!") end
	print("") print("")
overprint=1
end
gt(160,145,sf("Overworld: %5d",mw(zds+2*11)))
   gt(160,155,sf("Script: %8d",mw(zds+2*3)))
gt(160,165,sf("Text: %10d",mw(zds+2*5)))

flyx=md(zds+2*18)
flyy=md(zds+2*22)
flyz=md(zds+2*20)
if (flyx==5 and flyy==4 and flyz==0) or (flyx==13 and flyy==0 and flyz==5) then
gt(149,174,sf("Can't Fly to here.")) else
gt(185,174,sf("FlyTo (XYZ)"))
gt(185,184,sf("%d,%d,%d",flyx,flyy,flyz)) end

gt(1,145, sf("SubMap of Map: %3d",mw(zds+2*12)))
       if mw(zds+2*10)%256<255 then
               gt(1,155,sf("Slot Location: %d",mw(zds+2*10)%256)) else gt(1,155,sf("No Encounters Here!")) end

       gt(1,165, sf("Current Position"))
       gt(2,175, sf("M: %3d, X: %3d", mw(pos_m), mw(pos_m+0x6)))
gt(2,184, sf("Y: %3d, Z: %3d", mw(pos_m+0xE), mw(pos_m+0xA)))
end


gui.register(main)

Edited by Kaphotics
Link to comment
Share on other sites

  • 2 months later...

B2/W2 Script Parser

Reads the memory of the game and translates the script language to meaningful instructions similar to XSE and other scripting programs.

I primarily made the script to help me see how commands are used and help further our understanding of each command. No, it does not make the scripts, only interprets the hex.

I've made a ton of progress and the whole script is 90,000 characters! Too big to include in this post.

http://dl.dropbox.com/u/12206225/pporg/bw2scr/scrparse.lua

Old bare below.

local rshift, lshift=bit.rshift, bit.lshift
local wd,ww,wb=memory.writedword,memory.writeword,memory.writebyte
local rd,rw,rb=memory.readdwordunsigned,memory.readwordunsigned,memory.readbyteunsigned

mb=function(SRP)
return rb(SRP) 
end

mw=function(SRP)
return rb(SRP)+rb(SRP+1)*0x100 
end

md=function(SRP)
return rb(SRP)+rb(SRP+1)*0x100+rb(SRP+2)*0x10000+rb(SRP+3)*0x1000000
end

local gt,sf=gui.text,string.format
local table={}
local start=md(0x02000024)+0x459A4
local startscr=md(md(0x02000024)+0x459A4)+md(0x02000024)+0x0459A8
local SRP=start
local goscrp=0
local iterhead=0
local iterscr=0
local scrt={}
local scrnum=0
local scrindex=mw(md(0x02000024)+0x41B32)
local printiter=0
local catcherror=1
local itercatch=290



function main()
--Notify when analysis is starting:
	if SRP==start then	
		print(""..string.format("~Script File %d~",scrindex))
	end

while goscrp==0 and mw(SRP)~=0xFD13 and iterhead<35 do 
	readval=md(SRP)
	scrt[scrnum] = readval
	if rd(start) > 4000 then 
		print(""..sf("~Error Catch, Start Read Error~",curscr))
		goscrp=-1 end
	SRP=SRP+4
	scrnum=scrnum+1
	print(""..sf("Script %d: %08X",scrnum,readval))
	iterhead=iterhead+1
end

if scrnum>0 then gt(1,00,sf("%08X",scrt[0])) end
if scrnum>1 then gt(1,10,sf("%08X",scrt[1])) end
if scrnum>2 then gt(1,20,sf("%08X",scrt[2])) end
if scrnum>3 then gt(1,30,sf("%08X",scrt[3])) end
if scrnum>4 then gt(1,40,sf("%08X",scrt[4])) end

--Notify that Lua is ready to parse the script data
if mw(SRP)==0xFD13 and goscrp==0 then
	---print(""..sf("Finished Offset Parse")) 
	goscrp=1					--proceed to next phase
	SRP=SRP+2
	curscr=1
	end

--Begin 
while goscrp==1 and scrnum>=curscr and catcherror==1 and iterscr<300 do
		printiter=printiter+1
	if printiter>20 or iterscr>itercatch then 
		print(""..sf("~Error Catch, Command Read Error~",curscr))
		catcherror=0
		break 
	end

	print(""..sf("~~~~~Script %d~~~~~~",curscr))
		iterscr=1
		done=0
	while done==0 and md(SRP-2)~=0x0002 and (mw(SRP)~=0x5544 or mw(SRP)~=0x0000 or mw(SRP)~=0x4652) and iterscr<300 do
	if printiter>20 or iterscr>itercatch then 
		print(""..sf("~Error Catch, Command Read Error~",curscr))
		catcherror=0
		break 
	end
		cmd=mw(SRP)
		SRP=SRP+2
			if cmd==0x02 then 
			print(""..sf("End (0x0002)"))
			curscr=curscr+1
			if scrnum>=curscr then print(""..sf("~~~~~Script %d~~~~~~",curscr)) 
			else done=1
			end

		elseif cmd==0x04 then
			rt=md(SRP) SRP=SRP+4
			print(""..sf("CallRoutine (0x0004) 0x%08X",rt))

		elseif cmd==0x05 then 
			print(""..sf("End???[*TR] (0x0005)")) 

		elseif cmd==0x08 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("Logic08 (0x0008)  %s%d",fa,u16a))

		elseif cmd==0x09 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("Logic09 (0x0009)  %s%d",fa,u16a)) 

		elseif cmd==0x0A then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("Logic0A (0x000A)  %s%02X",fa,u16a))  

		elseif cmd==0x10 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("Readflag (0x0010)  %s%d",fa,u16a)) 

		elseif cmd==0x11 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("Logic11 (0x0011)  %s%d",fa,u16a)) 

		elseif cmd==0x19 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("CompareAtoB (0x0019) A=%s%d B=%s%d",fa,u16a,fb,u16b))


		elseif cmd==0x1C then
			std=mw(SRP) SRP=SRP+2
			print(""..sf("CallStd (0x001C) 0x%04X",std))


		elseif cmd==0x1D then
			std=mw(SRP) SRP=SRP+2
			print(""..sf("EndStdReturn[**] (0x001D)"))

		elseif cmd==0x1E then
			jump=md(SRP) SRP=SRP+4
			print(""..sf("GoTo (0x001E) jump=0x%08X",jump))

		elseif cmd==0x1F then
			logic=mb(SRP) SRP=SRP+1
			jump=md(SRP) SRP=SRP+4
			print(""..sf("IfThenGoTo (0x001F) 0x%02X jump=0x%08X",logic,jump))

		elseif cmd==0x23 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("SetFlag (0x0023)  %s%d",fa,u16a))  

		elseif cmd==0x24 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("ClearFlag (0x0023)  %s%d",fa,u16a)) 

		elseif cmd==0x26 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("SetVarEqCont (0x0028) %s%d %s%d",fa,u16a,fb,u16b)) 

		elseif cmd==0x27 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("SetVar27 (0x0027) %s%d %s%d",fa,u16a,fb,u16b)) 


		elseif cmd==0x28 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("SetVarEqVal (0x0028) %s%d %s%d",fa,u16a,fb,u16b)) 

		elseif cmd==0x2A then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("SetVarEq28 (0x002A) %s%d %s%d",fa,u16a,fb,u16b)) 

		elseif cmd==0x2E then 
			print(""..sf("LockAll (0x002E)"))  

		elseif cmd==0x2F then 
			print(""..sf("UnlockAll (0x002F)"))

		elseif cmd==0x30 then 
			print(""..sf("WaitMoment (0x0030)"))

		elseif cmd==0x32 then 
			print(""..sf("WaitKeyPress (0x0032)"))

		elseif cmd==0x33 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("EventMessage (0x0033) id=%s%d",fa,u16a))

		elseif cmd==0x34 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("GreyMessage (0x0034) id=%s%d view=%s%d",fa,u16a,fb,u16b))

		elseif cmd==0x35 then 
			print(""..sf("CloseEventMessage (0x0035)"))

		elseif cmd==0x36 then 
			print(""..sf("CloseGreyMessage (0x0036)"))



		elseif cmd==0x38 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u8a=mw(SRP) SRP=SRP+1
				if u8a/0x8000>=1 then fb="Var_" u8a=u8a%0x4000
				elseif u8a/0x4000>=1 then fb="Cont_" u8a=u8a%0x4000
				else fb="Num_"
				end
			print(""..sf("BubbleMessage (0x0038) %s%d %s%d",fa,u16a,fb,u8a)) 

		elseif cmd==0x39 then 
			print(""..sf("CloseBubbleMessage (0x0039)"))

		elseif cmd==0x3C then
			u8a=mb(SRP) SRP=SRP+1
			u8b=mb(SRP) SRP=SRP+1
			mid=mw(SRP)  SRP=SRP+2
				if mid/0x8000>=1 then fm="Var_" mid=mid%0x4000
				elseif mid/0x4000>=1 then fm="Cont_" mid=mid%0x4000
				else fm="Num_"
				end
			npc=mw(SRP) SRP=SRP+2
			view=mw(SRP) SRP=SRP+2
			type=mw(SRP) SRP=SRP+2
			print(""..sf("Message1 (0x003C) MID=%s%X NPC=%d",fm,mid,npc))

		elseif cmd==0x3D then
			u8a=mb(SRP) SRP=SRP+1
			u8b=mb(SRP) SRP=SRP+1
			mid=mw(SRP)  SRP=SRP+2
				if mid/0x8000>=1 then fm="Var_" mid=mid%0x4000
				elseif mid/0x4000>=1 then fm="Cont_" mid=mid%0x4000
				else fm="Num_"
				end
			view=mw(SRP) SRP=SRP+2
			type=mw(SRP) SRP=SRP+2
			print(""..sf("Message2 (0x003D) MID=%s%X",fm,mid))

		elseif cmd==0x3E then 
			print(""..sf("CloseMessage (0x003E)"))

		elseif cmd==0x3F then 
			print(""..sf("CloseMessage2[*] (0x003F)"))

		elseif cmd==0x43 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("BorderMessage (0x0028) id=%s%d color=%s%d",fa,u16a,fb,u16b)) 

		elseif cmd==0x44 then 
			print(""..sf("CloseBorderMessage (0x0044)")) 

		elseif cmd==0x47 then
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("PopYesNoVar (0x0047) 0x%04X",u16a))


		elseif cmd==0x48 then 
			u8a=mw(SRP) SRP=SRP+2
				if 	u8a/0x8000>=1 then 	f1="Var_"  u8a=u8a%0x4000
				elseif 	u8a/0x4000>=1 then 	f1="Cont_" u8a=u8a%0x4000
				else 				f1="Num_"
				end
			u8b=mw(SRP) SRP=SRP+2
				if 	u8b/0x8000>=1 then 	f2="Var_"  u8b=u8b%0x4000
				elseif 	u8b/0x4000>=1 then 	f2="Cont_" u8b=u8b%0x4000
				else 				f2="Num_"
				end
			u16a=mw(SRP) SRP=SRP+2
				if 	u16a/0x8000>=1 then 	fa="Var_"  u16a=u16a%0x4000
				elseif 	u16a/0x4000>=1 then 	fa="Cont_" u16a=u16a%0x4000
				else 				fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if 	u16b/0x8000>=1 then 	fb="Var_"  u16b=u16b%0x4000
				elseif 	u16b/0x4000>=1 then 	fb="Cont_" u16b=u16b%0x4000
				else 				fb="Num_"
				end
			u16c=mw(SRP) SRP=SRP+2
				if 	u16c/0x8000>=1 then 	fc="Var_"  u16c=u16c%0x4000
				elseif 	u16c/0x4000>=1 then 	fc="Cont_" u16c=u16c%0x4000
				else 				fc="Num_"
				end
			u16d=mw(SRP) SRP=SRP+2
				if 	u16d/0x8000>=1 then 	fd="Var_"  u16d=u16d%0x4000
				elseif 	u16d/0x4000>=1 then 	fd="Cont_" u16d=u16d%0x4000
				else 				fd="Num_"
				end
			u16e=mw(SRP) SRP=SRP+2
				if 	u16e/0x8000>=1 then 	fe="Var_"  u16e=u16e%0x4000
				elseif 	u16e/0x4000>=1 then 	fe="Cont_" u16e=u16e%0x4000
				else 				fe="Num_"
				end
			print(""..sf("Message3 (0x0048) %s%d %s%d %s%d %s%d %s%d %s%d %s%d",f1,u8a,f2,u8b,fa,u16a,fb,u16b,fc,u16c,fd,u16d,fe,u16e))


		elseif cmd==0x4B then 
			print(""..sf("CloseAngryMessage (0x004B)"))

		elseif cmd==0x4C then 
			u8a=mb(SRP) SRP=SRP+1
			print(""..sf("???? (0x004C), 0x%02X",u8a))

		elseif cmd==0x64 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u32a=md(SRP) SRP=SRP+4
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("Movement[***] (0x0064) A=%s%d color=%s%d",fa,u16a,fb,u32a)) 

		elseif cmd==0x65 then 
			print(""..sf("WaitMovement (0x0065)"))

		elseif cmd==0x68 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("StoreHeroPosition (0x0068) A=%s%d B=%s%d",fa,u16a,fb,u16b))

		elseif cmd==0x6C then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("???? (0x006C)  %s%d",fa,u16a)) 


		elseif cmd==0x6D then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa=""
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb=""
				end
			u16c=mw(SRP) SRP=SRP+2
				if u16c/0x8000>=1 then fc="Var_" u16c=u16c%0x4000
				elseif u16c/0x4000>=1 then fc="Cont_" u16c=u16c%0x4000
				else fc=""
				end
			u16d=mw(SRP) SRP=SRP+2
				if u16d/0x8000>=1 then fd="Var_" u16d=u16d%0x4000
				elseif u16d/0x4000>=1 then fd="Cont_" u16d=u16d%0x4000
				else fd=""
				end
			u16e=mw(SRP) SRP=SRP+2
				if u16e/0x8000>=1 then fe="Var_" u16e=u16e%0x4000
				elseif u16e/0x4000>=1 then fe="Cont_" u16e=u16e%0x4000
				else fe=""
				end
			print(""..sf("SetOWPos (0x006D) npc=%s%d x=%s%d y=%s%d z=%s%d dir=%s%d",fa,u16a,fb,u16b,fc,u16c,fd,u16d,fe,u16e))  

		elseif cmd==0x74 then
			print(""..sf("FacePlayer"))
		elseif cmd==0x85 then
			u16a=mw(SRP) SRP=SRP+2
				if 	u16a/0x8000>=1 then 	fa="Var_"  u16a=u16a%0x4000
				elseif 	u16a/0x4000>=1 then 	fa="Cont_" u16a=u16a%0x4000
				else 				fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if 	u16b/0x8000>=1 then 	fb="Var_"  u16b=u16b%0x4000
				elseif 	u16b/0x4000>=1 then 	fb="Cont_" u16b=u16b%0x4000
				else 				fb="Num_"
				end
			u16c=mw(SRP) SRP=SRP+2
				if 	u16c/0x8000>=1 then 	fc="Var_"  u16c=u16c%0x4000
				elseif 	u16c/0x4000>=1 then 	fc="Cont_" u16c=u16c%0x4000
				else 				fc="Num_"
				end
			print(""..sf("TrBattle (0x0085) Opp1=%s%d Opp2=%s%d Logic=%s%d",fa,u16a,fb,u16b,fc,u16c))

		elseif cmd==0x8C then 
			print(""..sf("EndBattle (0x008C)")) 

		elseif cmd==0x8D then
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("SetVarBattleResult (0x008D) %s%d",fa,u16a))

		elseif cmd==0x8E then 
			print(""..sf("DisableTrainer (0x008E)")) 

		elseif cmd==0xA6 then
			u16a=mw(SRP) SRP=SRP+2
			print(""..sf("PlaySound (0x00A6) opp1=0x%X opp2=0x%X logic=%d",u16a,u16b,u16c))



		elseif cmd==0xCB then
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
			print(""..sf("StoreRand (0x00CB) %s%d rand(0x%d)",fa,u16a,u16b)) 


		elseif cmd==0xCC then
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("SetVarQualItem (0x00CC) %s%d",fa,u16a))

		elseif cmd==0xCD then
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("SetVarQual???? (0x00CD) %s%d",fa,u16a))



		elseif cmd==0x227 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("??? (0x0227) A=%s%d B=%s%d",fa,u16a,fb,u16b))

		elseif cmd==0x24F then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa=""
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb=""
				end
			u16c=mw(SRP) SRP=SRP+2
				if u16c/0x8000>=1 then fc="Var_" u16c=u16c%0x4000
				elseif u16c/0x4000>=1 then fc="Cont_" u16c=u16c%0x4000
				else fc=""
				end
			u16d=mw(SRP) SRP=SRP+2
				if u16d/0x8000>=1 then fd="Var_" u16d=u16d%0x4000
				elseif u16d/0x4000>=1 then fd="Cont_" u16d=u16d%0x4000
				else fd=""
				end
			print(""..sf("????? (0x024F) A=%s%d B=%s%d C=%s%d D=%s%d",fa,u16a,fb,u16b,fc,u16c,fd,u16d))  

		elseif cmd==0x276 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			u16b=mw(SRP) SRP=SRP+2
				if u16b/0x8000>=1 then fb="Var_" u16b=u16b%0x4000
				elseif u16b/0x4000>=1 then fb="Cont_" u16b=u16b%0x4000
				else fb="Num_"
				end
			print(""..sf("??? (0x0276) A=%s%d B=%s%d",fa,u16a,fb,u16b))

		elseif cmd==0x2C5 then 
			u16a=mw(SRP) SRP=SRP+2
				if u16a/0x8000>=1 then fa="Var_" u16a=u16a%0x4000
				elseif u16a/0x4000>=1 then fa="Cont_" u16a=u16a%0x4000
				else fa="Num_"
				end
			print(""..sf("??? (0x02C5) A=%s%d",fa,u16a))






		else
		print(""..sf("0x%X",cmd))
		iterscr=iterscr+1
		end
	end








end

if goscrp==1 and scrnum<curscr then 
print(""..sf("~~~~~~Finish~~~~~~")) 
goscrp=2 end


gt(1,70,sf("Total Scripts: %d",scrnum))
gt(1,80,sf("Attempts: %d",iterhead))

gt(1,90,sf("SRP: %08X",SRP))
if goscrp==2 then gt(1,100,sf("~~~~~Finish~~~~~")) end














end
gui.register(main)

Some examples of what it creates in the Console window:

http://pastebin.com/raw.php?i=72nRf1aa

http://pastebin.com/raw.php?i=fRBaRPkv

http://pastebin.com/raw.php?i=gMRLPeuR

http://pastebin.com/raw.php?i=TpgbtWnF

To use it, the script file must be already loaded in game. Talk to an NPC that uses a script from the script file so that the game will have it loaded in the memory. Some locations don't work, I've only tested it indoors.

I'll be updating it when I get time, school comes first :) Unknown/Un-programmed commands can throw off the parse so in general don't trust anything when it starts reporting hex.

Edited by Kaphotics
Link to comment
Share on other sites

  • 2 months later...

Overworld Editing for BW/B2W2

5dA9V.jpg

Edits a single memory value of all overworlds of a certain type (say NPC->Overworld Sprite) to help the user position/assign overworlds properly. Pretty useful in finding out overworld sprite values. Enable (and keep on) before a fade2black map change, not a seamless route change. Even though the pic is B2W2, it works in BW. Current setup is to edit the sprite of all overworld NPCs.

local rshift, lshift=bit.rshift, bit.lshift
local wd,ww,wb=memory.writedword,memory.writeword,memory.writebyte
local rd,rw,rb=memory.readdwordunsigned,memory.readwordunsigned,memory.readbyteunsigned
mb=function(x) return rb(x) 							end
mw=function(x) return rb(x)+rb(x+1)*0x100 					end
md=function(x) return rb(x)+rb(x+1)*0x100+rb(x+2)*0x10000+rb(x+3)*0x1000000 	end
local gt,sf=gui.text,string.format

if mb(0x023FFE09)==0x00 then		-- Not "2" ~ Not B2/W2
  pos_m=md(0x02000024)+0x3461C
    zds=md(0x02000024)+0x3DFAC
ows=md(0x02000024)+0x34E04
game=1
else
  pos_m=md(0x02000024)+0x36780
    zds=md(0x02000024)+0x41B2C
ows=md(0x02000024)+0x36BE8
game=2
end

local useupper=true
local L8=0x01
local U8=0x00
local edit="NPC"

local mapexit=1
local offset=0x02 --sprite. change to 0xA for script reassigning



function main()
--L8=math.random(500)
--mapexit=math.random(6)

if edit=="Furniture" then mode=1 
mult=0x14 
editat=0x08+ows
elseif edit=="NPC" then 
mode=2
mult=0x24 
editat=0x08+mb(0x04+ows)*0x14+ows
elseif edit=="Warp" then 
mode=3
mult=0x14 
editat=0x08+mb(0x04+ows)*0x14+mb(0x05+ows)*0x24+ows
elseif edit=="Trigger" then 
mode=4 
mult=0x16 
editat=0x08+mb(0x04+ows)*0x14+mb(0x05+ows)*0x24+mb(0x06+ows)*0x14+ows end
count=mb(ows+3+mode)

--word editing mode
if useupper==true then
if mw(editat+offset)~=(L8+U8*0x100) then i=0
   gt(1,00,sf("Map is Switching!"))
	while i<count do
		insert=(L8+U8*0x100)
		if mode==3 then ww(i*mult+offset+editat+4,mapexit) end
		ww(i*mult+offset+editat,insert)
		i=i+1
	end
end end

--byte editing mode
if useupper==false then 
if mb(editat+offset)~=(L8) then i=0
   gt(1,00,sf("Map is Switching!"))
	while i<count do
		insert=(L8)
		if mode==3 then ww(i*mult+offset+editat+4,mapexit) end
		wb(i*mult+offset+editat,insert)
		i=i+1
	end
end end

--Debug
gt(1,10,sf("OW Data Start: %08X",ows))
gt(1,20,sf("Desired Count: %d",count))
gt(1,30,sf("Start of Desired Data: %08X",editat))
gt(1,40,sf("Mode: %s",edit))

end
gui.register(main)

Event Script writer for BW & B2/W2

b9504.jpg

Replaces the first script of the current map with a customized event script. Be sure the current event script file is loaded before enabling in order to write to the proper area.

Allows a user to test an event script in real time, and change up instructions on the fly rather than tinker with the ROM. Be sure to buffer the event script file that is being edited with zeroes such that a long custom script won't overwrite other important memory locations. This is how I tested both of

on my YouTube channel.

local wb,md,gt,sf=memory.writebyte,memory.readdwordunsigned,gui.text,string.format
local rd,rw,rb=memory.readdwordunsigned,memory.readwordunsigned,memory.readbyteunsigned
mb=function(x) return rb(x) 							end
mw=function(x) return rb(x)+rb(x+1)*0x100 					end
md=function(x) return rb(x)+rb(x+1)*0x100+rb(x+2)*0x10000+rb(x+3)*0x1000000 	end
local i,j,x,t=1,1,1,{}

if mb(0x023FFE09)==0x00 then		-- Not "2" ~ Not B2/W2
  pos_m=md(0x02000024)+0x3461C
    zds=md(0x02000024)+0x3DFAC
ows=md(0x02000024)+0x34E04
scstart=md(md(0x02000024)+0x41834)+md(0x02000024)+0x41838
game=1
else
  pos_m=md(0x02000024)+0x36780
    zds=md(0x02000024)+0x41B2C
ows=md(0x02000024)+0x36BE8
scstart=md(md(0x02000024)+0x459A4)+md(0x02000024)+0x0459A8
game=2
end

function main()

--List all portions of or script
s1="2E 00"
s2=""
s3=""
s4="02 00"

--Concatenate all strings in order
s=s1..s2..s3..s4

--Remove spaces from eventscript so that we can add the script in
s = string.gsub (s, " ", "")

--Break up eventscript string into a table
while i<=string.len(s) do
t[j] ="0x"..string.sub(s,i,i+1)
j=j+1
i=i+2
end

--Write script per byte via values in the table.
while x<j do
wb(scstart+x-1,t[x])
--Graphical display of text
gt((x-1)%10*15,math.floor((x-1)/0xA)*10,sf("%02X",t[x]))
x=x+1
end

x=1
end
gui.register(main)

Edited by Kaphotics
Link to comment
Share on other sites

  • 3 months later...
  • 1 month later...
  • 2 months later...
  • 2 years later...

I'm trying to find or get working a version of this for White (J) does anyone have one that I could get please?

I have tried modifying this script using the rng and mtrng values from the notable breakpoints page on the wiki for the Japanese versions of the game but it never works.

It reports a seed but it is always wrong and the frames don't track right. Along with it randomly pausing the emulator with the following error.

"Save state's session did not start with script."

"Either load a valid save state or resume with this one."

The only thing I got working right is the map position and that I don't use. I tracked the correct pos_m offset for White (J) on my own. It is pos_m=0x0224F78C which could be useful for other people.

Edited by shadowofdarkness
fix formatting
Link to comment
Share on other sites

  • 4 years later...
  • 1 year later...

Sorry to necro a thread but @Kaphotics I have been scouring the web for zonedata tools for BW1. This is the closest I have found, but it's for BW2. The scripts don't seem to work on the original versions, and I am not skilled enough with the internals of these games to modify the scripts to work on the originals. Do you by any chance have scripts that work for BW1 or could point me in the right direction on how to modify the BW2 ones?

  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...