首页  >  问答  >  正文

获取模拟器错误

<p>我一直在尝试对我在网上找到的 GBA 模拟器 (https://gba.44670.org/) 进行逆向工程,并使用 HTML 提取器来尝试复制它。我希望它能够离线工作,所以我将所有脚本下载到我的计算机上,并在那里运行。但是,此后,“选择文件”按钮不再出现,取而代之的是“正在加载,请稍候...”文本行。深入研究代码,我发现它与 WASM 有关。代码如下:</p> <pre class="brush:php;toolbar:false;"><div id="wasm-loading"> Loading, please wait... </div> <div id="select-rom" hidden> <input type="file" id="romFile" onchange="onFileSelected()" hidden /></p> <button onclick="$id('romFile').click()" id="btn-choose">Choose File...</button> </div></pre> <p>代码中对 WASM 的其他提及位于 .js 文件 app.js 中:</p> <pre class="brush:php;toolbar:false;">function wasmReady() { romBuffer = Module._emuGetSymbol(1) var ptr = Module._emuGetSymbol(2) wasmSaveBuf = Module.HEAPU8.subarray(ptr, ptr + wasmSaveBufLen) ptr = Module._emuGetSymbol(3) imgFrameBuffer = new Uint8ClampedArray(Module.HEAPU8.buffer).subarray(ptr, ptr + 240 * 160 * 4) idata = new ImageData(imgFrameBuffer, 240, 160) isWasmReady = true document.getElementById('wasm-loading').hidden = true document.getElementById('select-rom').hidden = false }</pre> <p>我期望一旦我下载了脚本,它就会像平常一样工作。我的意思是,它仍然可以访问它需要的脚本,对吧?我尝试通过更改 <code>document.getElementById('select-rom').hidden = false</code> 中的 true/false 语句来隐藏文本,反之亦然,但似乎没有任何效果。有任何想法吗?提前致谢。</p> <p>(顺便说一句,我正在 vscode.dev 中查找文件路径。它看起来像这样: <code><script src="/Scripts/44gba.js"></script> <script src="/Scripts /app.js"></script> <script src="/Scripts/localforage.js"></script> <script src=/Scripts/pako.min.js></script></code> )</p>
P粉447495069P粉447495069414 天前788

全部回复(1)我来回复

  • P粉550823577

    P粉5508235772023-09-02 11:05:59

    要使用脚本将应用程序保留在本地,请记住两件事:

    1. 脚本已经编写完毕,将在当前App目录结构中查找资源(js、css、图片)
    2. 大多数浏览器中的请求和文件读取都会被 CORS 阻止,除非您停用 CORS 预检检查。

    也就是说,复制您在响应中得到的相同 HTML (https://gba.44670.org/ ),这将保留文件结构。这是我得到的内容(index.html):

    <html lang="en"><head>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black">
        <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height">
        <link rel="apple-touch-icon" href="icon.png">
        <link rel="manifest" href="manifest.json">
        <title>44VBA</title>
    
    </head>
    
    <body>
        <style>
            a,
            a:visited {
                color: white;
            }
    
            html,
            body {
                position: fixed;
                overflow: hidden;
                -webkit-user-select: none;
                user-select: none;
                -webkit-touch-callout: none;
                touch-action: none;
                cursor: inherit;
            }
    
            body {
    
                background-color: #000000;
                color: #FFFFFF;
                padding: 0;
                margin: 0;
                width: 100vw;
                height: 100vh;
                font-family: 'Myriad Set Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif;
            }
    
            hr {
                color: white;
            }
    
            button {
                border: 2px solid white;
                background: transparent;
                color: white;
                padding: .5em;
            }
    
            .vk-round {
                text-align: center;
                vertical-align: middle;
                border-radius: 50%;
                display: inline-block;
            }
    
    
            .vk {
                color: rgba(0, 0, 0, 0.2);
                background-color: rgba(255, 255, 255, 0.25);
                position: absolute;
                z-index: 1;
                text-align: center;
                vertical-align: middle;
                display: inline-block;
            }
    
            .vk-hide {
                background-color: transparent !important
            }
    
            .vk-touched {
                background-color: rgba(255, 255, 255, 0.75) !important
            }
    
            .menu {
                background: rgb(32, 43, 56);
                position: absolute;
                left: 0;
                top: 0;
                width: 100vw;
                height: 100vh;
                z-index: 999;
            }
    
            #gba-canvas {
                position: absolute;
                z-index: -1;
            }
    
            #vk-layer {
                position: absolute;
                left: 0;
                top: 0;
                width: 100%;
                height: 100%;
                z-index: 3;
                touch-action: none;
            }
    
            #msg-layer {
                position: absolute;
                left: 0;
                width: 100%;
                top: 40vh;
                background: rgba(0, 0, 0, 0.5);
                z-index: 2;
            }
    
            textarea {
                background: transparent;
                color: #fff;
                border: 2px solid white;
    
            }
    
            /* textarea placeholder */
            textarea::placeholder {
                color: #666;
            }
        </style>
        <div id="pause-menu" class="menu" style="background: rgba(32,43,56,0.7);" hidden="">
            <button onclick="setPauseMenu(false)"> ← Back </button>
            <hr>
            Savegame management:<br>
            <button onclick="savBackupBtn()">Backup</button>
            <input type="file" id="sav-file" onchange="savRestoreBtn()" hidden="">
            <button onclick="$id('sav-file').click()">Restore</button>
            <hr>
            <label for="cfg-scale-mode">Screen filter:</label>
            <select id="cfg-scale-mode">
                <option value="0">Pixelated</option>
                <option value="1">Smooth</option>
                <option value="2">XBRZ</option>
            </select><br>
            <input type="checkbox" id="cfg-mute">
            <label for="cfg-mute">Mute Sound</label><br>
            <input type="checkbox" id="cfg-turbo">
            <label for="cfg-turbo">Turbo mode</label><br>
            <div id="div-cht">
                Cheat Codes(backup your savegame before using it):<br>
                <textarea id="txt-code" style="width:100%" rows="10" placeholder="Cheat code:
    GamesharkAdv: XXXXXXXX YYYYYYYY
    CodeBreaker: XXXXXXXX YYYY"></textarea><br>
                <button onclick="chtSaveBtn()">Save Cheat Codes</button>
            </div>
            <hr>
            Cloud Save:<span id="span-cloud-id"></span><br>
            <button onclick="dpOnConnectButtonClicked()" id="btn-dp-connect">Connect Dropbox</button><br>
            <button onclick="dpManualBtn(true)">↑ Upload</button>|<button onclick="dpManualBtn(false)">↓ Download</button><br>
        </div>
        <div id="welcome" class="menu">
            <h1 id="title">44VBA</h1>
            <hr>
            <div id="wasm-loading" hidden="">
                Loading, please wait...
            </div>
            <div id="select-rom">
                <input type="file" id="romFile" onchange="onFileSelected()" hidden=""><p></p>
                <button onclick="$id('romFile').click()" id="btn-choose">Choose File...</button>
            </div>
            <hr>
            Ver. 20230107 | <a href="https://github.com/44670/44vba">GitHub</a>
            <p>
                Your files are processed locally and won't be uploaded to any server.<br>
                This software should not be used to play games you have not legally obtained.<br>
                "GBA", "Game Boy Advance" are trademarks of Nintendo Co.,Ltd, This site is not associated with Nintendo in
                any way.
            </p>
            <div id="ios-hint" hidden="">
                Due to iOS limitations, please open this site(https://gba.44670.org) in <b>Safari</b>, and add it to your
                <b>Home Screen</b> by <b>Share Menu</b> to continue.
                <p style="text-align: center;">⬇⬇⬇</p>
            </div>
        </div>
        <div id="msg-layer" hidden="">
            <p id="msg-text">Gamepad disconnected.</p>
        </div>
        <div id="vk-layer" hidden="">
            <div class="vk-rect vk" data-k="menu" style="top: 25px; left: 591px; width: 150px; height: 25px; font-size: 35px; line-height: 25px;">Menu</div>
            <div class="vk-rect vk" data-k="turbo" style="top: 25px; left: 0px; width: 150px; height: 25px; font-size: 35px; line-height: 25px;">F.F.</div>
            <div class="vk-rect vk" data-k="l" style="top: 75px; left: 0px; width: 150px; height: 50px; font-size: 35px; line-height: 50px;">L</div>
            <div class="vk-rect vk" data-k="r" style="top: 75px; left: 591px; width: 150px; height: 50px; font-size: 35px; line-height: 50px;">R</div>
            <div class="vk-round vk" data-k="a" style="top: 175px; left: 676px; width: 65px; height: 65px; font-size: 35px; line-height: 65px;">A</div>
            <div class="vk-round vk" data-k="b" style="top: 200px; left: 585px; width: 65px; height: 65px; font-size: 35px; line-height: 65px;">B</div>
            <div class="vk-rect vk" data-k="select" style="top: 605px; left: 205.5px; width: 150px; height: 25px; font-size: 35px; line-height: 25px;">Select</div>
            <div class="vk-rect vk" data-k="start" style="top: 605px; left: 385.5px; width: 150px; height: 25px; font-size: 35px; line-height: 25px;">Start</div>
            <div class=" vk" data-k="left" style="top: 200px; left: 0px; width: 50px; height: 50px; font-size: 35px; line-height: 50px;">←</div>
            <div class=" vk" data-k="right" style="top: 200px; left: 100px; width: 50px; height: 50px; font-size: 35px; line-height: 50px;">→</div>
            <div class=" vk" data-k="up" style="top: 150px; left: 50px; width: 50px; height: 50px; font-size: 35px; line-height: 50px;">↑</div>
            <div class=" vk" data-k="down" style="top: 250px; left: 50px; width: 50px; height: 50px; font-size: 35px; line-height: 50px;">↓</div>
            <div class=" vk vk-hide" style="top: 150px; left: 0px; width: 50px; height: 50px; font-size: 35px; line-height: 50px;" data-k="ul"></div>
            <div class=" vk vk-hide" style="top: 150px; left: 100px; width: 50px; height: 50px; font-size: 35px; line-height: 50px;" data-k="ur"></div>
            <div class=" vk vk-hide" style="top: 250px; left: 0px; width: 50px; height: 50px; font-size: 35px; line-height: 50px;" data-k="dl"></div>
            <div class=" vk vk-hide" style="top: 250px; left: 100px; width: 50px; height: 50px; font-size: 35px; line-height: 50px;" data-k="dr"></div>
        </div>
        <canvas width="240" height="160" id="gba-canvas" style="width: 741px; height: 494px; left: 0px; image-rendering: pixelated;"></canvas>
        <script src="pako.min.js"></script>
        <script src="localforage.js"></script>
        <script src="app.js"></script>
        <script src="build/44gba.js"></script>
    
    
    
    
    </body></html>

    然后您可以看到脚本路径,您将按照该路径创建文件:

    <script src="pako.min.js"></script>
    <script src="localforage.js"></script>
    <script src="app.js"></script>
    <script src="build/44gba.js"></script>

    此外,您还需要下载 WASM 文件(压缩后 651KB,未压缩 7.7MB)。您可以在此处下载压缩包(您可以在开发工具的“网络”选项卡中找到它):https ://gba.44670.org/build/44gba.wasm

    最后,下载所有必要的文件(如果需要,还可以下载图标和图片,但不是必需的):

    您将得到如下所示的结构:

    现在,如果您可以从浏览器中停用 CORS,那就太好了。但如果没有,您必须从本地 HTTP 服务器提供服务。一种选择是安装 NPM 包: https://www.npmjs.com/package/http-服务器,运行npm install --global http-server。之后,只需导航到终端中的项目目录并启动服务器:

    npx http-server ./ --port 4000

    您将看到正确的屏幕并加载 ROM,然后就完成了。

    编辑:通过简单的 Hack 解决本地 CORS 问题

    由于我知道您现在使用的是 ChromeOS,并且从技术上讲还不知道如何使用 Node、NPM 和 HTTP-Server 来处理它,因此我为您做了一些修改,并将 WASM 二进制内容直接放入 < code>build/44gba.js,并在函数 readBinary 上返回该二进制内容,以便绕过 CORS 问题。您可以直接启动index.html。以下是新 build/44gba.js 文件的链接,只需将其内容替换为以下文件:https://sendeyo.com/en/b02f94b524,你们都很好。以下是更改内容:

    const wasmData = `0061 736d 0100 0000 01c9 011e 6001 7f00
    6002 7f7f 0060 0000 6001 7f01 7f60 037f
    ...  ...  ...  ...  ...  ...  ...  ...
    0a00 41c0 8106 0b04 7064 6202`;
    
    // other codes ...
    
    readBinary = filename=>{
        var ret = new Uint8Array(wasmData);
        return ret;
        /* var ret = read_(filename, true);
        if (!ret.buffer) {
            ret = new Uint8Array(ret)
        }
        return ret
        */
    }
    
    // other codes ...

    回复
    0
  • 取消回复