<commit_before>"use strict";

require("fullscrn");
const BBox = require("b-box");
const dock_n_liquid = require("dock-n-liquid");
const MZ700 = require("./mz700.js");

const MZBeep = require("../lib/mz-beep.js");
const MZ_Tape = require("../lib/mz-tape.js");
const MZ_TapeHeader = require("../lib/mz-tape-header.js");
const Z80 = require("../Z80/Z80.js");
const Z80_assemble = require("../Z80/assembler.js");

const packageJson = require("../package.json");
const NumberUtil = require("../lib/number-util.js");
const parseAddress = require("../lib/parse-addr.js");
const parseRequest = require("../lib/parse-request");
const requestJsonp = require("../lib/jsonp");
const { getDeviceType } = require("../lib/user-agent-util.js");

require("../lib/jquery-plugin/jquery.mz700-kb.js");
require("../lib/jquery-plugin/jquery.Z80-reg.js");
require("../lib/jquery-plugin/jquery.asmview.js");
require("../lib/jquery-plugin/jquery.asmlist.js");
require("../lib/jquery-plugin/jquery.tabview.js");
require("../lib/jquery-plugin/jquery.Z80-mem.js");
require("../lib/jquery-plugin/jquery.mz700-img-button.js");
require("../lib/jquery-plugin/jquery.mz700-scrn.js");
require("../lib/jquery-plugin/jquery.mz-sound-control.js");
require("../lib/jquery-plugin/jquery.emu-speed-control.js");
require("../lib/jquery-plugin/jquery.mz-data-recorder.js");
require("../lib/jquery-plugin/jquery.toggle-button.js");
require("../lib/jquery-plugin/jquery.tool-window.js");

/**
 * MONITOR ROM を読み込む。
 * @param {string} filename ROM filename
 * @return {Array<number>} Uint8Arrayを配列に変換したもの
 */
async function loadMonitorROM(filename) {
    const monitorRom = await new Promise(resolve => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", `./mz_newmon/ROMS/${filename}`, true);
        xhr.responseType = "arraybuffer";
        xhr.onload = function () {
            const arrayBuffer = xhr.response;
            if (arrayBuffer) {
                const byteArray = Array.from(new Uint8Array(arrayBuffer));
                resolve(byteArray);
            }
        };
        xhr.send(null);
    });
    return monitorRom;
}

/**
 * Load an IMG element.
 * @param {string} src source attribute value.
 * @param {string|null} alt alt attribute value.
 * @param {any} width (Optional) Width attribute value.
 * @param {any} height (Optional) Height attibute value.
 * @returns {Promise<Image>} a promise to be resolved by image element.
 */
function loadImage(src, alt, width, height) {
    return new Promise((resolve, reject) => {
        const image = new Image(width, height);
        image.onload = () => {
            resolve(image);
        };
        image.onerror = () => {
            reject(new Error(`Fail to load an image from ${src}`));
        };
        image.src = src;
        image.setAttribute("alt", alt);
        image.setAttribute("title", alt);
    });
}

async function createUI(mz700js, mz700screen, canvas) {
    // Set module version to the page title
    const pageTitle = [
        packageJson.description,"(",
        packageJson.name,
        "@",packageJson.version,")"
    ].join("");
    $("title").html(pageTitle);
    $("h1 .mz700scrn").html(pageTitle);

    // load monitor rom
    const monitorRom = await loadMonitorROM("NEWMON7.ROM");
    mz700js.setMonitorRom(monitorRom);

    // Stop on break point
    mz700js.subscribe("onBreak", ()=> mz700js.stop());

    // MZ-700 Beep sound
    const mzBeep = new MZBeep(mz700js);
    mz700js.subscribe("startSound", freq => mzBeep.startSound(freq[0]));
    mz700js.subscribe("stopSound", () => mzBeep.stopSound());

    // Control panel
    const mz700container = $("#mz700container");
    const ctrlPanel = $("<div/>").attr("id", "control-panel").css("display", "none");
    mz700container.append(ctrlPanel);

    const resizeScreen = function() {
        dock_n_liquid.select($("#liquid-panel-MZ-700").get(0)).layout();
        const bboxContainer = new BBox(mz700container.get(0));
        const bboxScreen = new BBox(mz700screen.get(0));
        const containerSize = bboxContainer.getSize();
        containerSize._h -= bboxScreen.px("border-top-width");
        containerSize._h -= bboxScreen.px("border-bottom-width");
        const orgSize = new BBox.Size(320,200);
        const innerSize = containerSize.getMaxInscribedSize(orgSize);

        const margin = new BBox.Size((containerSize._w - innerSize._w) / 2, 0);
        if(margin._w < 0) {
            margin._w = 0;
        }
        mz700screen
            .css("margin-left", margin._w + "px")
            .css("margin-top", margin._h + "px")
            .css("width", innerSize._w + "px")
            .css("height", innerSize._h + "px");
        if(ctrlPanel.is(":visible")) {
            const phifBBox = new BBox(ctrlPanel.get(0));
            const phifSize = phifBBox.getSize();
            const phifMargin = new BBox.Size(
                    (containerSize._w - phifSize._w) / 2,
                    innerSize._h - phifSize._h);
            if(phifMargin._w < 0) {
                phifMargin._w = 0;
            }
            if(phifMargin._h < 0) {
                phifMargin._h = 0;
            }
            ctrlPanel.css("margin-left", phifMargin._w + "px")
                .css("margin-top", phifMargin._h + "px");
        }
    };

    /**
     * Show the panel to operate MZ-700.
     * @param {Function} resize resize handler.
     * @returns {undefined}
     */
    const showCtrlPanel = () => {
        if(!ctrlPanel.is(":visible")) {
            ctrlPanel.addClass("hover");
            ctrlPanel.show(0, () => {
                resizeScreen();
            });
        }
    };

    /**
     * Hide the panel to operate MZ-700.
     * @param {Function} resize resize handler.
     * @returns {undefined}
     */
    const hideCtrlPanel = () => {
        if(ctrlPanel.is(":visible")) {
            ctrlPanel.removeClass("hover");
            ctrlPanel.hide(0, ()=> {
                resizeScreen();
            });
        }
    };

    let tidHideCtrlPanel = null;
    const installHideCtrlPanelTimer = () => {
        tidHideCtrlPanel = setTimeout(() => {
            hideCtrlPanel();
            tidHideCtrlPanel = null;
        }, 1000);
    };
    const cancelHideCtrlPanelTimer = () => {
        if(tidHideCtrlPanel) {
            clearTimeout(tidHideCtrlPanel);
            tidHideCtrlPanel = null;
        }
    };

    const deviceType = getDeviceType();
    if(deviceType === "pc") {
        mz700container.mouseenter(() => {
            cancelHideCtrlPanelTimer();
            showCtrlPanel();
            installHideCtrlPanelTimer();
        }).mouseleave(() => {
            cancelHideCtrlPanelTimer();
            hideCtrlPanel();
        });
        ctrlPanel.mouseenter(event => {
            event.stopPropagation();
            cancelHideCtrlPanelTimer();
        }).mouseleave(event =>{
            event.stopPropagation();
            cancelHideCtrlPanelTimer();
            installHideCtrlPanelTimer();
        });
    }

    // Reset Button
    const imgBtnResetOff = await loadImage("./image/btnReset-off.png", "Reset");
    const imgBtnResetOn = await loadImage("./image/btnReset-on.png", "Reset");
    const btnReset = $("<button/>").MZ700ImgButton("create", {
        img: imgBtnResetOff,
    }).click(async () => {
        await mz700js.stop();
        await mz700js.reset();
        await mz700js.start();
        await dataRecorder.MZDataRecorder("updateCmtSlot");
    }).hover(
        () => btnReset.MZ700ImgButton("setImg", imgBtnResetOn),
        () => btnReset.MZ700ImgButton("setImg", imgBtnResetOff)
    );

    // MZ-700 Running status
    let _isRunning = false;

    // Run/Stop/Step Button
    const imgBtnRunOff = await loadImage("image/btnRun-off.png", "[F8] Run");
    const imgBtnRunOn = await loadImage("image/btnRun-on.png", "[F8] Run");
    const imgBtnStopOff = await loadImage("image/btnStop-off.png", "[F8] Stop");
    const imgBtnStopOn = await loadImage("image/btnStop-on.png", "[F8] Stop");
    const btnStart = $("<button/>").MZ700ImgButton("create", {
        img: imgBtnRunOff,
    }).click(() => {
        _isRunning ? mz700js.stop() : mz700js.start();
    }).hover(
        () => btnStart.MZ700ImgButton("setImg",
                _isRunning ? imgBtnStopOn : imgBtnRunOn),
        () => btnStart.MZ700ImgButton("setImg",
                _isRunning ? imgBtnStopOff : imgBtnRunOff),
    );
    const imgBtnStepOff = await loadImage("image/btnStepIn-off.png", "[F9] Step-In");
    const imgBtnStepOn = await loadImage("image/btnStepIn-on.png", "[F9] Step-In");
    const imgBtnStepDi = await loadImage("image/btnStepIn-disabled.png", "[F9] Step-In");
    const btnStep = $("<button/>").MZ700ImgButton("create", {
        img: imgBtnStepOff,
    }).click( () => mz700js.step() ).hover(
        () => {
            if(!_isRunning) {
                btnStep.MZ700ImgButton("setImg", imgBtnStepOn);
            }
        }, () => {
            if(!_isRunning) {
                btnStep.MZ700ImgButton("setImg", imgBtnStepOff);
            }
        }
    );

    // Operate the emulation state by key
    window.addEventListener("keyup", async event => {
        switch(event.keyCode) {
        case 119://F8 - RUN/STOP
            event.stopPropagation();
            _isRunning ? mz700js.stop() : mz700js.start();
            break;
        case 120://F9 - STEP In
            event.stopPropagation();
            _isRunning ? mz700js.stop() : mz700js.step();
            break;
        }
    });

    // Emulation started
    mz700js.subscribe("start", async () => {
        if(!_isRunning && reg_visibility) {
            await Z80RegViewAutoUpdate(true);
        }
        _isRunning = true;
<commit_msg>Replace deprecated property 'keyCode' of keyup event to 'code'<commit_after>"use strict";

require("fullscrn");
const BBox = require("b-box");
const dock_n_liquid = require("dock-n-liquid");
const MZ700 = require("./mz700.js");

const MZBeep = require("../lib/mz-beep.js");
const MZ_Tape = require("../lib/mz-tape.js");
const MZ_TapeHeader = require("../lib/mz-tape-header.js");
const Z80 = require("../Z80/Z80.js");
const Z80_assemble = require("../Z80/assembler.js");

const packageJson = require("../package.json");
const NumberUtil = require("../lib/number-util.js");
const parseAddress = require("../lib/parse-addr.js");
const parseRequest = require("../lib/parse-request");
const requestJsonp = require("../lib/jsonp");
const { getDeviceType } = require("../lib/user-agent-util.js");

require("../lib/jquery-plugin/jquery.mz700-kb.js");
require("../lib/jquery-plugin/jquery.Z80-reg.js");
require("../lib/jquery-plugin/jquery.asmview.js");
require("../lib/jquery-plugin/jquery.asmlist.js");
require("../lib/jquery-plugin/jquery.tabview.js");
require("../lib/jquery-plugin/jquery.Z80-mem.js");
require("../lib/jquery-plugin/jquery.mz700-img-button.js");
require("../lib/jquery-plugin/jquery.mz700-scrn.js");
require("../lib/jquery-plugin/jquery.mz-sound-control.js");
require("../lib/jquery-plugin/jquery.emu-speed-control.js");
require("../lib/jquery-plugin/jquery.mz-data-recorder.js");
require("../lib/jquery-plugin/jquery.toggle-button.js");
require("../lib/jquery-plugin/jquery.tool-window.js");

/**
 * MONITOR ROM を読み込む。
 * @param {string} filename ROM filename
 * @return {Array<number>} Uint8Arrayを配列に変換したもの
 */
async function loadMonitorROM(filename) {
    const monitorRom = await new Promise(resolve => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", `./mz_newmon/ROMS/${filename}`, true);
        xhr.responseType = "arraybuffer";
        xhr.onload = function () {
            const arrayBuffer = xhr.response;
            if (arrayBuffer) {
                const byteArray = Array.from(new Uint8Array(arrayBuffer));
                resolve(byteArray);
            }
        };
        xhr.send(null);
    });
    return monitorRom;
}

/**
 * Load an IMG element.
 * @param {string} src source attribute value.
 * @param {string|null} alt alt attribute value.
 * @param {any} width (Optional) Width attribute value.
 * @param {any} height (Optional) Height attibute value.
 * @returns {Promise<Image>} a promise to be resolved by image element.
 */
function loadImage(src, alt, width, height) {
    return new Promise((resolve, reject) => {
        const image = new Image(width, height);
        image.onload = () => {
            resolve(image);
        };
        image.onerror = () => {
            reject(new Error(`Fail to load an image from ${src}`));
        };
        image.src = src;
        image.setAttribute("alt", alt);
        image.setAttribute("title", alt);
    });
}

async function createUI(mz700js, mz700screen, canvas) {
    // Set module version to the page title
    const pageTitle = [
        packageJson.description,"(",
        packageJson.name,
        "@",packageJson.version,")"
    ].join("");
    $("title").html(pageTitle);
    $("h1 .mz700scrn").html(pageTitle);

    // load monitor rom
    const monitorRom = await loadMonitorROM("NEWMON7.ROM");
    mz700js.setMonitorRom(monitorRom);

    // Stop on break point
    mz700js.subscribe("onBreak", ()=> mz700js.stop());

    // MZ-700 Beep sound
    const mzBeep = new MZBeep(mz700js);
    mz700js.subscribe("startSound", freq => mzBeep.startSound(freq[0]));
    mz700js.subscribe("stopSound", () => mzBeep.stopSound());

    // Control panel
    const mz700container = $("#mz700container");
    const ctrlPanel = $("<div/>").attr("id", "control-panel").css("display", "none");
    mz700container.append(ctrlPanel);

    const resizeScreen = function() {
        dock_n_liquid.select($("#liquid-panel-MZ-700").get(0)).layout();
        const bboxContainer = new BBox(mz700container.get(0));
        const bboxScreen = new BBox(mz700screen.get(0));
        const containerSize = bboxContainer.getSize();
        containerSize._h -= bboxScreen.px("border-top-width");
        containerSize._h -= bboxScreen.px("border-bottom-width");
        const orgSize = new BBox.Size(320,200);
        const innerSize = containerSize.getMaxInscribedSize(orgSize);

        const margin = new BBox.Size((containerSize._w - innerSize._w) / 2, 0);
        if(margin._w < 0) {
            margin._w = 0;
        }
        mz700screen
            .css("margin-left", margin._w + "px")
            .css("margin-top", margin._h + "px")
            .css("width", innerSize._w + "px")
            .css("height", innerSize._h + "px");
        if(ctrlPanel.is(":visible")) {
            const phifBBox = new BBox(ctrlPanel.get(0));
            const phifSize = phifBBox.getSize();
            const phifMargin = new BBox.Size(
                    (containerSize._w - phifSize._w) / 2,
                    innerSize._h - phifSize._h);
            if(phifMargin._w < 0) {
                phifMargin._w = 0;
            }
            if(phifMargin._h < 0) {
                phifMargin._h = 0;
            }
            ctrlPanel.css("margin-left", phifMargin._w + "px")
                .css("margin-top", phifMargin._h + "px");
        }
    };

    /**
     * Show the panel to operate MZ-700.
     * @param {Function} resize resize handler.
     * @returns {undefined}
     */
    const showCtrlPanel = () => {
        if(!ctrlPanel.is(":visible")) {
            ctrlPanel.addClass("hover");
            ctrlPanel.show(0, () => {
                resizeScreen();
            });
        }
    };

    /**
     * Hide the panel to operate MZ-700.
     * @param {Function} resize resize handler.
     * @returns {undefined}
     */
    const hideCtrlPanel = () => {
        if(ctrlPanel.is(":visible")) {
            ctrlPanel.removeClass("hover");
            ctrlPanel.hide(0, ()=> {
                resizeScreen();
            });
        }
    };

    let tidHideCtrlPanel = null;
    const installHideCtrlPanelTimer = () => {
        tidHideCtrlPanel = setTimeout(() => {
            hideCtrlPanel();
            tidHideCtrlPanel = null;
        }, 1000);
    };
    const cancelHideCtrlPanelTimer = () => {
        if(tidHideCtrlPanel) {
            clearTimeout(tidHideCtrlPanel);
            tidHideCtrlPanel = null;
        }
    };

    const deviceType = getDeviceType();
    if(deviceType === "pc") {
        mz700container.mouseenter(() => {
            cancelHideCtrlPanelTimer();
            showCtrlPanel();
            installHideCtrlPanelTimer();
        }).mouseleave(() => {
            cancelHideCtrlPanelTimer();
            hideCtrlPanel();
        });
        ctrlPanel.mouseenter(event => {
            event.stopPropagation();
            cancelHideCtrlPanelTimer();
        }).mouseleave(event =>{
            event.stopPropagation();
            cancelHideCtrlPanelTimer();
            installHideCtrlPanelTimer();
        });
    }

    // Reset Button
    const imgBtnResetOff = await loadImage("./image/btnReset-off.png", "Reset");
    const imgBtnResetOn = await loadImage("./image/btnReset-on.png", "Reset");
    const btnReset = $("<button/>").MZ700ImgButton("create", {
        img: imgBtnResetOff,
    }).click(async () => {
        await mz700js.stop();
        await mz700js.reset();
        await mz700js.start();
        await dataRecorder.MZDataRecorder("updateCmtSlot");
    }).hover(
        () => btnReset.MZ700ImgButton("setImg", imgBtnResetOn),
        () => btnReset.MZ700ImgButton("setImg", imgBtnResetOff)
    );

    // MZ-700 Running status
    let _isRunning = false;

    // Run/Stop/Step Button
    const imgBtnRunOff = await loadImage("image/btnRun-off.png", "[F8] Run");
    const imgBtnRunOn = await loadImage("image/btnRun-on.png", "[F8] Run");
    const imgBtnStopOff = await loadImage("image/btnStop-off.png", "[F8] Stop");
    const imgBtnStopOn = await loadImage("image/btnStop-on.png", "[F8] Stop");
    const btnStart = $("<button/>").MZ700ImgButton("create", {
        img: imgBtnRunOff,
    }).click(() => {
        _isRunning ? mz700js.stop() : mz700js.start();
    }).hover(
        () => btnStart.MZ700ImgButton("setImg",
                _isRunning ? imgBtnStopOn : imgBtnRunOn),
        () => btnStart.MZ700ImgButton("setImg",
                _isRunning ? imgBtnStopOff : imgBtnRunOff),
    );
    const imgBtnStepOff = await loadImage("image/btnStepIn-off.png", "[F9] Step-In");
    const imgBtnStepOn = await loadImage("image/btnStepIn-on.png", "[F9] Step-In");
    const imgBtnStepDi = await loadImage("image/btnStepIn-disabled.png", "[F9] Step-In");
    const btnStep = $("<button/>").MZ700ImgButton("create", {
        img: imgBtnStepOff,
    }).click( () => mz700js.step() ).hover(
        () => {
            if(!_isRunning) {
                btnStep.MZ700ImgButton("setImg", imgBtnStepOn);
            }
        }, () => {
            if(!_isRunning) {
                btnStep.MZ700ImgButton("setImg", imgBtnStepOff);
            }
        }
    );

    // Operate the emulation state by key
    window.addEventListener("keyup", async event => {
        switch(event.code) {
        case 0x0042://F8 - RUN/STOP
            event.stopPropagation();
            _isRunning ? mz700js.stop() : mz700js.start();
            break;
        case 0x0043://F9 - STEP In
            event.stopPropagation();
            _isRunning ? mz700js.stop() : mz700js.step();
            break;
        }
    });

    // Emulation started
    mz700js.subscribe("start", async () => {
        if(!_isRunning && reg_visibility) {
            await Z80RegViewAutoUpdate(true);
        }
        _isRunning = true;

{'fraction_non_alphanumeric': 0.16204559457794207, 'fraction_numerical': 0.020640788662969808, 'mean_word_length': 2.3703062813635576, 'pattern_counts': {'":': 6, '<': 21, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '198620', 'n_tokens_mistral': 6333, 'n_tokens_neox': 6045, 'n_words': 1078}