分區結構
在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 文件中, 將來開機就會自動生效.