Script to display the RNG in Fire Emblem 12
local rngbase=0x1BC09C
function nextSuperRN(r1, r4)
-- Given four sequential RNG values, generate the value after it
local RES = bit.bxor(r1, bit.rshift(r1, 8))
local TEMP = (r1 % 2^21)
RES = bit.bxor(RES, bit.lshift(TEMP, 3))
RES = bit.bxor(RES, bit.lshift(TEMP, 11))
RES = bit.bxor(RES, r4)
RES = bit.bxor(RES, bit.rshift(r4, 19))
return bit.band(RES,0xFFFFFFFF)
end
function getbit(NUM, BIT)
return math.floor((NUM % 2^BIT) / 2^(BIT-1))
end
function previousSuperRN(r4, r5)
-- Given four sequential RNG values, generate the value before it
-- Can most likely be simplified with some bit shifting but for now this will do
local val = bit.bxor(r5, bit.rshift(r4, 19))
val = bit.bxor(val, r4)
local val2 = {0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0} --32 bits
for i = 1, 32 do
val2[i] = getbit(val, i)
end
local RES = {0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0} --32 bits
for i = 1, 8 do
RES[i] = (val2[i] + val2[i+8] + val2[i+16] + val2[i+24]) % 2
end
for i = 9, 11 do
RES[i] = (val2[i] + val2[i+8] + val2[i+16]) % 2
end
for i = 12, 16 do
RES[i] = (val2[i] + val2[i+8] + val2[i+16] + RES[i-11]) % 2
end
for i = 17, 24 do
RES[i] = (val2[i] + val2[i+8] + RES[i-11]) % 2
end
for i = 25, 32 do
RES[i] = (val2[i] + RES[i-11]) % 2
end
local RES2 = 0
for i = 1, 32 do
RES2 = RES2 + RES[i]*(2^(i-1))
end
return RES2
end
function rngsim(n)
--Simulate the next n random numbers, including the 4 already in the RAM
local result = {
memory.read_u32_le(rngbase, "Main RAM");
memory.read_u32_le(rngbase + 0x4, "Main RAM");
memory.read_u32_le(rngbase + 0x8, "Main RAM");
memory.read_u32_le(rngbase + 0xC, "Main RAM")
}
for i = 5, n do
result[i] = nextSuperRN(result[i-4], result[i-1])
end
return result
end
function decrementRNG()
local RNG2 = memory.read_u32_le(rngbase + 0x0, "Main RAM")
local RNG3 = memory.read_u32_le(rngbase + 0x4, "Main RAM")
local RNG4 = memory.read_u32_le(rngbase + 0x8, "Main RAM")
local RNG5 = memory.read_u32_le(rngbase + 0xC, "Main RAM")
local RNG1 = previousSuperRN(RNG4, RNG5)
-- Swap the RNG values 2,3,4,5 by the RNG values 1,2,3,4
memory.write_u32_le(rngbase + 0x0, RNG1, "Main RAM")
memory.write_u32_le(rngbase + 0x4, RNG2, "Main RAM")
memory.write_u32_le(rngbase + 0x8, RNG3, "Main RAM")
memory.write_u32_le(rngbase + 0xC, RNG4, "Main RAM")
end
function incrementRNG()
local RNG1 = memory.read_u32_le(rngbase + 0x0, "Main RAM")
local RNG2 = memory.read_u32_le(rngbase + 0x4, "Main RAM")
local RNG3 = memory.read_u32_le(rngbase + 0x8, "Main RAM")
local RNG4 = memory.read_u32_le(rngbase + 0xC, "Main RAM")
local RNG5 = nextSuperRN(RNG1, RNG4)
-- Swap the RNG values 1,2,3,4 by the RNG values 2,3,4,5
memory.write_u32_le(rngbase + 0x0, RNG2, "Main RAM")
memory.write_u32_le(rngbase + 0x4, RNG3, "Main RAM")
memory.write_u32_le(rngbase + 0x8, RNG4, "Main RAM")
memory.write_u32_le(rngbase + 0xC, RNG5, "Main RAM")
end
function rngsim2(n)
--Simulate the previous n random numbers, including the 4 already in the RAM
local result = {
memory.read_u32_le(rngbase + 0xC, "Main RAM");
memory.read_u32_le(rngbase + 0x8, "Main RAM");
memory.read_u32_le(rngbase + 0x4, "Main RAM");
memory.read_u32_le(rngbase, "Main RAM")
}
for i = 5, n+4 do
result[i] = previousSuperRN(result[i-3], result[i-4])
end
return result
end
while true do
userInput = input.get()
if userInput.I then decrementRNG() end
if userInput.O then incrementRNG() end
local nsim = 40
rngs = rngsim(40)
rngs2 = rngsim2(25)
for i = 1, nsim do
gui.text(480, 196+15*(i-1), string.format("%3d", (rngs[i]%2147483648)%100))
end
gui.text(465, 196+60, "->", "red")
for i = 1, 13 do
gui.text(480, 196-15*i, string.format("%3d", (rngs2[i+4]%2147483648)%100), "white")
end
emu.frameadvance()
end