ラスボスの倒し方

重要のはダッシュの原点のX座標です。だが、問題があります。座標はpixelより細かくて、画面で区別出来ません。例えばX=100に立ってるMaximとX=100.5に立ってるMaximの表示が画面に全く同じです。

ダッシュする前は左に歩く必要ありますからダッシュの原点より歩く前の座標が便利と思います。

2フレーム間左押して、3フレーム目に右にダッシュすると成功出来る原点は:

91.7592.5
96.2597
100.75101.5
105.25106
109.75110.5
114.25115

(正確にいうと上記のは半開区間で右開です。)

歩く速度は2フレームで5 pixelだからX=97から始めると4フレーム間左押して5フレーム目にダッシュとかでも大丈夫です。

剣を振るうタイミングはホァイが出来るか出来ないかしか影響ありません。

RTAする時に座標は整数の部分しか分かりませんので2か4か6行目がいいと思います。(整数じゃない部分がなんとか出来るか英語のDiscordに聞きましたが返事がありません。)

崖からダッシュの原点の距離で空中なる座標が決まります。速度と加速はその時点まで固定されてるのでその座標は軌道決まります。

ダッシュの速度は1フレームで4.5 pixelだから上の座標は4.5 pixel離れています。(例えば96.25 - 91.75 = 4.5)

座標と表示

96 105 114
X =

Golem

296 305 314 323
X =

どうでもいい事

Robert Ordisさんのお陰でゲームの内部は簡単に弄り事できた。Twitterに参考になったスクリプトのリンクある。

BizHawk(mGBAコア)というエミュレータ使った。書いたLuaスクリプトは下にある。

byakuyahelpers.lua

function inputs(t)
        local i = {}
        i['A'] = false
        i['B'] = false
        i['Down'] = false
        i['L'] = false
        i['Left'] = false
        i['Power'] = false
        i['R'] = false
        i['Right'] = false
        i['Select'] = false
        i['Start'] = false
        i['Light Sensor'] = 0
        i['Tilt X'] = 0
        i['Tilt Y'] = 0
        i['Tilt Z'] = 0
        i['Up'] = false

        for _,v in ipairs(t) do i[v] = true end
        return i
end

function fromEighths(n)
        return n << 13
end

function fromFloat(n)
        return math.floor(n / 0.125 + 0.5)
end

function toFloat(n)
        return (n >> 13) * 0.125
end

function toEighths(n)
        return n >> 13
end

MemVar = {}
function MemVar:setup()
        local mt = {
                __index = function(t, k)
                        local vars = rawget(t, "vars")
                        if vars[k] then
                                return vars[k].read(vars[k].addr, vars[k].domain)
                        else
                                return self[k]
                        end
                end,
                __newindex = function(t, k, v)
                        local vars = rawget(t, "vars")
                        if vars[k] then
                                vars[k].write(vars[k].addr, v, vars[k].domain)
                        else
                                rawset(t, k, v)
                        end
                end
        }

        local ret = setmetatable({}, mt)
        rawset(ret, "vars", {})
        return ret
end

function MemVar:vz()
        return rawget(self, "vars")
end

function MemVar:reg(t)
        local v = {}
        v.addr = t.addr
        v.domain = t.domain or "System Bus"
        v.bits = t.bits or 16
        v.signed = t.signed == nil and true or t.signed

        func = (v.signed and "s" or "u") .. v.bits .. ((v.bits > 8) and "_le" or "")
        v.read = memory["read_" .. func]
        v.write = memory["write_" .. func]

        local vars = rawget(self, "vars")
        vars[t.name] = v
end

function dumppos()
        print("x = " .. v.xPos + toFloat(v.xPosFrac) + v.xCam .. " y = " .. v.yPos + toFloat(v.yPosFrac) + v.yCam)
end

v = MemVar:setup()
--v:reg({name="hp", addr=0x0201854e})
v:reg({name="xPos", addr=0x2000462})
v:reg({name="xPosFrac", addr=0x02000460, signed=false})
v:reg({name="yPos", addr=0x02000466})
v:reg({name="yPosFrac", addr=0x02000464, signed=false})

v:reg({name="xAcc", addr=0x02000470})
v:reg({name="yAcc", addr=0x02000474})

v:reg({name="pushRight", addr=0x03001A24})

v:reg({name="xCam", addr=0x0200A446})
v:reg({name="yCam", addr=0x0200A44A})

v:reg({name="xVel", addr=0x0200046A})
v:reg({name="xVelFrac", addr=0x02000468, signed=false})
v:reg({name="yVel", addr=0x0200046E})
v:reg({name="yVelFrac", addr=0x0200046C, signed=false})

brute.lua

require("byakuyahelpers")

for x=88, 116 do
        for frac=0, 7 do
                savestate.loadslot(1)
                v.xPos = x
                v.xPosFrac = fromEighths(frac)
                emu.frameadvance()

                joypad.set(inputs({"Left"}))
                emu.frameadvance()
                joypad.set(inputs({"Left"}))
                emu.frameadvance()
                joypad.set(inputs({"R"}))
                emu.frameadvance()

                while v.yAcc == 0 do emu.frameadvance() end
                joypad.set(inputs({"B"}))

                while v.yPos + v.yCam > 214 and v.yPos + v.yCam < 240 do emu.frameadvance() end
                if v.yPos + v.yCam < 214 then
                        print("PASS " .. x + frac * 0.125)
                end
        end
end

screenshot.lua

require("byakuyahelpers")

function fa(n, i)
        for _=1, n do
                if i then joypad.set(i) end
                emu.frameadvance()
        end
end

for x=88,116 do
        savestate.loadslot(1)
        v.xPos = x
        v.xPosFrac = 0
        emu.frameadvance()

        joypad.set(inputs({"Left"}))
        fa(10)
        client.screenshot(string.format("%d left.png", x))

        fa(10, inputs({"Down"}))
        client.screenshot(string.format("%d left crouch.png", x))

        joypad.set(inputs({"Right"}))
        fa(10)
        client.screenshot(string.format("%d right.png", x))

        joypad.set(inputs({"Down"}))
        fa(10, inputs({"Down"}))
        client.screenshot(string.format("%d right crouch.png", x))
end