• EmuELEC笔记


    分区结构

    在img写入后, 会产生两个分区
    EMUELEC: 用于启动的文件, 例如dtb文件等, 以及system.img & system.img.md5, EmuELEC的系统文件都在这个img里面
    STORAGE:

    运行中目录结构

    /dev/mmcblk1p1 511.7M 373.6M 138.2M 73% /flash
    /dev/loop0 357.5M 357.5M 0 100% /
    /dev/mmcblk1p2 28.6G 3.5G 25.1G 12% /storage
    

    启动后, EMUELEC分区被挂载为 /flash, STORAGE分区被挂载为 /storage, system.img 通过 /dev/loop0 被挂载为系统根目录 / 

    所以, 用户能修改的仅仅是 /flash 和 /storage 目录下的内容
    root用户的home目录被定位到 /storage, 如果需要添加登录后自动执行的命令(例如添加alias), 可以直接在 /storage 目录下新建 .profile 文件来实现

    开机启动顺序

    这个是在uboot中进行管理的, 可以通过fw_printenv命令进行查看

    EmuELEC:/usr/sbin # fw_printenv
    ...
    baudrate=115200
    boot_count=0
    bootcmd=if test ${bootfromnand} = 1; then setenv bootfromnand 0; saveenv; else run bootfromsd; run bootfromusb; fi; run storeboot
    bootcount_check=echo bootcounts=${boot_count}; if itest ${boot_count} == 0; then setenv boot_count 1;saveenv;else if itest ${boot_count} == 1; then setenv boot_count 2;saveenv;else if itest ${boot_count} == 2; then setenv boot_count 3;saveenv;else if itest ${boot_count} == 3; then setenv boot_count 4;saveenv;else if itest ${boot_count} == 4; then run recovery_from_flash;fi;fi;fi;fi;fi
    bootdelay=0
    bootfromnand=0
    bootfromsd=mmcinfo; if fatload mmc 0 ${loadaddr} kernel.img; then run sddtb; setenv bootargs ${bootargs} bootfromsd; bootm; fi
    bootfromusb=usb start 0; if fatload usb 0 ${loadaddr} kernel.img; then run usbdtb; setenv bootargs ${bootargs} bootfromusb; bootm; fi
    bootmode_check=get_rebootmode; echo reboot_mode=${reboot_mode};if test ${reboot_mode} = factory_reset; then defenv_reserv;setenv upgrade_step 2; save;fi;
    cmdline_keys=if keyman init 0x1234; then if sec_keyunify read mac ${loadaddr} str; then setenv bootargs ${bootargs} mac=${mac} androidboot.mac=${mac};fi;fi;
    ...
    

    可以看到其中的 bootfromnand 变量是用于控制设备的启动顺序, 如果值为1, 那么从nand(设备内部存储, eMMC等), 如果值为0, 那么依次从sd, 从usb启动, 在这个过程中如果某个介质可以启动了, 就把这个方式加到bootargs变量的值当中去, 例如

    setenv bootargs ${bootargs} bootfromsd;
    

    .然后调用系统函数bootm启动内核. bootm会调用 ./lib_arm/armlinux.c的do_bootm() 方法, 里面会调用./common/cmd_bootm.c的do_bootm_linux()

    如果这些都不成功, 那就调用storeboot 

    storeboot=if imgread kernel boot ${loadaddr}; then bootm ${loadaddr}; fi;run update;
    

    而update会依次尝试从各个媒介升级

    update=run usb_burning; run sdc_burning; if mmcinfo; then run recovery_from_sdcard;fi;if usb start 0; then run recovery_from_udisk;fi;run recovery_from_flash;
    

    中间还会记录启动次数, 如果启动次数达到4, 就会执行 recovery_from_flash

    recovery_from_flash=setenv bootargs ${bootargs} aml_dt=${aml_dt} recovery_part={recovery_part} recovery_offset={recovery_offset};if imgread kernel ${recovery_part} ${loadaddr} ${recovery_offset}; then wipeisb; bootm ${loadaddr}; fi
    

    ES的Quit菜单中的Reboot From NAND, 实际执行的就是 /usr/sbin/rebootfromnand 这个命令, 里面将 bootfromnand 值设为了1

    EmuELEC:/usr/sbin # more rebootfromnand 
    #!/bin/sh
    
    # SPDX-License-Identifier: GPL-2.0-or-later
    # Copyright (C) 2016-2018 kszaq (kszaquitto@gmail.com)
    # Copyright (C) 2018-present Team CoreELEC (https://coreelec.org)
    
    if /usr/sbin/fw_printenv whereToBootFrom > /dev/null 2>&1; then /usr/sbin/fw_setenv whereToBootFrom internal; fi
    /usr/sbin/fw_setenv bootfromnand 1
    

      

    服务启动顺序

    系统启动的服务是通过systemd管理的, 启动脚本位于 /usr/lib/systemd/system/ 下, 因为是过loop设备挂载的, 所以这里面的文件都不可修改. 默认的启动target为

    EmuELEC:/usr/lib/systemd/system # systemctl get-default
    emuelec.target
    EmuELEC:/usr/lib/systemd/system # ll def*.*
    lrwxrwxrwx    1 root     root            14 Nov 19 00:42 default.target -> emuelec.target
    

    服务依赖关系为

    EmuELEC:/usr/lib/systemd/system # systemctl list-dependencies emuelec.target
    emuelec.target
    ● ├─emuelec-autostart.service
    ● ├─emustation.service
    ● ├─retroarch.service
    ● ├─tmp-assets.mount
    ● ├─tmp-cores.mount
    ● ├─tmp-database.mount
    ● ├─tmp-joypads.mount
    ● ├─tmp-overlays.mount
    ● ├─tmp-shaders.mount
    ● ├─graphical.target
    ● │ ├─unbind-console.service
    ● │ └─multi-user.target
    ● │   ├─avahi-daemon.service
    ● │   ├─connman.service
    ● │   ├─dbus.service
    ● │   ├─entware.service
    ● │   ├─iptables.service
    ● │   ├─nmbd.service
    ● │   ├─pulseaudio.service
    ● │   ├─rpcbind.service
    ● │   ├─sixaxis@multi-user.service
    ● │   ├─smbd.service
    ● │   ├─sshd.service
    ● │   ├─systemd-ask-password-wall.path
    ● │   ├─systemd-logind.service
    ● │   └─basic.target
    ● │     ├─add-entropy.service
    ● │     ├─amlogic-dvb.service
    ● │     ├─fstrim.service
    ● │     ├─hwdb.service
    ● │     ├─kvimfan.service
    ● │     ├─openvfd.service
    ● │     ├─show-version.service
    ● │     ├─swap.service
    ● │     ├─tmp.mount
    ● │     ├─var.mount
    ● │     ├─wetekdvb.service
    ● │     ├─paths.target
    ● │     ├─slices.target
    ● │     │ ├─-.slice
    ● │     │ └─system.slice
    ● │     ├─sockets.target
    ● │     │ ├─dbus.socket
    ● │     │ ├─systemd-initctl.socket
    ● │     │ ├─systemd-journald-audit.socket
    ● │     │ ├─systemd-journald-dev-log.socket
    ● │     │ ├─systemd-journald.socket
    ● │     │ ├─systemd-udevd-control.socket
    ● │     │ └─systemd-udevd-kernel.socket
    ● │     ├─sysinit.target
    ● │     │ ├─debug-shell.service
    ● │     │ ├─debugconfig.service
    ● │     │ ├─dev-hugepages.mount
    ● │     │ ├─dev-mqueue.mount
    ● │     │ ├─kmod-static-nodes.service
    ● │     │ ├─machine-id.service
    ● │     │ ├─openssl-config.service
    ● │     │ ├─sys-fs-fuse-connections.mount
    ● │     │ ├─sys-kernel-config.mount
    ● │     │ ├─sys-kernel-debug.mount
    ● │     │ ├─systemd-ask-password-console.path
    ● │     │ ├─systemd-hwdb-update.service
    ● │     │ ├─systemd-journal-catalog-update.service
    ● │     │ ├─systemd-journal-flush.service
    ● │     │ ├─systemd-journald.service
    ● │     │ ├─systemd-modules-load.service
    ● │     │ ├─systemd-sysctl.service
    ● │     │ ├─systemd-tmpfiles-setup-dev.service
    ● │     │ ├─systemd-tmpfiles-setup.service
    ● │     │ ├─systemd-udev-trigger.service
    ● │     │ ├─systemd-udevd.service
    ● │     │ ├─tz-data.service
    ● │     │ ├─usercache.service
    ● │     │ ├─userconfig.service
    ● │     │ ├─local-fs.target
    ● │     │ │ ├─kernel-overlays.service
    ● │     │ │ ├─libmali.service
    ● │     │ │ ├─tmp.mount
    ● │     │ │ └─var.mount
    ● │     │ └─swap.target
    ● │     └─timers.target
    ● │       └─systemd-tmpfiles-clean.timer
    ● └─multi-user.target
    ●   ├─avahi-daemon.service
    ●   ├─connman.service
    ●   ├─dbus.service
    ●   ├─entware.service
    ●   ├─iptables.service
    ●   ├─nmbd.service
    ●   ├─pulseaudio.service
    ●   ├─rpcbind.service
    ●   ├─sixaxis@multi-user.service
    ●   ├─smbd.service
    ●   ├─sshd.service
    ●   ├─systemd-ask-password-wall.path
    ●   ├─systemd-logind.service
    ●   └─basic.target
    

    在 emuelec-autostart.service 里, 执行了/storage/.config/autostart.sh

    在autostart.sh的结尾, 又执行了 /storage/.config/custom_start.sh

    最后一步, 通过 emustation.service, 把/usr/bin/emulationstation启动起来

    通过ScreenScraper自动下载游戏说明和截图

    首先到 https://www.screenscraper.fr/ 注册一个帐号, 需要邮箱验证

    在EmuELEC界面上, 通过 SCRAPE 菜单, 填充帐号和口令, 依次选择
    Scrape From: SCREENSCRAPER
    Image Source: SCREENSHOT(游戏运行画面), TITLE SCREENSHOT(游戏开始画面), MIX (游戏运行截图+游戏盒子合并在一起的一张图)
    Box Source: NONE (游戏包装, 2d或3d, 因为色深为24bit, 文件size会比较大, 都是200~400K大小, 如果用列表展示, 就不需要下载这个)
    Logo Source: WHEEL
    Scrape Ratings: YES
    Scrape Videos: NO
    然后点击Scrape Now, 选择要下载的集合, 选择处理冲突的方式, 建议自动.

    系统就会在后台自动下载, 因为来源在国外所以速度会比较慢.

    修改时区

    系统默认时区为墨西哥, 界面上没有修改时区的地方, 需要命令行登录后修改 /emuelec/configs/emuelec.conf , 里面有timezone配置. 改为

    system.timezone=Asia/Shanghai
    

    连发键的设置Autofire, Turbo Button, Duty Cycle

    这个其实是RetroArch的配置, 和以往的连发键设置不太一样, RetroArch用的是开关触发的机制, 有三处相关的设置
    Settings->Input->Turbo Period, 连发键开启时, 在连发当中每次按下的时间长度(多少帧)
    Settings->Input->Duty Cycle, 连发键开启时, 在连发当中按下的时间占空比
    Settings->Input->User/Port[1,2,3,4] Binds->User/Port[1,2,3,4] Turbo, 开启连发的键

    使用方法是, 按住需要连发的按键后, 按一下开启连发的键, 这个按住的键就开启连发了. 这个开启连发的效果只在按住时有效, 松开按键后连发的效果就消失, 需要再来一遍.

    输入设备按键测试

    查看所有输入设备, 列出各设备对应的event编号

    cat /proc/bus/input/devices
    

     输入设备测试

    # 手柄测试, 需要对应上面命令输出的js编号
    jstest --event /dev/input/js0 
    # 通用的输入事件测试, 需要对应上面命令产生的event编号
    evtest /dev/input/event3
    

     对于乐视尚酷版手柄, 无法设置select键的问题: 这个手柄在输入设备里会产生两个设备, 分别是

    I: Bus=0003 Vendor=0101 Product=1d79 Version=0110
    N: Name="MY-POWER LeWGP-201"
    P: Phys=usb-xhci-hcd.0.auto-1.4/input0
    S: Sysfs=/devices/c9000000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.4/1-1.4:1.0/0003:0101:1D79.0003/input/input4
    U: Uniq=
    H: Handlers=js0 event4 
    B: PROP=0
    B: EV=1b
    B: KEY=7fff0000 0 0 0 0 0 0 0 0 0
    B: ABS=3063f
    B: MSC=10
    
    I: Bus=0003 Vendor=0101 Product=1d79 Version=0110
    N: Name="MY-POWER LeWGP-201"
    P: Phys=usb-xhci-hcd.0.auto-1.4/input1
    S: Sysfs=/devices/c9000000.dwc3/xhci-hcd.0.auto/usb1/1-1/1-1.4/1-1.4:1.1/0003:0101:1D79.0004/input/input5
    U: Uniq=
    H: Handlers=kbd event5 
    B: PROP=0
    B: EV=1f
    B: KEY=3007f 0 0 0 0 483ffff 17aff32d bf544446 0 0 1 120c13 b17c000 267bfa d941dfed 9e1680 4400 0 10000002
    B: REL=40
    B: ABS=1 0
    B: MSC=10
    

     其中js0:event4设备可以响应除了back键和底下一排三个键以外其他所有按键, 而kbd:event5设备则正好相反. 可以通过evremap将event5的按键映射到event4

    # Enable 'BACK' key on LeWGP-201 gamepad
    evremap /dev/input/by-id/usb-MY-POWER_LeWGP-201-event-if01 /dev/input/by-id/usb-MY-POWER_LeWGP-201-event-joystick 
    

    将其添加到 /storage/.config/custom_start.sh 文件中, 将来开机就会自动生效.

  • 相关阅读:
    CCF-CSP认证 C++题解目录
    LeetCode周赛#205
    LeetCode双周赛#34
    Codeforces Round #667 (Div. 3) B、C、D、E 题解
    Codeforces Round #656 (Div. 3) 题解
    牛客小白月赛#26 题解
    LeetCode周赛#204 题解
    LeetCode周赛#203 题解
    牛客小白月赛#27 题解
    N阶上楼梯问题——动态规划(递推求解)
  • 原文地址:https://www.cnblogs.com/milton/p/11971119.html
Copyright © 2020-2023  润新知