1 Commits

Author SHA1 Message Date
Douglas Teles 2d0a76b94a ArchR v2.0-rc3 — first official release-candidate
Kernel 6.12 LTS · Mesa 26.0.5 Panfrost · CMA 96 MB · zlib-ng 2.2.4
CPU turbo 1.5 GHz (vdd_arm 1.45 V) · GPU 650 MHz @ 1.150 V · mali_kbase PM patch
43 motherboard revisions covered · two image variants with hardware auto-detect
PortMaster pre-installed · MESA_GLTHREAD whitelist · RetroAchievements
Tailscale / WireGuard / ZeroTier · Syncthing + rclone · Samba

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 14:36:32 -03:00
51 changed files with 141 additions and 1539 deletions
+1 -1
View File
@@ -172,4 +172,4 @@ packages/sysutils/open-vm-tools/
#other
docs/*
bench-results/config/mipi-generator/__pycache__/
bench-results/
-7
View File
@@ -1,12 +1,5 @@
-include $(HOME)/.archr/options
# Normalise OFFICIAL once, before any recipe runs. `override` makes
# this assignment win against MAKEFLAGS cmdline propagation, so
# recursive make invocations (build_distro -> make image) see the
# canonical "yes" value instead of the raw "y" / "Y" / "1" the user
# passed on the outer command line. `export` then forwards it to
# every shell, including scripts/image which tests `= "yes"` exact.
override OFFICIAL := $(if $(filter y yes Y YES 1,$(OFFICIAL)),yes,)
export OFFICIAL
all: world
+1 -128
View File
@@ -188,38 +188,7 @@
};
};
/*
* Sound card layout for the R36S family.
*
* The default `rk817-sound` (overridden right below) keeps the
* Speaker Amp routing that the R36S original and most clones need.
* That node stays enabled by default so any board the overlay
* generator cannot positively re-classify still gets functional
* audio (the historic behaviour up to v2.0-rc3).
*
* Three additional variant cards are pre-defined with
* status = "disabled" so the overlay can switch to them when the
* vendor DTB does not match the default assumption:
*
* rk817-sound-amplified : external speaker amp gated by a GPIO
* (explicit re-affirmation of the default
* for boards where the overlay needs to
* rewrite the amp enable line).
* rk817-sound-simple : external amp on a regulator, no GPIO
* gate (a handful of clone batches).
* rk817-sound-spko-direct: speaker driven directly from rk817 SPKO
* with no external amp at all (Soysauce
* V05 and any board where the amp circuit
* was depopulated). Without this variant
* V05 boots with speaker muted, because
* mainline ASoC will not route to SPKO
* through a card that declares the Speaker
* widget behind an Amp.
*
* When the overlay enables one of these variants it also writes
* status = "disabled" on the default `rk817-sound`, so the kernel
* always sees exactly one active simple-audio-card.
*/
/* Override sound card from r3xs.dtsi: add speaker amplifier */
/ {
rk817-sound {
simple-audio-card,aux-devs = <&spk_amp>;
@@ -229,102 +198,6 @@
"Headphones", "HPOR",
"Speaker Amp INL", "SPKO";
};
rk817-sound-amplified {
compatible = "simple-audio-card";
pinctrl-names = "default";
pinctrl-0 = <&hp_det>;
simple-audio-card,name = "rk817_ext";
simple-audio-card,aux-devs = <&spk_amp>;
simple-audio-card,format = "i2s";
simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Headphone", "Headphones",
"Speaker", "Internal Speakers";
/* The Y3506 / R36S clone speaker is mono, but the amp is
* stereo. We route both amp inputs to HPOL/HPOR so the
* second channel doesn't latch the amp on permanently. */
simple-audio-card,routing =
"Headphones", "HPOL",
"Headphones", "HPOR",
"Internal Speakers", "Speaker Amp OUTL",
"Internal Speakers", "Speaker Amp OUTR",
"Speaker Amp INL", "HPOL",
"Speaker Amp INR", "HPOR";
simple-audio-card,pin-switches = "Internal Speakers";
status = "disabled";
simple-audio-card,codec {
sound-dai = <&rk817>;
};
simple-audio-card,cpu {
sound-dai = <&i2s1_2ch>;
};
};
rk817-sound-simple {
compatible = "simple-audio-card";
pinctrl-names = "default";
pinctrl-0 = <&hp_det>;
simple-audio-card,name = "rk817_ext";
simple-audio-card,format = "i2s";
simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Headphone", "Headphones",
"Speaker", "Internal Speakers";
simple-audio-card,routing =
"Headphones", "HPOL",
"Headphones", "HPOR",
"Internal Speakers", "SPKO";
status = "disabled";
simple-audio-card,codec {
sound-dai = <&rk817>;
};
simple-audio-card,cpu {
sound-dai = <&i2s1_2ch>;
};
};
rk817-sound-spko-direct {
compatible = "simple-audio-card";
pinctrl-names = "default";
pinctrl-0 = <&hp_det>;
simple-audio-card,name = "rk817_ext";
simple-audio-card,format = "i2s";
simple-audio-card,hp-det-gpio = <&gpio2 RK_PC6 GPIO_ACTIVE_HIGH>;
simple-audio-card,mclk-fs = <256>;
simple-audio-card,widgets =
"Microphone", "Mic Jack",
"Headphone", "Headphones",
"Speaker", "Internal Speaker";
simple-audio-card,routing =
"MICL", "Mic Jack",
"Headphones", "HPOL",
"Headphones", "HPOR",
"Internal Speaker", "SPKO";
/* Userspace can mute the speaker when headphones are
* plugged via this pin-switch. */
simple-audio-card,pin-switches = "Internal Speaker";
status = "disabled";
simple-audio-card,codec {
sound-dai = <&rk817>;
};
simple-audio-card,cpu {
sound-dai = <&i2s1_2ch>;
};
};
};
&pinctrl {
-9
View File
@@ -1,9 +0,0 @@
SYSTEM_NAME="gp32"
SYSTEM_FULLNAME="GP32"
SYSTEM_MANUFACTURER="GamePark"
SYSTEM_HARDWARE="portable"
SYSTEM_PATH="/storage/roms/gp32"
SYSTEM_EXTENSION=".smc .zip .7z"
SYSTEM_PLATFORM="gp32"
SYSTEM_THEME="gp32"
SYSTEM_WIKI_PATH="gp32"
+1 -1
View File
@@ -4,7 +4,7 @@ SYSTEM_MANUFACTURER="&#xf013; System"
SYSTEM_RELEASE="System"
SYSTEM_HARDWARE="System"
SYSTEM_PATH="/storage/roms/mplayer"
SYSTEM_EXTENSION=".3g2 .3gp .aac .ac3 .asf .avi .divx .dts .eac33 .f4f .f4v .flac .flv .m2p .m2ts .m3u .m4a .m4v .mka .mkv .mov .mp3 .mp4 .mpeg .mpg .mxf .ogg .ogm .opus .ps .sh .thd .ts .twi .vob .wav .webm .wma .wmv .wv .ytb"
SYSTEM_EXTENSION=".3g2 .3gp .aac .ac3 .asf .avi .divx .dts .eac33 .f4f .f4v .flac .flv .m2p .m2ts .m3u .m4a .mka .mkv .mov .mp3 .mp4 .mpeg .mpg .mxf .ogg .ogm .opus .ps .sh .thd .ts .twi .vob .wav .webm .wma .wmv .wv .ytb"
SYSTEM_PLATFORM="mplayer"
SYSTEM_THEME="mplayer"
SYSTEM_WIKI_PATH="mplayer"
+1 -1
View File
@@ -4,7 +4,7 @@ SYSTEM_MANUFACTURER="&#xf013; System"
SYSTEM_RELEASE="System"
SYSTEM_HARDWARE="computer"
SYSTEM_PATH="/storage/roms/ports"
SYSTEM_EXTENSION=".sh .appimage"
SYSTEM_EXTENSION=".sh"
SYSTEM_PLATFORM="pc"
SYSTEM_THEME="ports"
SYSTEM_WIKI_PATH="ports"
+30 -413
View File
@@ -308,249 +308,6 @@ def switch_joypad_to_mymini(overlay, jp_ovl):
jp_ovl.set_property('poll-interval', 10)
def copy_gpio_prop(dt, symbols, overlay, src_node, prop_name, ovl_target_path):
"""Propagate a *-gpios property from `src_node` (vendor DTB) into the
overlay at `ovl_target_path`, attaching the correct __fixup__ so the
bootloader resolves the phandle against the live base DTB.
Returns True on success, False if the property is absent or the
referenced controller cannot be resolved. Logs nothing — caller can
decide whether to warn.
"""
if not src_node.exist_property(prop_name):
return False
try:
data = src_node.get_property(prop_name).data
except Exception:
return False
if not data or len(data) < 3:
return False
try:
gpio_path = resolve_phandle(dt, data[0])
gpio_sym = next(p.name for p in symbols.props if p.value == gpio_path)
except (StopIteration, Exception):
return False
overlay.set_property(prop_name, [0xffffffff, data[1], data[2]],
path=ovl_target_path)
add_fixup(overlay, gpio_sym, ovl_target_path + ':' + prop_name + ':0')
return True
def extract_joypad_wiring(dt, overlay, jp_ovl, args, symbols):
"""Propagate vendor-specific joypad wiring to the overlay:
* amux-a-gpios, amux-b-gpios, amux-en-gpios (root joypad node)
* gpios on each swN child (per-button)
* button-adc-{deadzone,fuzz,flat} when vendor differs from defaults
These vary per board family: clone uses pins 16/15/11, original
uses 11/8/13, soysauce uses 13/12/17. The button GPIOs vary even
more (different banks). Without this propagation the merged DTB
keeps our base's "original" wiring and clone/soysauce hardware
boots with all buttons mapped to wrong pins.
"""
try:
jp = dt.get_node('/odroidgo3-joypad')
except Exception:
return
ovl_root = jp_ovl.path + '/__overlay__'
# amux selectors
for prop in ('amux-a-gpios', 'amux-b-gpios', 'amux-en-gpios'):
if copy_gpio_prop(dt, symbols, overlay, jp, prop, ovl_root):
data = jp.get_property(prop).data
args['logger'].info(f"{prop} pin={data[1]} flags={data[2]} on {ovl_root}")
# per-button gpios (sw1..sw22 etc.)
button_count = 0
for sw_node in jp.nodes:
name = sw_node.name
if not name.startswith('sw'):
continue
target = ovl_root + '/' + name
if copy_gpio_prop(dt, symbols, overlay, sw_node, 'gpios', target):
button_count += 1
if button_count:
args['logger'].info(f"propagated {button_count} per-button gpios on {ovl_root}")
# button-adc tunings — only emit override if vendor differs from
# the default our base ships. Saves overlay size for the common case.
BUTTON_ADC_DEFAULTS = {
'button-adc-deadzone': 96,
'button-adc-fuzz': 48,
'button-adc-flat': 48,
}
for prop, default in BUTTON_ADC_DEFAULTS.items():
if not jp.exist_property(prop):
continue
val = jp.get_property(prop).value
if val != default:
overlay.set_property(prop, val, path=ovl_root)
args['logger'].info(f"{prop}={val} (vendor differs from default {default})")
# rumble-gpio: some clone boards (R36S V20 2025-05-18 batch, GR36)
# expose a dedicated GPIO that gates the rumble motor — without
# propagating it the motor sits in its default state, which on
# those boards is "on" (= constant vibration). The audit across
# 44 vendor DTBs flagged this in Tier 3; we handle it explicitly
# here so the overlay carries the right pin and the bootloader
# phandle fixup resolves against our GPIO controller.
if copy_gpio_prop(dt, symbols, overlay, jp, 'rumble-gpio', ovl_root):
data = jp.get_property('rumble-gpio').data
args['logger'].info(f"rumble-gpio pin={data[1]} flags={data[2]} on {ovl_root}")
# ---------- Tier 3: auto-discovery of custom vendor properties --------------
#
# Some vendor BSPs ship board-specific properties we never planned for
# (rumble-direction-fix, special-button-quirk, custom-trigger-mode, ...).
# The "extract every known prop" approach leaves those on the cutting
# room floor. Tier 3 walks the vendor tree, identifies anything we don't
# already handle, and propagates it to the overlay — with logging so
# the user knows exactly which non-standard props came along.
# Props we ALREADY handle via dedicated extraction logic above; don't
# touch them in the auto-discovery pass.
_KNOWN_PANEL_PROPS = frozenset({
'compatible', 'reg', 'phandle', 'linux,phandle', 'status',
'panel_description', 'panel-init-sequence', 'panel-exit-sequence',
'display-timings', 'rotation',
'dsi,format', 'dsi,lanes', 'dsi,flags', 'dsi,burst-mode', 'dsi,sync-mode',
'prepare-delay-ms', 'reset-delay-ms', 'init-delay-ms',
'enable-delay-ms', 'disable-delay-ms', 'unprepare-delay-ms',
'width-mm', 'height-mm', 'bus-format', 'bpc',
'reset-gpios', 'enable-gpios',
'led-red-gpios', 'led-green-gpios',
'led-blue1-gpios', 'led-blue2-gpios',
'iovcc-supply', 'vdd-supply', 'vsp-supply', 'vsn-supply',
'vcc-supply', 'power-supply', 'backlight', 'backlight-supply',
})
_KNOWN_JOYPAD_PROPS = frozenset({
'compatible', 'reg', 'phandle', 'linux,phandle', 'status',
'pinctrl-names', 'pinctrl-0', 'pinctrl-1',
'io-channel-names', 'io-channels',
'amux-count', 'amux-channel-mapping',
'amux-a-gpios', 'amux-b-gpios', 'amux-en-gpios',
'button-adc-deadzone', 'button-adc-fuzz', 'button-adc-flat',
'button-adc-scale', 'button-adc-tuned-scale',
'abs_x-p-tuning', 'abs_x-n-tuning', 'abs_y-p-tuning', 'abs_y-n-tuning',
'abs_rx-p-tuning', 'abs_rx-n-tuning', 'abs_ry-p-tuning', 'abs_ry-n-tuning',
'abs-x-p-tuned-val', 'abs-x-n-tuned-val',
'abs-y-p-tuned-val', 'abs-y-n-tuned-val',
'abs-rx-p-tuned-val', 'abs-rx-n-tuned-val',
'abs-ry-p-tuned-val', 'abs-ry-n-tuned-val',
'abs-left-first', 'poll-interval',
'invert-absx', 'invert-absy', 'invert-absrx', 'invert-absry',
'swap-absxy', 'swap-absrxy', 'vendor-direction',
'rumble-boost-weak', 'rumble-boost-strong',
'rumble-gpio',
'pwms', 'pwm-names',
'key-gpios',
})
_KNOWN_SW_PROPS = frozenset({
'gpios', 'phandle', 'linux,phandle',
'amux-channel',
})
# Props that must NEVER be propagated from vendor, even if discovered.
# Either userspace expects our specific value (joypad-name, linux,code)
# or our base intentionally diverges (regulator ranges for OC).
_BLACKLIST = frozenset({
'joypad-name', 'joypad-product', 'joypad-revision',
'linux,code', 'label',
'regulator-min-microvolt', 'regulator-max-microvolt',
'regulator-ramp-delay', 'regulator-initial-mode',
'regulator-always-on', 'regulator-boot-on',
})
def _prop_is_phandle_array(prop):
"""Heuristic: PropWords with values that look like phandles (small
positive integers, multiple entries). Without knowing the exact
layout (#xxx-cells) we can't remap; skip these and let the user
add manual support if needed."""
if not isinstance(prop, fdt.PropWords):
return False
# Common phandle arrays have 2-4 cells per entry; single-cell
# numerics (delays, sizes) are safe to copy.
if len(prop.data) <= 1:
return False
# If every value is small (< 0x1000), it's likely a numeric tuning
# array; if any is "large" (>= 0x10), it's likely a phandle. Soft
# rule but works for the props we've seen in the wild.
return any(v >= 0x10 for v in prop.data)
def _set_prop_on_overlay(overlay, prop, ovl_target_path):
"""Copy a Property to the overlay tree at the given path. Handles
the three concrete subclasses of fdt.Property we care about."""
if isinstance(prop, fdt.PropStrings):
overlay.set_property(prop.name, prop.data, path=ovl_target_path)
elif isinstance(prop, fdt.PropWords):
overlay.set_property(prop.name, prop.data, path=ovl_target_path)
elif isinstance(prop, fdt.PropBytes):
overlay.set_property(prop.name, bytes(prop.data), path=ovl_target_path)
elif hasattr(prop, 'value') and prop.value is None:
# Boolean-style empty property
overlay.set_property(prop.name, True, path=ovl_target_path)
else:
# Unknown type — skip rather than crash
return False
return True
def auto_discover_custom(dt, overlay, panel_ovl, jp_ovl, args):
"""Walk panel + joypad + sw* subnodes in the vendor DTB. Any prop
not in our known/handled set and not blacklisted gets propagated
to the overlay. Phandle arrays are skipped (would need remap that
we don't have layout info for). Logs each discovery."""
discoveries = []
def _visit(node, known_set, ovl_target_path, scope_label):
for p in node.props:
if p.name in known_set or p.name in _BLACKLIST:
continue
if _prop_is_phandle_array(p):
args['logger'].info(
f"auto-discovery: skip {scope_label}/{p.name} "
f"(phandle array, layout unknown)")
continue
if _set_prop_on_overlay(overlay, p, ovl_target_path):
val = p.value if hasattr(p, 'value') else '<binary>'
discoveries.append((scope_label, p.name, val))
# Panel
try:
panel = dt.get_node('/dsi@ff450000/panel@0')
panel_ovl_path = panel_ovl.path + '/__overlay__/dsi@ff450000/panel@0'
_visit(panel, _KNOWN_PANEL_PROPS, panel_ovl_path, 'panel')
except Exception:
pass
# Joypad root
try:
jp = dt.get_node('/odroidgo3-joypad')
jp_ovl_path = jp_ovl.path + '/__overlay__'
_visit(jp, _KNOWN_JOYPAD_PROPS, jp_ovl_path, 'joypad')
# And each sw* subnode
for sw in jp.nodes:
if not sw.name.startswith('sw'):
continue
_visit(sw, _KNOWN_SW_PROPS, jp_ovl_path + '/' + sw.name,
f'joypad/{sw.name}')
except Exception:
pass
if discoveries:
args['logger'].info(
f"auto-discovery: propagated {len(discoveries)} custom vendor props")
for scope, name, val in discoveries:
args['logger'].info(f" custom: {scope}/{name} = {val!r}")
return discoveries
def make_dtbo(dtb_data, args):
dt = fdt.parse_dtb(dtb_data)
symbols = dt.get_node('__symbols__')
@@ -585,31 +342,9 @@ def make_dtbo(dtb_data, args):
compat = dt.get_node('/').get_property('compatible').data[0]
args['logger'].info(f"compatible {compat}")
# Original-only short-circuit: the original kernel DTB (rk3326-odroid-go2)
# already has the correct reset-gpios, power-supply and backlight wiring,
# so the DTBO only needs panel description/timings/init-sequence.
#
# Gate by subdevice (passed as 'SDORIG' from generator.sh), NOT by vendor
# compatible alone: several clone vendor DTBs (e.g. G80CA V1.2 04-22/04-23
# Panel 8 and 9, G80C V1.1 Panel 9) ship with
# `compatible = "rockchip,rk3326-odroidgo3-linux"` despite being clone
# hardware. Trusting that string skipped the GPIO overrides on clones and
# produced the "backlight on, no image" black screen on those boards.
if 'SDORIG' in args['flags'] and 'odroidgo3' in compat:
# Short-circuit path: kernel base DTB already has the correct
# GPIO/panel wiring, no overlay edits needed beyond what we
# already produced. BUT: if the user passed NAm (no external
# amplifier), we still have to switch the active sound card
# from `rk817-sound` (amp routing) to `rk817-sound-spko-direct`,
# otherwise mainline ASoC keeps the speaker muted (Y3506
# Soysauce V03/V04/V05 fall here).
if 'NAm' in args['flags']:
hpdet_ovl = add_overlay(overlay, '/')
spko_path = hpdet_ovl.path + '/__overlay__/rk817-sound-spko-direct'
default_path = hpdet_ovl.path + '/__overlay__/rk817-sound'
overlay.set_property('status', 'okay', path=spko_path)
overlay.set_property('status', 'disabled', path=default_path)
args['logger'].info("audio: spko-direct variant via short-circuit (odroidgo3 + NAm)")
if 'odroidgo3' in compat:
# R36S base DTS already has reset-gpios, power-supply, backlight
# Only the panel description/timings/init-sequence are needed in overlay
return overlay.to_dtb()
# copy reset config
@@ -643,19 +378,6 @@ def make_dtbo(dtb_data, args):
except:
pass
# Soysauce Y3506 V04+/V05 boards have status LEDs on the panel
# itself (red + blue1/blue2/green) used for battery/charging
# indication. Tier 3 audit flagged these in 8 vendor DTBs. Without
# propagation the LED GPIOs default to the bootloader state — on
# most boards they end up "on", giving the user a permanent red
# light that doesn't react to charging state. Each is a standard
# <phandle pin flags> triple, same layout as reset-gpios.
for led_prop in ('led-red-gpios', 'led-green-gpios',
'led-blue1-gpios', 'led-blue2-gpios'):
if copy_gpio_prop(dt, symbols, overlay, panel, led_prop, panel_ovl_path):
data = panel.get_property(led_prop).data
args['logger'].info(f"panel {led_prop} pin={data[1]} flags={data[2]}")
# If the vendor DTB explicitly disables /adc-keys, mirror that decision
# in the overlay. We deliberately do NOT treat "/adc-keys absent" as
@@ -707,48 +429,19 @@ def make_dtbo(dtb_data, args):
jp_ovl.set_property('invert-absry', 1)
args['logger'].info(f"invert right stick on {jp_ovl.path}")
# Propagate the vendor's joypad hardware wiring (amux pins, per-button
# GPIOs, ADC tunings). Without this, clone and soysauce boards inherit
# the "original" base layout and end up with controls all over the
# place — see audit_all.py for the pin matrix across the 44 vendor
# DTBs we ship.
extract_joypad_wiring(dt, overlay, jp_ovl, args, symbols)
try:
snd = dt.get_node('/rk817-sound')
# Vendor BSP DTBs use one of two names for the headphone
# detection GPIO. Legacy Rockchip BSP 4.4 boards write
# `hp-det-gpio`. Newer batches (including most Soysauce
# variants generated from mainline-style DT) use the
# canonical `simple-audio-card,hp-det-gpio`. Without
# accepting both we silently skipped the audio block on V05.
hpdet_prop = snd.get_property('hp-det-gpio')
if hpdet_prop is None:
hpdet_prop = snd.get_property('simple-audio-card,hp-det-gpio')
if hpdet_prop is None:
raise RuntimeError("no hp-det-gpio property on /rk817-sound")
hpdet = list(hpdet_prop.data)
# Some vendor DTBs omit /pinctrl/headphone/hp-det entirely
# because the kernel auto-binds via the codec phandle. We
# tolerate that: if the pinctrl node is missing we skip the
# bias-pull fixup; the codec still picks up the headphone
# detection gpio from simple-audio-card,hp-det-gpio.
try:
hp_det = dt.get_node('/pinctrl/headphone/hp-det')
hp_det_pins = list(hp_det.get_property('rockchip,pins').data)
hp_det_pull_node = node_by_phandle(dt, hp_det_pins[3])
except Exception:
hp_det = None
hp_det_pins = None
hp_det_pull_node = None
# fetch raw hp-det-gpio = <0x6f 0x16 0x00>;
hpdet = snd.get_property('hp-det-gpio').data
hp_det = dt.get_node('/pinctrl/headphone/hp-det')
hp_det_pins = hp_det.get_property('rockchip,pins')
hp_det_pull_node = node_by_phandle(dt, hp_det_pins[3])
# resolve <0x6f> into '/pinctrl/gpio2@ff260000'
hpdet_gpio_path = resolve_phandle(dt, hpdet[0])
# find symbol 'gpio2' for path '/pinctrl/gpio2@ff260000'
gpiosyms = [p.name for p in symbols.props if p.value == hpdet_gpio_path]
if not gpiosyms:
raise RuntimeError(f"hp-det gpio controller phandle {hpdet[0]} not in __symbols__")
gpio_sym = gpiosyms[0]
# on success, add overlay
@@ -771,42 +464,12 @@ def make_dtbo(dtb_data, args):
if snd_codec.exist_property('spk-ctl-gpios'):
amp_gpio = snd_codec.get_property('spk-ctl-gpios').data
# ---------------------------------------------------------------
# Pick one of three sound card variants exposed by the base DTS
# (defined in rk3326-gameconsole-r36s.dts):
#
# 1. `rk817-sound-amplified`: external speaker amp gated by a
# discrete enable GPIO (R36S original, K36, most clones).
# Selected when vendor DTB declares `spk-con-gpio` (or its
# codec-side equivalent `spk-ctl-gpios`).
# 2. `rk817-sound-simple`: external amp on a regulator without
# a GPIO gate. Selected via the SRs flag, since vendor DTBs
# cannot disambiguate this from "no amp at all".
# 3. `rk817-sound-spko-direct`: speaker driven straight from
# the rk817 SPKO output, with no external amp. Selected via
# the NAm (No Amplifier) flag. This is what Y3506 Soysauce
# V03/V04/V05 actually need. Vendor BSP kernel 4.4 hid this
# gap because `rk817_codec.c` carried hardcoded DAPM
# widgets; mainline ASoC respects the DT strictly, so
# without this variant the speaker stays muted no matter
# what the vendor card declares.
#
# Vendor DTBs cannot be reliably auto-classified because the
# R36S original BSP and the Y3506 BSP both publish identical
# rk817-sound nodes (just Mic + Headphone, no Speaker widget,
# no `spk-con-gpio`). The amp presence is a hardware fact, so
# generator.sh tags soysauce boards with NAm and original /
# clone boards default to amplified.
force_no_amp = ('NAm' in args['flags'])
if force_no_amp:
rk817_path = hpdet_ovl.path+'/__overlay__/rk817-sound-spko-direct'
args['logger'].info("audio: spko-direct variant (NAm flag: no external amp, SPKO direct to speaker)")
elif amp_gpio:
# Determine preset, configure amplifier if needed
if amp_gpio:
rk817_path = hpdet_ovl.path+'/__overlay__/rk817-sound-amplified'
amp_gpio_sym = [p.name for p in symbols.props if p.value == resolve_phandle(dt, amp_gpio[0])][0]
gpio_num = int(amp_gpio_sym[4:])
args['logger'].info(f"audio: amplified variant (spk-con-gpio {amp_gpio_sym} {amp_gpio[1]})")
args['logger'].info(f"spk-con-gpio {amp_gpio_sym} {amp_gpio[1]} on {hpdet_ovl.path}")
amp_path = hpdet_ovl.path+'/__overlay__/audio-amplifier'
overlay.set_property('enable-gpios', [0xffffffff, amp_gpio[1], amp_gpio[2]], path=amp_path)
@@ -815,75 +478,29 @@ def make_dtbo(dtb_data, args):
amp_pc_path = hpdet_ovl.path+'/__overlay__/pinctrl/speaker/spk-amp-enable-h'
overlay.set_property('rockchip,pins', [gpio_num, amp_gpio[1], 0, 0xffffffff], path=amp_pc_path)
add_fixup(overlay, 'pcfg_pull_none', amp_pc_path+':rockchip,pins:12')
elif force_simple_audio_routing:
rk817_path = hpdet_ovl.path+'/__overlay__/rk817-sound-simple'
args['logger'].info("audio: simple variant (SRs flag: external amp on regulator)")
else:
# No amp GPIO detected, no SRs flag, no NAm flag. Keep the
# default rk817-sound (amp routing) active. This preserves
# R36S original/clone behaviour that worked under RC-3.
rk817_path = None
args['logger'].info("audio: keeping default rk817-sound (amp routing from base DTS)")
rk817_path = hpdet_ovl.path+'/__overlay__/rk817-sound-simple'
# If we picked an explicit variant (amplified/simple/spko-direct),
# enable it AND disable the default rk817-sound so the kernel
# never sees two simple-audio-card instances competing for the
# rk817 codec / i2s pair. If rk817_path is None we keep the
# base DTS sound card as-is.
if rk817_path is not None:
overlay.set_property('status', 'okay', path=rk817_path)
default_path = hpdet_ovl.path + '/__overlay__/rk817-sound'
overlay.set_property('status', 'disabled', path=default_path)
# Headphone-detect polarity needs to be inverted on a
# handful of boards (HPi flag).
if 'HPi' in args['flags']:
hpdet[2] = 0 if hpdet[2] != 0 else 1
overlay.set_property('simple-audio-card,hp-det-gpio',
[0xffffffff, hpdet[1], hpdet[2]],
path=rk817_path)
add_fixup(overlay, gpio_sym, rk817_path+':simple-audio-card,hp-det-gpio:0')
# Pinctrl override only when the vendor DTB actually defines
# /pinctrl/headphone/hp-det. Boards without that node use
# the base DTS pinctrl unchanged.
if hp_det_pins is not None and hp_det_pull_node is not None:
pins_path = hpdet_ovl.path+'/__overlay__/pinctrl/headphone/hp-det'
overlay.set_property('rockchip,pins', hp_det_pins[0:3] + [0xffffffff], path=pins_path)
if hp_det_pull_node.exist_property('bias-pull-down'):
add_fixup(overlay, 'pcfg_pull_down', pins_path+':rockchip,pins:12')
else:
add_fixup(overlay, 'pcfg_pull_up', pins_path+':rockchip,pins:12')
args['logger'].info(f"hp-det-gpio {gpio_sym} on {hpdet_ovl.path}")
overlay.set_property('status', 'okay', path=rk817_path)
# for some reason hp detection polarity needs to be inverted on some devices
if 'HPi' in args['flags']:
if hpdet[2] == 0:
hpdet[2] = 1
else:
hpdet[2] = 0
overlay.set_property('simple-audio-card,hp-det-gpio', [0xffffffff, hpdet[1], hpdet[2]], path=rk817_path)
add_fixup(overlay, gpio_sym, rk817_path+':simple-audio-card,hp-det-gpio:0')
pins_path = hpdet_ovl.path+'/__overlay__/pinctrl/headphone/hp-det'
overlay.set_property('rockchip,pins', hp_det_pins[0:3] + [0xffffffff], path=pins_path)
# Restore bias reference
if hp_det_pull_node.exist_property('bias-pull-down'):
add_fixup(overlay, 'pcfg_pull_down', pins_path+':rockchip,pins:12')
else:
add_fixup(overlay, 'pcfg_pull_up', pins_path+':rockchip,pins:12')
args['logger'].info(f"hp-det-gpio {gpiosyms[0]} on {hpdet_ovl.path}")
except Exception as e:
import traceback
args['logger'].info(f"audio block: {e}\n{traceback.format_exc()}")
# Fallback for boards where the vendor DTB lacks `hp-det-gpio`
# entirely (six Y3506 Soysauce V03/V04 batches). With NAm we
# still need to switch the active sound card to spko-direct,
# even though we can't propagate the headphone-detect pin from
# the vendor. The base DTS variant carries a sensible default
# hp-det-gpio so headphone detection still works on the panel
# the kernel actually ships for these boards.
if 'NAm' in args['flags']:
try:
hpdet_ovl_fb = add_overlay(overlay, '/')
spko_path = hpdet_ovl_fb.path + '/__overlay__/rk817-sound-spko-direct'
default_path = hpdet_ovl_fb.path + '/__overlay__/rk817-sound'
overlay.set_property('status', 'okay', path=spko_path)
overlay.set_property('status', 'disabled', path=default_path)
args['logger'].info("audio: spko-direct variant via fallback (NAm flag, no hp-det in vendor)")
except Exception as e2:
args['logger'].info(f"audio fallback also failed: {e2}")
# Tier 3: walk any remaining vendor properties we haven't already
# handled and propagate them. Catches board-specific quirks (custom
# rumble flags, exotic input properties, etc.) without us needing
# to hardcode every possible vendor invention.
auto_discover_custom(dt, overlay, panel_ovl, jp_ovl, args)
args['logger'].info(e)
# Move fixups to the very end (if any)
if overlay.exist_node('__fixups__'):
+10 -48
View File
@@ -99,17 +99,16 @@ VARIANT_FLAGS_MM=("JPmm" "JPk36" "JPmm" "JPmm-SRs" "JPk36-SRs" "J
VARIANT_SUFFIX_MM=("" "_JPk36" "_JPmm" "_SRs" "_JPk36_SRs" "_JPmm_SRs")
# Pick the variant flag/suffix arrays that match each subdevice's expected
# default. Every Y3506 (soysauce) vendor DTB we have inspected (V03 1104,
# V03 1210 2507/2533, V03 0317, V04 2528, V04 253x P6/P7, V04 2548, V05
# 2551, V05 2601) ships odroidgo3-joypad with amux-count=4 and
# amux-channel-mapping — that's K36 (single-ADC + amux). The earlier
# assumption that Y3506 was MyMini was wrong, and forcing JPmm here
# made the overlay inject multi-ADC io-channels that the singleadc
# driver ignores, leaving the sticks dead (see issue #27). K36 is the
# safe default everywhere; MyMini boards (if any ever appear) can pick
# the _JPmm suffix variant explicitly.
# default. Names are matched literally against $sd.
default_variant_arrays() {
echo "K36"
case "$1" in
soysauce)
echo "MM"
;;
*)
echo "K36"
;;
esac
}
process_subdevice() {
@@ -134,33 +133,6 @@ process_subdevice() {
local -n suffix_arr="VARIANT_SUFFIX_${kind}"
log "Default joypad: ${kind} (${flags_arr[0]:-K36})"
# SDORIG: trust the `odroidgo3 in compat` early-return in archr-dtbo.py.
# Original and soysauce kernel DTBs (rk3326-odroid-go2.dtb and
# rk3326-gameconsole-soysauce.dtb) already carry the correct
# reset-gpios / vcc18-lcd0 / backlight wiring, so the DTBO only needs
# the panel description. Clone hardware needs the GPIO overrides
# because the eeclone kernel DTB is wired differently from the actual
# boards; several clone vendor DTBs are mislabeled with `odroidgo3`
# compatible and previously slipped through the short-circuit, leaving
# the overlay without GPIO fixes (= "backlight on, no image").
local sd_prefix=""
case "$sd" in
original|soysauce) sd_prefix="SDORIG" ;;
esac
# Soysauce (Y3506) boards have NO external speaker amplifier on
# the PCB; the rk817 SPKO line drives the speaker directly. The
# vendor BSP 4.4 hides this with hardcoded DAPM widgets in
# rk817_codec.c, but mainline ASoC respects the DT strictly, so
# without the NAm flag the speaker stays muted on every Y3506
# board (most visibly on V05 where users actually use it). We
# append NAm to every soysauce overlay so the generator picks the
# `rk817-sound-spko-direct` card variant.
local audio_flag=""
case "$sd" in
soysauce) audio_flag="NAm" ;;
esac
local count=0
# Sort makes output deterministic across filesystems.
while IFS= read -r mb_dir; do
@@ -181,17 +153,7 @@ process_subdevice() {
local flags="${flags_arr[$i]}"
local suffix="${suffix_arr[$i]}"
local out_file="${out_dir}/${sanitized}${suffix}.dtbo"
# Compose the flag string in stable order:
# <sd_prefix>-<audio_flag>-<variant flags>
local parts=()
[ -n "$sd_prefix" ] && parts+=("$sd_prefix")
[ -n "$audio_flag" ] && parts+=("$audio_flag")
[ -n "$flags" ] && parts+=("$flags")
local effective_flags
effective_flags="$(IFS=-; echo "${parts[*]}")"
generate_overlay "$input_dtb" "$out_file" "${sd}/${mb_name}${suffix}" "$effective_flags"
generate_overlay "$input_dtb" "$out_file" "${sd}/${mb_name}${suffix}" "$flags"
done
count=$((count + 1))
done < <(find "$src_dir" -mindepth 1 -maxdepth 1 -type d | sort)
@@ -1,9 +1,9 @@
|Manufacturer|System|Release Date|Games Path|Supported Extensions|Emulator / Core|
|----|----|----|----|----|----|
|&#xf013; System|Media Player (mplayer)|System|`mplayer`|.3g2 .3gp .aac .ac3 .asf .avi .divx .dts .eac33 .f4f .f4v .flac .flv .m2p .m2ts .m3u .m4a .m4v .mka .mkv .mov .mp3 .mp4 .mpeg .mpg .mxf .ogg .ogm .opus .ps .sh .thd .ts .twi .vob .wav .webm .wma .wmv .wv .ytb|**mplayer:** mplayer (default)<br>**retroarch:** ffmpeg<br>|
|&#xf013; System|Media Player (mplayer)|System|`mplayer`|.3g2 .3gp .aac .ac3 .asf .avi .divx .dts .eac33 .f4f .f4v .flac .flv .m2p .m2ts .m3u .m4a .mka .mkv .mov .mp3 .mp4 .mpeg .mpg .mxf .ogg .ogm .opus .ps .sh .thd .ts .twi .vob .wav .webm .wma .wmv .wv .ytb|**mplayer:** mplayer (default)<br>**retroarch:** ffmpeg<br>|
|&#xf013; System|Moonlight Game Streaming (moonlight)|System|`moonlight`|.sh|**moonlight:** moonlight (default)<br>|
|&#xf013; System|Music Player (music)|System|`playlists`|.m3u .sh|**gmu:** gmu (default)<br>|
|&#xf013; System|Ports (ports)|System|`ports`|.sh .appimage|**portmaster:** portmaster (default)<br>|
|&#xf013; System|Ports (ports)|System|`ports`|.sh|**portmaster:** portmaster (default)<br>|
|&#xf013; System|Screenshots (imageviewer)|System|`screenshots`|.jpg .jpeg .png .bmp .psd .tga .gif .hdr .pic .ppm .pgm .mkv .pdf .mp4 .avi||
|&#xf013; System|Tools (tools)|System|`modules`|.sh||
|Acorn|BBC Micro (bbcmicro)|1981|`bbcmicro`|.ssd .dsd|**retroarch:** b2 (default)<br>|
@@ -40,7 +40,6 @@
|Elektronika|Elektronika BK (bk)|1984|`bk`|.bin .img .dsk|**retroarch:** bk (default)<br>|
|EPOCH/YENO|Super Cassette Vision (scv)|1984|`scv`|.cart .bin .rom .0 .zip|**retroarch:** emuscv (default)<br>|
|Fairchild|Fairchild Channel F (channelf)|1976|`channelf`|.bin .chf .zip .7z|**retroarch:** freechaf (default)<br>|
|GamePark|GP32 (gp32)|1996|`gp32`|.smc .zip .7z|**retroarch:** mame (default)<br>|
|id Software|Doom (doom)|1993|`doom`|.doom|**gzdoom:** gzdoom-sa (default)<br>|
|id Software|iDtech (idtech)|1991|`idtech`|.sh|**retroarch:** idtech<br>|
|Infocom|Z-machine (zmachine)|1979|`zmachine`|.dat .z1 .z2 .z3 .z4 .z5 .z6 .zip|**retroarch:** mojozork (default)<br>|
Binary file not shown.
Binary file not shown.
@@ -179,28 +179,6 @@
};
};
/*
* Force the rumble motor enable pin (gpio0 PB7, shared with pwm0 function)
* to drive LOW at gpiolib probe time. Without this, some R36S revisions
* (notably V21 P4 — see archr-linux/Arch-R#25) come out of reset with the
* pin in a high-impedance / pulled-up state, the rumble transistor latches
* on and the motor runs continuously through boot.
*
* The hog acquires the pin before the PWM driver, which means rumble is
* effectively disabled on every R36S that uses this DTS. Trade-off: a few
* boards lose rumble support, but every board stops vibrating non-stop.
* If a future R36S variant needs working rumble, gate this with a board
* compatible check instead of removing it outright.
*/
&gpio0 {
rumble-en-hold-low {
gpio-hog;
gpios = <RK_PB7 GPIO_ACTIVE_HIGH>;
output-low;
line-name = "rumble_en_hold_low";
};
};
&pinctrl {
btns {
btn_pins: btn-pins {
@@ -53,14 +53,7 @@
};
joypad: odroidgo3-joypad {
/* All Y3506 (soysauce) boards we've seen use single-ADC + amux
* (amux-count=4, amux-channel-mapping=<3 2 0 1>) — that is the
* archr-singleadc-joypad driver's wire protocol. The previous
* "archr-joypad" / "odroidgo3-joypad" compat strings bind to
* the multi-ADC driver, which ignores the amux-* props and
* leaves the analog sticks dead (see archr-linux/Arch-R#27).
*/
compatible = "archr-singleadc-joypad";
compatible = "archr-joypad", "odroidgo3-joypad";
pwms = <&pwm0 0 200000000 0>;
pwm-names = "enable";
rumble-boost-weak = <0x0000>;
@@ -7,7 +7,7 @@ PKG_ARCH="arm aarch64"
PKG_LICENSE="MIT"
PKG_SITE="https://github.com/PortsMaster/PortMaster-GUI"
PKG_URL="https://github.com/PortsMaster/PortMaster-GUI/releases/download/${PKG_VERSION}/PortMaster.zip"
PKG_DEPENDS_TARGET="toolchain archr-hotkey gamecontrollerdb oga_controls control-gen xmlstarlet list-guid gst-plugins-base Python3 xz portmaster-compat-libs"
PKG_DEPENDS_TARGET="toolchain archr-hotkey gamecontrollerdb oga_controls control-gen xmlstarlet list-guid gst-plugins-base Python3 xz"
PKG_LONGDESC="Portmaster - a simple tool that allows you to download various game ports"
PKG_TOOLCHAIN="manual"
@@ -28,8 +28,4 @@ makeinstall_target() {
mkdir -p ${INSTALL}/usr/lib/compat
curl -Lo ${PKG_BUILD}/compat.zip ${COMPAT_URL}
unzip -qq ${PKG_BUILD}/compat.zip -d ${INSTALL}/usr/lib/compat
# libcodec2.so.0.9, libx264.so.160 e libx265.so.192 (SONAMEs do
# Debian 11 listados no PortMaster_CFW.md) sao instaladas como
# arquivos reais pelo pacote portmaster-compat-libs (dependencia).
}
@@ -15,15 +15,11 @@ fi
cd /storage/.config/PortMaster
#Grab the latest control.txt, mapper.txt & mod_ArchR.txt, then set correct permissions
#Grab the latest control.txt & mapper.txt, then set correct permissions
cp /usr/config/PortMaster/control.txt control.txt
chmod +x /storage/.config/PortMaster/control.txt
cp /usr/config/PortMaster/mapper.txt mapper.txt
chmod +x /storage/.config/PortMaster/mapper.txt
if [ -f /usr/config/PortMaster/mod_ArchR.txt ]; then
cp /usr/config/PortMaster/mod_ArchR.txt mod_ArchR.txt
chmod +x /storage/.config/PortMaster/mod_ArchR.txt
fi
#Use our gamecontrollerdb.txt
@@ -51,7 +47,6 @@ rm -f gptokeyb
#Copy over required files for ports
cp /storage/.config/PortMaster/control.txt /storage/roms/ports/PortMaster/control.txt
cp /storage/.config/PortMaster/mapper.txt /storage/roms/ports/PortMaster/mapper.txt
[ -f /storage/.config/PortMaster/mod_ArchR.txt ] && cp /storage/.config/PortMaster/mod_ArchR.txt /storage/roms/ports/PortMaster/mod_ArchR.txt
cp /storage/.config/PortMaster/gamecontrollerdb.txt /storage/roms/ports/PortMaster/gamecontrollerdb.txt
cp /usr/bin/oga_controls* /storage/roms/ports/PortMaster/
@@ -17,11 +17,6 @@
directory="roms"
controlfolder="/$directory/ports/PortMaster"
# ArchR roda EmulationStation/runemu/PortMaster como root (modelo herdado de
# JELOS/ROCKNIX). Por isso ESUDO fica vazio: ports que executam mount,
# umount, chmod /dev/uinput, zramctl, swapon ou systemctl funcionam sem
# privilege escalation. Se algum dia o frontend rodar como usuario comum,
# adicionar doas/sudo e definir ESUDO="doas" (ou "sudo") aqui.
ESUDO=""
ESUDOKILL="-1"
ESUDOKILL2="-1"
@@ -1,37 +0,0 @@
#!/bin/bash
#
# SPDX-License-Identifier: MIT
#
## Modular - ArchR
#
# A modular file that is sourced for specific script lines required by ports
# running on ArchR. Triggered by PortMaster.sh via:
# [ -f "${controlfolder}/mod_${CFW_NAME}.txt" ] && source "${controlfolder}/mod_${CFW_NAME}.txt"
#
# CFW_NAME is read from /etc/os-release (NAME="ArchR").
PORT_32BIT="${PORT_32BIT:-"N"}"
if [[ "$PORT_32BIT" == "Y" ]]; then
export SPA_PLUGIN_DIR="/usr/lib32/spa-0.2"
export PIPEWIRE_MODULE_DIR="/usr/lib32/pipewire-0.3/"
fi
export LIBGL_DRIVERS_PATH=/usr/lib32/dri:/usr/lib/dri
# Use for Godot 2
GODOT2_OPTS="-r ${DISPLAY_WIDTH}x${DISPLAY_HEIGHT} -f"
# Use for Godot 3+
GODOT_OPTS="--resolution ${DISPLAY_WIDTH}x${DISPLAY_HEIGHT} -f"
pm_platform_helper() {
if [ -e "$PM_PIPE" ]; then
PortMasterDialogExit
fi
if [ -e "/usr/bin/portmaster_sway_fullscreen.sh" ]; then
/usr/bin/portmaster_sway_fullscreen.sh "$(basename "$1")"
fi
}
@@ -65,54 +65,22 @@ function start_ms() {
fi
MS_ENABLED=$(get_setting system.merged.storage)
if [ "${1}" = "internal" ]
then
# No external SD detected — /storage/roms (the real internal ROMs
# directory) is already the right thing for EmulationStation.
log $0 "No external SD; /storage/roms used directly"
return 0
fi
if [ -e "/storage/.ms_unsupported" ] || \
[ ! "${MS_ENABLED}" = 1 ]
then
# External SD present but overlay isn't usable (FAT/exFAT/NTFS) or
# merged storage was disabled by the user. Bind-mount the external
# roms over /storage/roms so ES sees them. The internal /storage/roms
# content is shadowed for as long as the external SD is mounted; it
# comes back next boot if the user pulls the card.
if [ -d "/storage/games-external/roms" ]
then
log $0 "Bind-mounting /storage/games-external/roms over ${MS_PATH}"
mount --bind /storage/games-external/roms ${MS_PATH}
else
log $0 "External SD has no roms/ directory; leaving /storage/roms intact"
fi
# Single SD: /storage/roms is used directly (no bind mount needed)
log $0 "Using /storage/roms directly"
else
log $0 "Enabling merged storage of games-${LOWER} and games-${UPPER} on ${MS_PATH}."
log $0 "Enabling merged storage of /storage/games-${LOWER} and /storage/games-${UPPER} to ${MS_PATH}."
# `LOWER`/`UPPER` may refer to "internal" — which now lives at
# /storage/roms directly. Resolve "internal" to the real /storage/roms
# path; bind-mount it to a working location so overlayfs doesn't try
# to use the same path as both lowerdir and mount point (which would
# fail with -EBUSY).
local LOWER_DIR UPPER_DIR
[ "${LOWER}" = "internal" ] && LOWER_DIR="/storage/.games-internal-bind/roms" || LOWER_DIR="/storage/games-${LOWER}/roms"
[ "${UPPER}" = "internal" ] && UPPER_DIR="/storage/.games-internal-bind/roms" || UPPER_DIR="/storage/games-${UPPER}/roms"
if [ "${LOWER}" = "internal" ] || [ "${UPPER}" = "internal" ]
then
mkdir -p /storage/.games-internal-bind/roms
mountpoint -q /storage/.games-internal-bind/roms || \
mount --bind /storage/roms /storage/.games-internal-bind/roms
fi
for DIR in /storage/games-${UPPER}/.tmp/games-workdir "${LOWER_DIR}" "${UPPER_DIR}"
for DIR in /storage/games-${UPPER}/.tmp/games-workdir /storage/games-${LOWER}/roms /storage/games-${UPPER}/roms
do
[ -d "${DIR}" ] || mkdir -p "${DIR}"
if [ ! -d "${DIR}" ]
then
mkdir -p "${DIR}"
fi
done
mount overlay -t overlay -o lowerdir=${LOWER_DIR},upperdir=${UPPER_DIR},workdir=/storage/games-${UPPER}/.tmp/games-workdir ${MS_PATH}
mount overlay -t overlay -o lowerdir=/storage/games-${LOWER}/roms,upperdir=/storage/games-${UPPER}/roms,workdir=/storage/games-${UPPER}/.tmp/games-workdir ${MS_PATH}
fi
}
@@ -354,13 +354,8 @@ case ${EMULATOR} in
RUNTHIS='${RUN_SHELL} /usr/bin/start_dolphin_wii.sh "${ROMNAME}" "${PLATFORM}" "${CORE}"'
;;
"ports")
if [[ "${ROMNAME,,}" == *".appimage" ]]; then
RUNTHIS='${EMUPERF} "${ROMNAME}"'
else
RUNTHIS='${EMUPERF} ${RUN_SHELL} "${ROMNAME}"'
fi
chmod +x "${ROMNAME}"
sed -i "/^ACTIVE_GAME=/c\ACTIVE_GAME=\"${ROMNAME}\"" /storage/.config/PortMaster/mapper.txt
RUNTHIS='${EMUPERF} ${RUN_SHELL} "${ROMNAME}"'
sed -i "/^ACTIVE_GAME=/c\ACTIVE_GAME=\"${ROMNAME}\"" /storage/.config/PortMaster/mapper.txt
sed -i "/^ACTIVE_PLATFORM=/c\ACTIVE_PLATFORM=\"${PLATFORM}\"" /storage/.config/PortMaster/mapper.txt
;;
"windows")

Some files were not shown because too many files have changed in this diff Show More