mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-01 00:27:20 -05:00
chore: merge games parts and cores ticked
# Conflicts: # tests/test_doc_pages.py
This commit is contained in:
commit
57e0f306e8
31 files changed
+1669
-514
No files matched your search
+1
-1
@@ -16,7 +16,7 @@
|
||||
# and Invoke-WebRequest throws on a cut transfer before the hash is read:
|
||||
# the site's build rewrites this line there (scripts/sitebootstrap.py).
|
||||
$mismatchAdvice = "The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
|
||||
$defaultInstallSha256 = "665534440e8b79c9643e6dc176c4a03da1ec497f151eb33fa0b9d4fb44809511"
|
||||
$defaultInstallSha256 = "403b6e8a7efcd24858b0f46ffa19c2b9012cdeef149768729d8e48d0b68a296a"
|
||||
$maximumInstallerBytes = 2MB
|
||||
$installerExit = 0
|
||||
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
|
||||
|
||||
+629
-187
File diff suppressed because it is too large.
Load diff
+1
-1
@@ -23,7 +23,7 @@ DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/ins
|
||||
# curl or wget stop on a cut transfer before the hash is read: the site's
|
||||
# build rewrites this line there (scripts/sitebootstrap.py).
|
||||
MISMATCH_ADVICE="The download was most likely cut short: try again. Within minutes of an update of this project the two files can come from caches of different ages. Waiting five minutes settles that."
|
||||
DEFAULT_INSTALL_SHA256="665534440e8b79c9643e6dc176c4a03da1ec497f151eb33fa0b9d4fb44809511"
|
||||
DEFAULT_INSTALL_SHA256="403b6e8a7efcd24858b0f46ffa19c2b9012cdeef149768729d8e48d0b68a296a"
|
||||
MAX_INSTALLER_BYTES=2097152
|
||||
|
||||
cleanup() {
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
{
|
||||
"dest": "roms/ports/retrobios/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 961225,
|
||||
"sha256": "665534440e8b79c9643e6dc176c4a03da1ec497f151eb33fa0b9d4fb44809511",
|
||||
"size": 984900,
|
||||
"sha256": "403b6e8a7efcd24858b0f46ffa19c2b9012cdeef149768729d8e48d0b68a296a",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
@@ -71,8 +71,8 @@
|
||||
"muos": {
|
||||
"archive": {
|
||||
"dest": "ARCHIVE/RetroBIOS.muxapp",
|
||||
"size": 1014402,
|
||||
"sha256": "cdd06d24d30ad6b564d8a1595b906d50ce05d23093121cc7e5d91b5acd8e08ab"
|
||||
"size": 1038077,
|
||||
"sha256": "49b9de6afa23afda4f6c786fa0968c36af1bd2ec9b52cb0927df4c527dcc701c"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
@@ -92,8 +92,8 @@
|
||||
{
|
||||
"name": "RetroBIOS/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 961225,
|
||||
"sha256": "665534440e8b79c9643e6dc176c4a03da1ec497f151eb33fa0b9d4fb44809511",
|
||||
"size": 984900,
|
||||
"sha256": "403b6e8a7efcd24858b0f46ffa19c2b9012cdeef149768729d8e48d0b68a296a",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
@@ -166,8 +166,8 @@
|
||||
{
|
||||
"dest": ".config/modules/retrobios/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 961225,
|
||||
"sha256": "665534440e8b79c9643e6dc176c4a03da1ec497f151eb33fa0b9d4fb44809511",
|
||||
"size": 984900,
|
||||
"sha256": "403b6e8a7efcd24858b0f46ffa19c2b9012cdeef149768729d8e48d0b68a296a",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -177,8 +177,13 @@ def _marker(rule: _install._OsRule) -> str:
|
||||
path, pattern = rule.values
|
||||
line = re.sub(r"\\s\*\$$", "", re.sub(r"^(\^|\\A)", "", pattern)).replace("\\", "")
|
||||
return f"`{path}` holding the line `{line}`"
|
||||
return ", ".join(f"`{value}`" if PurePosixPath(value).suffix else f"`{value}/`"
|
||||
for value in rule.values)
|
||||
named = ", ".join(f"`{value}`" if PurePosixPath(value).suffix else f"`{value}/`"
|
||||
for value in rule.values)
|
||||
if rule.method == "games_part":
|
||||
# Told on the games part beside its bios folder, on a drive the
|
||||
# system does not call fixed (install.games_part).
|
||||
return f"{named} beside `bios/`, on a drive that is not a fixed disk"
|
||||
return named
|
||||
|
||||
|
||||
def _list_words(plat: str) -> str:
|
||||
@@ -189,7 +194,8 @@ def _list_words(plat: str) -> str:
|
||||
def card_marker_rows() -> list[list[str]]:
|
||||
"""The files that name a card or a SHARE drive, in the order they are
|
||||
read: install.py's card rules, then its SHARE drive files."""
|
||||
rows = [[_marker(rule), rule.name, f"`{rule.bios}`, {_list_words(rule.manifest)}"]
|
||||
rows = [[_marker(rule), rule.name,
|
||||
f"`{rule.bios or 'bios'}`, {_list_words(rule.manifest)}"]
|
||||
for rule in _install._card_rules()]
|
||||
hostname = "system.hostname=BATOCERA"
|
||||
for plat, marker in _install._SHARE_DRIVES:
|
||||
|
||||
@@ -3940,8 +3940,11 @@ def first_screen_words() -> list[str]:
|
||||
showed a line menu (Enter, i, c, q) nobody saw, whose keys had changed
|
||||
since."""
|
||||
installer = _installer()
|
||||
return [f"The command opens a screen. **{installer.TUI_INSTALL_ROW}** gets every "
|
||||
f"file, **{installer.TUI_SYSTEMS_ROW}** fewer."]
|
||||
# The screen it opens first: the setup found, or the list when none
|
||||
# is. Install comes on the next one, Choose systems beside it and named
|
||||
# above on the page (tui_audit_16 P3-10).
|
||||
return [f"It asks **{installer.TUI_FOUND_TITLE}** (or **{installer.TUI_CHOOSE_TITLE}**), "
|
||||
f"then offers **{installer.TUI_INSTALL_ROW}**."]
|
||||
|
||||
|
||||
def check_pass_line() -> str:
|
||||
|
||||
Vendored
+7
-7
@@ -494,7 +494,7 @@
|
||||
^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Preferred regions^[[0m
|
||||
|
||||
Tick the regions to keep, best first. Where a system has one BIOS per region, the best one found
|
||||
is installed.
|
||||
is installed. With none ticked, every region's BIOS is kept.
|
||||
|
||||
^[[0;7;35m > [1] North America^[[0m
|
||||
[ ] Japan
|
||||
@@ -534,9 +534,12 @@
|
||||
=== cores
|
||||
^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Cores^[[0m
|
||||
|
||||
Tick the cores you use. With none ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's files. Untick the cores you do not use: the platform's own
|
||||
files are always kept.
|
||||
|
||||
^[[0;7;35m > Filter (/ to type)^[[0m
|
||||
^[[0;7;35m > All^[[0m
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
@@ -568,10 +571,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
^[[0;1;35mA/Enter^[[0m Filter ^[[0;2mB/Esc^[[0m Back ^[[0;2mX/Space^[[0m Tick ^[[0;2m?^[[0m Help
|
||||
^[[0;1;35mA/Enter^[[0m Tick all ^[[0;2mB/Esc^[[0m Back ^[[0;2mX/Space^[[0m Tick ^[[0;2m?^[[0m Help
|
||||
=== preview
|
||||
^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Preview^[[0m
|
||||
|
||||
|
||||
Vendored
+10
-10
@@ -160,26 +160,26 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
^[[0;7;35m > [1] North America^[[0m
|
||||
[ ] Japan
|
||||
|
||||
|
||||
^[[0;1;35mA^[[0m Tick ^[[0;2mB^[[0m Done ^[[0;2m<>^[[0m Order ^[[0;2m?^[[0m Help
|
||||
=== cores
|
||||
^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Cores^[[0m
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
|
||||
^[[0;7;35m > Filter (/ to type)^[[0m
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
^[[0;7;35m > All^[[0m
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
^[[0;1;35mA^[[0m Filter ^[[0;2mB^[[0m Back ^[[0;2mX^[[0m Tick ^[[0;2m?^[[0m Help
|
||||
^[[0;1;35mA^[[0m Tick all ^[[0;2mB^[[0m Back ^[[0;2mX^[[0m Tick ^[[0;2m?^[[0m Help
|
||||
=== preview
|
||||
^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Preview^[[0m
|
||||
|
||||
|
||||
Vendored
+10
-10
@@ -196,7 +196,8 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
^[[0;7;35m > [1] North America^[[0m
|
||||
[ ] Japan
|
||||
@@ -204,24 +205,23 @@
|
||||
|
||||
|
||||
|
||||
|
||||
^[[0;1;35mA^[[0m Tick ^[[0;2mB^[[0m Done ^[[0;2m<>^[[0m Order ^[[0;2m?^[[0m Help
|
||||
=== cores
|
||||
^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Cores^[[0m
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
|
||||
^[[0;7;35m > Filter (/ to type)^[[0m
|
||||
^[[0;7;35m > All^[[0m
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
^[[0;1;35mA^[[0m Filter ^[[0;2mB^[[0m Back ^[[0;2mX^[[0m Tick ^[[0;2m?^[[0m Help
|
||||
^[[0;1;35mA^[[0m Tick all ^[[0;2mB^[[0m Back ^[[0;2mX^[[0m Tick ^[[0;2m?^[[0m Help
|
||||
=== preview
|
||||
^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Preview^[[0m
|
||||
|
||||
|
||||
Vendored
+8
-8
@@ -302,7 +302,8 @@
|
||||
^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Preferred regions^[[0m
|
||||
|
||||
Tick the regions to keep, best first. Where a system has one BIOS per region,
|
||||
the best one found is installed.
|
||||
the best one found is installed. With none ticked, every region's BIOS is
|
||||
kept.
|
||||
|
||||
^[[0;7;35m > [1] North America^[[0m
|
||||
[ ] Japan
|
||||
@@ -321,14 +322,16 @@
|
||||
|
||||
|
||||
|
||||
|
||||
^[[0;1;35mA/Enter^[[0m Tick ^[[0;2mB/Esc^[[0m Done ^[[0;2mLeft/Right^[[0m Order ^[[0;2m?^[[0m Help
|
||||
=== cores
|
||||
^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Cores^[[0m
|
||||
|
||||
Tick the cores you use. With none ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's files. Untick the cores you do not use:
|
||||
the platform's own files are always kept.
|
||||
|
||||
^[[0;7;35m > Filter (/ to type)^[[0m
|
||||
^[[0;7;35m > All^[[0m
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
@@ -344,10 +347,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
^[[0;1;35mA/Enter^[[0m Filter ^[[0;2mB/Esc^[[0m Back ^[[0;2mX/Space^[[0m Tick ^[[0;2m?^[[0m Help
|
||||
^[[0;1;35mA/Enter^[[0m Tick all ^[[0;2mB/Esc^[[0m Back ^[[0;2mX/Space^[[0m Tick ^[[0;2m?^[[0m Help
|
||||
=== preview
|
||||
^[[0;1m ^[[0;1;35mRetroBIOS^[[0;1m: Preview^[[0m
|
||||
|
||||
|
||||
Vendored
+6
-6
@@ -1,8 +1,11 @@
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's files. Untick the cores you do not use: the platform's own
|
||||
files are always kept.
|
||||
|
||||
> Filter (/ to type)
|
||||
> All
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
@@ -34,7 +37,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A/Enter Filter B/Esc Back X/Space Tick ? Help
|
||||
A/Enter Tick all B/Esc Back X/Space Tick ? Help
|
||||
Vendored
+8
-8
@@ -1,12 +1,12 @@
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
|
||||
> Filter (/ to type)
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
> All
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick ? Help
|
||||
A Tick all B Back X Tick ? Help
|
||||
Vendored
+8
-8
@@ -1,15 +1,15 @@
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
|
||||
> Filter (/ to type)
|
||||
> All
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick ? Help
|
||||
A Tick all B Back X Tick ? Help
|
||||
Vendored
+6
-6
@@ -1,8 +1,11 @@
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's files. Untick the cores you do not use:
|
||||
the platform's own files are always kept.
|
||||
|
||||
> Filter (/ to type)
|
||||
> All
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
@@ -18,7 +21,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A/Enter Filter B/Esc Back X/Space Tick ? Help
|
||||
A/Enter Tick all B/Esc Back X/Space Tick ? Help
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
RetroBIOS: Preferred regions
|
||||
|
||||
Tick the regions to keep, best first. Where a system has one BIOS per region, the best one found
|
||||
is installed.
|
||||
is installed. With none ticked, every region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
|
||||
Vendored
+2
-2
@@ -3,10 +3,10 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
|
||||
|
||||
A Tick B Done <> Order ? Help
|
||||
Vendored
+2
-2
@@ -3,7 +3,8 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -11,5 +12,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
A Tick B Done <> Order ? Help
|
||||
Vendored
+2
-2
@@ -1,7 +1,8 @@
|
||||
RetroBIOS: Preferred regions
|
||||
|
||||
Tick the regions to keep, best first. Where a system has one BIOS per region,
|
||||
the best one found is installed.
|
||||
the best one found is installed. With none ticked, every region's BIOS is
|
||||
kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -20,5 +21,4 @@
|
||||
|
||||
|
||||
|
||||
|
||||
A/Enter Tick B/Esc Done Left/Right Order ? Help
|
||||
Vendored
+28
-28
@@ -623,12 +623,12 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
|
||||
|
||||
A Tick B Done <> Order
|
||||
=== regions 40x15
|
||||
RetroBIOS: Preferred regions
|
||||
@@ -636,7 +636,8 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -644,13 +645,13 @@
|
||||
|
||||
|
||||
|
||||
|
||||
A Tick B Done <> Order
|
||||
=== regions 80x24
|
||||
RetroBIOS: Preferred regions
|
||||
|
||||
Tick the regions to keep, best first. Where a system has one BIOS per region,
|
||||
the best one found is installed.
|
||||
the best one found is installed. With none ticked, every region's BIOS is
|
||||
kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -669,43 +670,45 @@
|
||||
|
||||
|
||||
|
||||
|
||||
A Tick B Done Left/Right Order
|
||||
=== cores 40x12
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick
|
||||
A Tick all B Back X Tick
|
||||
=== cores 40x15
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick
|
||||
A Tick all B Back X Tick
|
||||
=== cores 80x24
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's files. Untick the cores you do not use:
|
||||
the platform's own files are always kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
@@ -721,10 +724,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick
|
||||
A Tick all B Back X Tick
|
||||
=== preview 80x24
|
||||
RetroBIOS: Preview
|
||||
|
||||
|
||||
+28
-28
@@ -623,12 +623,12 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
|
||||
|
||||
A Tick B Done <> Order
|
||||
=== regions 40x15
|
||||
RetroBIOS: Preferred regions
|
||||
@@ -636,7 +636,8 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -644,13 +645,13 @@
|
||||
|
||||
|
||||
|
||||
|
||||
A Tick B Done <> Order
|
||||
=== regions 80x24
|
||||
RetroBIOS: Preferred regions
|
||||
|
||||
Tick the regions to keep, best first. Where a system has one BIOS per region,
|
||||
the best one found is installed.
|
||||
the best one found is installed. With none ticked, every region's BIOS is
|
||||
kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -669,43 +670,45 @@
|
||||
|
||||
|
||||
|
||||
|
||||
A Tick B Done Left/Right Order
|
||||
=== cores 40x12
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick
|
||||
A Tick all B Back X Tick
|
||||
=== cores 40x15
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick
|
||||
A Tick all B Back X Tick
|
||||
=== cores 80x24
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's files. Untick the cores you do not use:
|
||||
the platform's own files are always kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
@@ -721,10 +724,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick
|
||||
A Tick all B Back X Tick
|
||||
=== preview 80x24
|
||||
RetroBIOS: Preview
|
||||
|
||||
|
||||
+28
-28
@@ -623,12 +623,12 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
|
||||
|
||||
A Tick B Done <> Order
|
||||
=== regions 40x15
|
||||
RetroBIOS: Preferred regions
|
||||
@@ -636,7 +636,8 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -644,13 +645,13 @@
|
||||
|
||||
|
||||
|
||||
|
||||
A Tick B Done <> Order
|
||||
=== regions 80x24
|
||||
RetroBIOS: Preferred regions
|
||||
|
||||
Tick the regions to keep, best first. Where a system has one BIOS per region,
|
||||
the best one found is installed.
|
||||
the best one found is installed. With none ticked, every region's BIOS is
|
||||
kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -669,43 +670,45 @@
|
||||
|
||||
|
||||
|
||||
|
||||
A Tick B Done Left/Right Order
|
||||
=== cores 40x12
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick
|
||||
A Tick all B Back X Tick
|
||||
=== cores 40x15
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick
|
||||
A Tick all B Back X Tick
|
||||
=== cores 80x24
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's files. Untick the cores you do not use:
|
||||
the platform's own files are always kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
@@ -721,10 +724,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Filter B Back X Tick
|
||||
A Tick all B Back X Tick
|
||||
=== preview 80x24
|
||||
RetroBIOS: Preview
|
||||
|
||||
|
||||
Vendored
+28
-28
@@ -598,12 +598,12 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
|
||||
|
||||
Enter Tick Esc Done <> Order ? Help
|
||||
=== regions 40x15
|
||||
RetroBIOS: Preferred regions
|
||||
@@ -611,7 +611,8 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -619,13 +620,13 @@
|
||||
|
||||
|
||||
|
||||
|
||||
Enter Tick Esc Done <> Order ? Help
|
||||
=== regions 80x24
|
||||
RetroBIOS: Preferred regions
|
||||
|
||||
Tick the regions to keep, best first. Where a system has one BIOS per region,
|
||||
the best one found is installed.
|
||||
the best one found is installed. With none ticked, every region's BIOS is
|
||||
kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -644,43 +645,45 @@
|
||||
|
||||
|
||||
|
||||
|
||||
Enter Tick Esc Done Left/Right Order ? Help
|
||||
=== cores 40x12
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
|
||||
> Filter (/ to type)
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
> All
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
Enter Filter Esc Back Space Tick
|
||||
Enter Tick all Esc Back Space Tick
|
||||
=== cores 40x15
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
|
||||
> Filter (/ to type)
|
||||
> All
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Enter Filter Esc Back Space Tick
|
||||
Enter Tick all Esc Back Space Tick
|
||||
=== cores 80x24
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's files. Untick the cores you do not use:
|
||||
the platform's own files are always kept.
|
||||
|
||||
> Filter (/ to type)
|
||||
> All
|
||||
None
|
||||
Filter (/ to type)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
@@ -696,10 +699,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Enter Filter Esc Back Space Tick ? Help
|
||||
Enter Tick all Esc Back Space Tick ? Help
|
||||
=== preview 40x12
|
||||
RetroBIOS: Preview
|
||||
|
||||
|
||||
Vendored
+28
-28
@@ -652,12 +652,12 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
|
||||
|
||||
A Tick R2 Done <> Order
|
||||
=== regions 40x15
|
||||
RetroBIOS: Preferred regions
|
||||
@@ -665,7 +665,8 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -673,13 +674,13 @@
|
||||
|
||||
|
||||
|
||||
|
||||
A Tick R2 Done <> Order
|
||||
=== regions 80x24
|
||||
RetroBIOS: Preferred regions
|
||||
|
||||
Tick the regions to keep, best first. Where a system has one BIOS per region,
|
||||
the best one found is installed.
|
||||
the best one found is installed. With none ticked, every region's BIOS is
|
||||
kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -698,43 +699,45 @@
|
||||
|
||||
|
||||
|
||||
|
||||
A Tick R2 Done Left/Right Order
|
||||
=== cores 40x12
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
A Filter R2 Back
|
||||
A Tick all R2 Back
|
||||
=== cores 40x15
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Filter R2 Back
|
||||
A Tick all R2 Back
|
||||
=== cores 80x24
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's files. Untick the cores you do not use:
|
||||
the platform's own files are always kept.
|
||||
|
||||
> Filter (with a keyboard)
|
||||
> All
|
||||
None
|
||||
Filter (with a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
@@ -750,10 +753,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
A Filter R2 Back
|
||||
A Tick all R2 Back
|
||||
=== preview 80x24
|
||||
RetroBIOS: Preview
|
||||
|
||||
|
||||
Vendored
+28
-28
@@ -652,12 +652,12 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
|
||||
|
||||
Start Tick B Done <> Order
|
||||
=== regions 40x15
|
||||
RetroBIOS: Preferred regions
|
||||
@@ -665,7 +665,8 @@
|
||||
Tick the regions to keep, best first.
|
||||
Where a system has one BIOS per
|
||||
region, the best one found is
|
||||
installed.
|
||||
installed. With none ticked, every
|
||||
region's BIOS is kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -673,13 +674,13 @@
|
||||
|
||||
|
||||
|
||||
|
||||
Start Tick B Done <> Order
|
||||
=== regions 80x24
|
||||
RetroBIOS: Preferred regions
|
||||
|
||||
Tick the regions to keep, best first. Where a system has one BIOS per region,
|
||||
the best one found is installed.
|
||||
the best one found is installed. With none ticked, every region's BIOS is
|
||||
kept.
|
||||
|
||||
> [1] North America
|
||||
[ ] Japan
|
||||
@@ -698,43 +699,45 @@
|
||||
|
||||
|
||||
|
||||
|
||||
Start Tick B Done Left/Right Order
|
||||
=== cores 40x12
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
|
||||
> Filter (Select shows a keyboard)
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
> All
|
||||
None
|
||||
Filter (Select shows a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
Start Filter B Back Y Tick
|
||||
Start Tick all B Back Y Tick
|
||||
=== cores 40x15
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none
|
||||
ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's
|
||||
files. Untick the cores you do not
|
||||
use: the platform's own files are
|
||||
always kept.
|
||||
|
||||
> Filter (Select shows a keyboard)
|
||||
> All
|
||||
None
|
||||
Filter (Select shows a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Start Filter B Back Y Tick
|
||||
Start Tick all B Back Y Tick
|
||||
=== cores 80x24
|
||||
RetroBIOS: Cores
|
||||
|
||||
Tick the cores you use. With none ticked, every core's files are kept.
|
||||
Every core ticked keeps every core's files. Untick the cores you do not use:
|
||||
the platform's own files are always kept.
|
||||
|
||||
> Filter (Select shows a keyboard)
|
||||
> All
|
||||
None
|
||||
Filter (Select shows a keyboard)
|
||||
[ ] mesen
|
||||
[x] pcsx_rearmed
|
||||
|
||||
@@ -750,10 +753,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Start Filter B Back Y Tick
|
||||
Start Tick all B Back Y Tick
|
||||
=== preview 40x12
|
||||
RetroBIOS: Preview
|
||||
|
||||
|
||||
@@ -133,11 +133,14 @@ class InstallerOutputExample(unittest.TestCase):
|
||||
text = _page("installer.md")
|
||||
run = _generated(text, "dry-run")
|
||||
manifest = json.loads((ROOT / "install" / "retroarch.json").read_text(encoding="utf-8"))
|
||||
omitted = re.search(r"Not installable: \d+ files? \(\d+ required, (.*)\)\.", run)
|
||||
# The line as the installer writes it (not_installable_words), or
|
||||
# its earlier "(1 required, not found: 37)" form.
|
||||
omitted = re.search(r"Not installable: \d+ files? (?:\(\d+ required, (.*)\)\.|(?:is|are) "
|
||||
r"not in the collection|.*Why: (.*)\.)", run)
|
||||
self.assertEqual(omitted is not None, bool(manifest.get("omitted_files")))
|
||||
if omitted:
|
||||
for part in omitted.group(1).split(", "):
|
||||
self.assertIn(part.rsplit(":", 1)[0], install.OMISSION_REASONS.values())
|
||||
if omitted and (omitted.group(1) or omitted.group(2)):
|
||||
for part in (omitted.group(1) or omitted.group(2)).split(", "):
|
||||
self.assertIn(re.split(r":| \(", part)[0], install.OMISSION_REASONS.values())
|
||||
count, size = re.search(r"\n (\d+) files \(([\d.]+ [KMG]B)\)", run).groups()
|
||||
self.assertIn(f"0 in place, {count} missing", run)
|
||||
self.assertSplitAddsUp(run, count, size)
|
||||
|
||||
+21
-1
@@ -1806,7 +1806,27 @@ class TestDetectedPlatformPrompt(unittest.TestCase):
|
||||
|
||||
|
||||
class TestManualPlatformPrompt(unittest.TestCase):
|
||||
"""With nothing detected, an interactive run asks instead of exiting."""
|
||||
"""With nothing detected, an interactive run asks instead of exiting.
|
||||
|
||||
Every test runs on no drive and a home of its own: two read the host's
|
||||
drives and home, and failed with a card in the reader (code_audit_23
|
||||
P3-7)."""
|
||||
|
||||
def setUp(self):
|
||||
home = Path(_tempdir(self))
|
||||
for patcher in (unittest.mock.patch.object(install, "_mounted_cards", return_value=[]),
|
||||
unittest.mock.patch.object(install, "_mount_points",
|
||||
return_value=frozenset()),
|
||||
unittest.mock.patch.object(install.Path, "home", return_value=home),
|
||||
unittest.mock.patch.dict(os.environ, {"HOME": str(home)}),
|
||||
unittest.mock.patch("sys.stdout", io.StringIO())):
|
||||
patcher.start()
|
||||
self.addCleanup(patcher.stop)
|
||||
|
||||
def test_the_host_is_not_read(self):
|
||||
self.assertEqual(install._mounted_cards(), [])
|
||||
self.assertEqual(install._default_dest("linux", "retroarch"),
|
||||
Path.home() / ".config" / "retroarch" / "system")
|
||||
|
||||
def test_number_picks_the_platform_and_default_directory(self):
|
||||
answers = iter(["1", ""])
|
||||
|
||||
@@ -148,7 +148,7 @@ class CopyFromAnOldCard(FromFolder):
|
||||
proc = self.install()
|
||||
self.assertEqual(proc.returncode, 1, proc.stdout + proc.stderr)
|
||||
self.assertEqual(self.installed(), {"scph5500.bin": JP, "pcsx/extra.bin": EXTRA})
|
||||
self.assertIn(f"2 files copied from {self.old}, 2 still missing.", proc.stdout)
|
||||
self.assertIn(f"2 files copied from {self.old}, 2 failed.", proc.stdout)
|
||||
|
||||
def test_a_link_out_of_the_folder_is_not_followed(self):
|
||||
outside = self.root / "elsewhere"
|
||||
@@ -196,7 +196,7 @@ class CopyFromAnOldCard(FromFolder):
|
||||
(repo.root / "bios" / "mgba_extra.bin").unlink()
|
||||
proc = repo.run("--from", str(old), "--no-input")
|
||||
self.assertEqual(proc.returncode, 1, proc.stdout + proc.stderr)
|
||||
self.assertIn(f"2 files copied from {old}, 2 downloaded, 1 still missing.",
|
||||
self.assertIn(f"2 files copied from {old}, 2 downloaded, 1 failed.",
|
||||
proc.stdout)
|
||||
self.assertEqual(sorted(repo.installed()), sorted(
|
||||
name for name in payloads if name != "mgba/extra.bin"))
|
||||
|
||||
@@ -234,15 +234,17 @@ class CheckNamesWhyAFileIsRefused(Scratch):
|
||||
self.complete("scph5501.bin", "pcsx/extra.bin")
|
||||
out = self.check()
|
||||
here = self.dest.resolve()
|
||||
self.assertIn(f"opened at {here / 'scph5501.bin'} by beetle_psx, pcsx_rearmed", out)
|
||||
self.assertIn(f"opened at {here / 'pcsx' / 'extra.bin'} by beetle_psx, pcsx_rearmed",
|
||||
self.assertIn(f"read by beetle_psx, pcsx_rearmed at {here / 'scph5501.bin'}", out)
|
||||
self.assertIn(f"read by beetle_psx, pcsx_rearmed at {here / 'pcsx' / 'extra.bin'}",
|
||||
out)
|
||||
# Never "opened" of a file that is not there (tui_audit_16 P3-12).
|
||||
self.assertNotIn("opened at", out)
|
||||
|
||||
def test_a_complete_folder_says_nothing_more(self):
|
||||
self.complete()
|
||||
proc = self.run_installer("--check", "--manifest", str(self.list))
|
||||
self.assertEqual(proc.returncode, 0, proc.stdout + proc.stderr)
|
||||
self.assertNotIn("opened at", proc.stdout)
|
||||
self.assertNotIn("read by", proc.stdout)
|
||||
|
||||
|
||||
class ArchivesInTheBiosFolder(Scratch):
|
||||
@@ -845,7 +847,7 @@ class OfflineLeavesFilesMissing(Scratch):
|
||||
proc = self.run_installer("--offline", "--manifest", str(self.list), "--no-input")
|
||||
# Its files are missing, as the BIOS files --offline leaves out are,
|
||||
# with or without questions.
|
||||
self.assertIn("bluemsx: 0 already in place, 1 need the internet (--offline)",
|
||||
self.assertIn("bluemsx: 0 already in place, 1 needs the internet (--offline)",
|
||||
proc.stdout)
|
||||
self.assertNotIn("could not read", proc.stderr)
|
||||
self.assertNotIn("no longer in the source", proc.stdout)
|
||||
|
||||
+710
-46
@@ -527,18 +527,20 @@ class Flow(unittest.TestCase):
|
||||
state.focus["options"] = 3
|
||||
press(state, "enter")
|
||||
self.assertEqual(state.screen, "cores")
|
||||
self.assertEqual([row.value for row in install.tui_rows(state)][1:],
|
||||
self.assertEqual([row.value for row in install.tui_rows(state)][3:],
|
||||
["mesen", "pcsx_rearmed"])
|
||||
self.assertEqual(install.tui_rows(state)[state.focus["cores"]].value, "mesen")
|
||||
# Every core ticked while none narrows the run: one untick keeps
|
||||
# the others, ticked back it is every core again.
|
||||
press(state, " ")
|
||||
self.assertEqual(state.cores, ["mesen"])
|
||||
press(state, "left")
|
||||
self.assertEqual(state.cores, ["pcsx_rearmed"])
|
||||
press(state, "right")
|
||||
self.assertEqual(state.cores, [])
|
||||
press(state, "/", "p", "c")
|
||||
self.assertEqual([row.value for row in install.tui_rows(state)][1:], ["pcsx_rearmed"])
|
||||
press(state, "enter", "right", "enter")
|
||||
self.assertEqual([row.value for row in install.tui_rows(state)][3:], ["pcsx_rearmed"])
|
||||
press(state, "enter", "left", "enter")
|
||||
self.assertEqual(state.screen, "options")
|
||||
self.assertEqual(install.tui_flags(state), [("--core", "pcsx_rearmed")])
|
||||
self.assertEqual(install.tui_flags(state), [("--core", "mesen")])
|
||||
|
||||
def test_preview_is_a_dry_run(self):
|
||||
state = checked_state()
|
||||
@@ -2537,10 +2539,11 @@ class AuditRoundThree(unittest.TestCase):
|
||||
state.summary = {"installed": 4, "up_to_date": 0, "failed": [
|
||||
{"dest": "fc/disksys.rom", "reason": "HTTP 404"}]}
|
||||
_title, lines = install.tui_outcome(state)
|
||||
self.assertEqual(lines[1], "2 files copied from OLD, 1 copied from the wrong place "
|
||||
"in the BIOS folder, 1 downloaded, 1 still missing.")
|
||||
# One count, the failed file said as failed (tui_audit_16 P3-11).
|
||||
self.assertEqual(lines[0], "2 files copied from OLD, 1 copied from the wrong place "
|
||||
"in the BIOS folder, 1 downloaded, 1 failed.")
|
||||
# The line mode's own sentence, from the same counts.
|
||||
self.assertEqual(lines[1], install.sources_line([("OLD", 2)], 1, 1, 1))
|
||||
self.assertEqual(lines[0], install.sources_line([("OLD", 2)], 1, 1, 0, failed=1))
|
||||
|
||||
def test_p2_3_a_run_that_copied_nothing_adds_no_line(self):
|
||||
state = install.TuiState()
|
||||
@@ -5100,9 +5103,13 @@ class EndToEnd(unittest.TestCase):
|
||||
term = self.start()
|
||||
term.wait("Enter for RetroArch")
|
||||
term.send("\r")
|
||||
term.wait("Enter) install everything")
|
||||
term.send("\r")
|
||||
# Installed by the first run, in place for the second.
|
||||
if value is None:
|
||||
# In place since the first run: no menu, nothing asked
|
||||
# (tui_audit_16 P3-4).
|
||||
term.wait("every one in place: nothing to install")
|
||||
else:
|
||||
term.wait("Enter) install everything")
|
||||
term.send("\r")
|
||||
term.wait("Done.")
|
||||
term.close()
|
||||
self.assertNotIn(b"\x1b", term.raw)
|
||||
@@ -6411,7 +6418,11 @@ class AuditSevenOneCardReading(unittest.TestCase):
|
||||
stick = self.blank(f"{name}STICK")
|
||||
choice = install.card_choice(plat, plat, stick)
|
||||
self.assertEqual(choice.folder, stick)
|
||||
self.assertIn("cannot tell", choice.note)
|
||||
# Its card is told by what it writes at every boot: a stick
|
||||
# holding none of it is one not started yet, never "cannot
|
||||
# tell" (tui_audit_16 P2-1).
|
||||
self.assertIn(f"says it is {install._a(name)} card yet", choice.note)
|
||||
self.assertNotIn("cannot tell", choice.note)
|
||||
|
||||
def test_install_py_has_two_blank_lines_around_each_definition(self):
|
||||
"""code_audit_14 P3-12: E305 after _card_mount, and the same slip
|
||||
@@ -7438,8 +7449,9 @@ class LineModeAndScreenDecideAlike(_LineModeFindings, _OutsideTextFindings,
|
||||
self.assertRaises(SystemExit):
|
||||
install.ask_platform_folder("linux", "retroarch")
|
||||
text = out.getvalue()
|
||||
self.assertIn(f"1) EASYROMS: bios (card or drive) ({stick / 'bios'})", text)
|
||||
self.assertIn(f"2) ONION: BIOS (Onion SD card) ({onion / 'BIOS'})", text)
|
||||
# One parenthesis a row (tui_audit_16 P3-9).
|
||||
self.assertIn(f"1) EASYROMS: bios (drive, {stick / 'bios'})", text)
|
||||
self.assertIn(f"2) ONION: BIOS (Onion SD card, {onion / 'BIOS'})", text)
|
||||
self.assertNotIn("3)", text)
|
||||
self.assertIn("Not offered here, each reads its own system's files: SHARE (Batocera "
|
||||
f"SHARE drive: --platform batocera --dest {share}), KNULLI (KNULLI SD "
|
||||
@@ -8259,7 +8271,9 @@ class LineModeAndScreenDecideAlike(_LineModeFindings, _OutsideTextFindings,
|
||||
found here.\""""
|
||||
text, _asked = self.line_run(_args(declared_only=False), [])
|
||||
self.assertIn("Looking for setups here...", text)
|
||||
self.assertIn("Nothing was found here. Which setup?", text)
|
||||
# Said once, the question alone after it (tui_audit_16 P3-2).
|
||||
self.assertEqual(text.count("Nothing was found here."), 1)
|
||||
self.assertIn("\nWhich setup?\n", text)
|
||||
self.assertNotIn("Detecting platform", text)
|
||||
self.assertNotIn("No supported platform", text)
|
||||
state = install.TuiState(os_type="linux", home=HOME)
|
||||
@@ -9866,6 +9880,7 @@ class AuditEighteenAndEleven(_CardFixtures, unittest.TestCase):
|
||||
"""P3-11."""
|
||||
state = checked_state()
|
||||
state.cli_systems, state.cores, state.regions = ["sony-playstation"], ["x"], ["us"]
|
||||
state.cli_cores = ["x"]
|
||||
text = " ".join(" ".join(install.tui_view(state, 120, 40)).split())
|
||||
self.assertIn("(--system), --core, --region.", text)
|
||||
|
||||
@@ -11633,7 +11648,10 @@ class AuditTwentyAndThirteen(unittest.TestCase):
|
||||
with mock.patch.dict(os.environ, {install.OFFLINE_VARIABLE:
|
||||
install.OFFLINE_FLAG_VALUE}):
|
||||
_title, lines = install.tui_outcome(state)
|
||||
self.assertIn("Still missing: 2 BIOS files and 1 game data file.", lines)
|
||||
# The wrong copy the check found is left in place: named as one,
|
||||
# never counted as missing (code_audit_23 P3-3).
|
||||
self.assertIn("1 file copied from OLD, 2 still missing, 1 wrong copy left.", lines)
|
||||
self.assertIn("Still missing: 1 BIOS file and 1 game data file.", lines)
|
||||
|
||||
# Root cause 6: every other word.
|
||||
|
||||
@@ -12278,15 +12296,16 @@ class AuditTwentyOneAndFourteen(unittest.TestCase):
|
||||
|
||||
def easyroms(self, name: str = "EASYROMS") -> Path:
|
||||
"""A handheld's games part as a computer mounts it, with the folders
|
||||
its system writes there (install._GAMES_PART_MARKERS): ArkOS's
|
||||
its system writes there (install._GAMES_PART_RULES): ArkOS's
|
||||
EASYROMS, AmberELEC's GAMES."""
|
||||
return games_part(self.root / "media" / name)
|
||||
|
||||
def test_an_arkos_card_is_found_and_comes_first(self):
|
||||
"""tui_audit_14 P2-3: an EASYROMS partition mounted, "Nothing was
|
||||
found here", and two presses of Enter filled this computer's
|
||||
~/.config/retroarch/system for a RetroArch that was not there."""
|
||||
for name in ("EASYROMS", "GAMES"):
|
||||
~/.config/retroarch/system for a RetroArch that was not there. An
|
||||
AmberELEC GAMES is AmberELEC's own card (tui_audit_16 P2-1)."""
|
||||
for name in ("EASYROMS",):
|
||||
with self.subTest(card=name):
|
||||
card = self.easyroms(name)
|
||||
home = self.root / "home"
|
||||
@@ -12562,15 +12581,14 @@ class AuditTwentyOneAndFourteen(unittest.TestCase):
|
||||
text = out.getvalue()
|
||||
self.assertNotIn(", created)", text)
|
||||
self.assertNotIn("(created)", text)
|
||||
self.assertIn(f"D: bios (card or drive) ({drives[0] / 'bios'}, does not exist yet)", text)
|
||||
self.assertIn(f"E: bios (card or drive) ({drives[1] / 'bios'})\n", text)
|
||||
self.assertIn(f"D: bios (drive, {drives[0] / 'bios'}, does not exist yet)", text)
|
||||
self.assertIn(f"E: bios (drive, {drives[1] / 'bios'})\n", text)
|
||||
state = fresh_state()
|
||||
state.platform = "retroarch"
|
||||
with mock.patch.object(install, "_mounted_cards", return_value=drives):
|
||||
install._open_folder_screen(state, SYSTEM_DIR)
|
||||
labels = [row.label for row in install.tui_rows(state) if row.action == "drive"]
|
||||
self.assertEqual(labels, ["D: bios (card or drive) (does not exist yet)",
|
||||
"E: bios (card or drive)"])
|
||||
self.assertEqual(labels, ["D: bios (drive, does not exist yet)", "E: bios (drive)"])
|
||||
|
||||
def test_line_mode_puts_the_arkos_card_first(self):
|
||||
card = self.easyroms()
|
||||
@@ -12578,9 +12596,9 @@ class AuditTwentyOneAndFourteen(unittest.TestCase):
|
||||
declared_only=False), ["1", ""], mounts=[card])
|
||||
self.assertIn("A card is in the reader (EASYROMS): choose its system.", text)
|
||||
self.assertNotIn("Nothing was found here", text)
|
||||
self.assertIn(f"The card in the reader keeps them in its bios folder: {card / 'bios'}.",
|
||||
text)
|
||||
self.assertIn(f"1) EASYROMS: bios (card or drive) ({card / 'bios'})", text)
|
||||
self.assertIn(f"The card in the reader keeps BIOS files in its bios folder: "
|
||||
f"{card / 'bios'}.", text)
|
||||
self.assertIn(f"1) EASYROMS: bios (SD card, {card / 'bios'})", text)
|
||||
self.assertIn("Enter for the card's bios folder", asked[-2])
|
||||
self.assertIn(f"BIOS folder: {card / 'bios'}", text)
|
||||
|
||||
@@ -12643,20 +12661,26 @@ class AuditTwentyTwoAndFifteen(unittest.TestCase):
|
||||
self.assertIn("Nothing was found here", self.screen(state))
|
||||
state, text, rows = self.folder_screen(mounts)
|
||||
self.assertNotIn(rows[0].value, (data / "bios", stick / "bios"))
|
||||
self.assertIn("DATA, STICK have a bios folder, and nothing on them shows a "
|
||||
"handheld's card: listed, not chosen.", text)
|
||||
self.assertIn(self.UNPROVEN_TWO, text)
|
||||
self.assertIn(data / "bios", [row.value for row in rows])
|
||||
text, asked = self.line_run(_args(manifest=self.game_listing(), dry_run=True,
|
||||
declared_only=False), ["1", ""], mounts=mounts)
|
||||
self.assertNotIn("in the reader", text)
|
||||
self.assertIn("DATA, STICK have a bios folder, and nothing on them shows a "
|
||||
"handheld's card: listed, not chosen.", text)
|
||||
self.assertIn(self.UNPROVEN_TWO, text)
|
||||
self.assertIn("Enter for the default above", asked[-2])
|
||||
self.assertNotIn(f"BIOS folder: {data / 'bios'}", text)
|
||||
|
||||
# The note on drives with a bios folder and no handheld's folder.
|
||||
UNPROVEN_TWO = ("DATA and STICK have a bios folder but no folder a handheld system "
|
||||
"writes. Pick one below if your files go there.")
|
||||
UNPROVEN_ONE = ("DATA has a bios folder but no folder a handheld system writes. Pick "
|
||||
"it below if your files go there.")
|
||||
|
||||
def test_the_layouts_handhelds_write_are_cards(self):
|
||||
"""ArkOS's EASYROMS, AmberELEC's GAMES and EmuELEC's EEROMS, each
|
||||
with the folders its own image writes there."""
|
||||
with the folders its own image writes there. ArkOS's reads
|
||||
RetroArch's list, the two others are their systems' own cards
|
||||
(tui_audit_16 P2-1)."""
|
||||
arkos = games_part(self.root / "media" / "EASYROMS")
|
||||
amber = games_part(self.root / "media" / "GAMES")
|
||||
emuelec = self.drive("EEROMS", ("bios", "nes", "bezels"))
|
||||
@@ -12664,12 +12688,17 @@ class AuditTwentyTwoAndFifteen(unittest.TestCase):
|
||||
mounts = [arkos, amber, emuelec]
|
||||
with mock.patch.object(install, "_mounted_cards", return_value=mounts), \
|
||||
mock.patch.object(install, "_mount_points", return_value=frozenset()):
|
||||
self.assertEqual(install.unnamed_cards(), mounts)
|
||||
self.assertEqual([install._games_part_system(mount) for mount in mounts],
|
||||
self.assertEqual(install.unnamed_cards(), [arkos])
|
||||
self.assertEqual([install.games_part(mount).name for mount in mounts],
|
||||
["ArkOS", "AmberELEC", "EmuELEC"])
|
||||
self.assertEqual([install.card_system(mount) for mount in mounts],
|
||||
[None, ("amberelec", amber, "AmberELEC"),
|
||||
("emuelec", emuelec, "EmuELEC")])
|
||||
# One of these the system calls fixed is a disk, not a card.
|
||||
with mock.patch.object(install, "_drive_not_removable", return_value=True):
|
||||
self.assertEqual(install.unnamed_cards(), [])
|
||||
self.assertEqual([install.card_system(mount) for mount in mounts],
|
||||
[None, None, None])
|
||||
|
||||
def test_a_card_beside_a_data_drive_comes_first(self):
|
||||
"""code_audit_22 P2-1: the ArkOS card and the data drive mounted,
|
||||
@@ -12683,31 +12712,31 @@ class AuditTwentyTwoAndFifteen(unittest.TestCase):
|
||||
self.assertIn("A card is in the reader (EASYROMS): choose its system", self.screen(state))
|
||||
state, text, rows = self.folder_screen(mounts)
|
||||
self.assertEqual(rows[0].value, card / "bios")
|
||||
self.assertIn("DATA has a bios folder, and nothing on it shows a handheld's card", text)
|
||||
self.assertIn(self.UNPROVEN_ONE, text)
|
||||
text, asked = self.line_run(_args(manifest=self.game_listing(), dry_run=True,
|
||||
declared_only=False), ["1", ""], mounts=mounts)
|
||||
self.assertIn("A card is in the reader (EASYROMS): choose its system.", text)
|
||||
self.assertIn(f"The card in the reader keeps them in its bios folder: {card / 'bios'}.",
|
||||
text)
|
||||
self.assertIn(f"1) EASYROMS: bios (card or drive) ({card / 'bios'})", text)
|
||||
self.assertIn("DATA has a bios folder, and nothing on it shows a handheld's card", text)
|
||||
self.assertIn(f"The card in the reader keeps BIOS files in its bios folder: "
|
||||
f"{card / 'bios'}.", text)
|
||||
self.assertIn(f"1) EASYROMS: bios (SD card, {card / 'bios'})", text)
|
||||
self.assertIn(self.UNPROVEN_ONE, text)
|
||||
self.assertIn(f"BIOS folder: {card / 'bios'}", text)
|
||||
|
||||
def test_two_cards_are_spoken_of_in_the_plural(self):
|
||||
"""code_audit_22 P3-2: "Cards are in the reader (DATA, EASYROMS):
|
||||
choose its system", then "The card in the reader" of one of two."""
|
||||
arkos = games_part(self.root / "media" / "EASYROMS")
|
||||
amber = games_part(self.root / "media" / "GAMES")
|
||||
mounts = [arkos, amber]
|
||||
second = games_part(self.root / "media" / "ROMS2")
|
||||
mounts = [arkos, second]
|
||||
state = self.first_screen(mounts)
|
||||
self.assertIn("Cards are in the reader (EASYROMS, GAMES): choose their systems",
|
||||
self.assertIn("Cards are in the reader (EASYROMS, ROMS2): choose their systems",
|
||||
self.screen(state))
|
||||
state, text, rows = self.folder_screen(mounts)
|
||||
self.assertIn("EASYROMS keeps them in its bios folder, first below.", text)
|
||||
self.assertIn("EASYROMS keeps BIOS files in its bios folder, first below.", text)
|
||||
text, asked = self.line_run(_args(manifest=self.game_listing(), dry_run=True,
|
||||
declared_only=False), ["1", ""], mounts=mounts)
|
||||
self.assertIn("Cards are in the reader (EASYROMS, GAMES): choose their systems.", text)
|
||||
self.assertIn(f"EASYROMS keeps them in its bios folder: {arkos / 'bios'}.", text)
|
||||
self.assertIn("Cards are in the reader (EASYROMS, ROMS2): choose their systems.", text)
|
||||
self.assertIn(f"EASYROMS keeps BIOS files in its bios folder: {arkos / 'bios'}.", text)
|
||||
self.assertNotIn("The card in the reader", text)
|
||||
|
||||
def test_a_fixed_partition_is_told_from_a_card(self):
|
||||
@@ -13280,8 +13309,16 @@ class TheSystemsQuestionFits(unittest.TestCase):
|
||||
[f for f in files if install._chosen(f, {system})]))
|
||||
# One line a system, a second for its shared files: the
|
||||
# 80-column question took 127 lines for 66 systems.
|
||||
limit = len(systems) + shared + 10 if cols == 80 else 2 * len(systems) + 12
|
||||
# At 40 columns a shared size takes a line more: its first
|
||||
# part alone was printed beside a long name, the shared
|
||||
# files unsaid (tui_audit_16 P3-5).
|
||||
limit = (len(systems) + shared + 10 if cols == 80
|
||||
else 2 * len(systems) + shared + 12)
|
||||
self.assertLessEqual(len(lines), limit)
|
||||
for line, after in zip(lines, lines[1:] + [""]):
|
||||
if line.rstrip().endswith(","):
|
||||
self.assertTrue(after.startswith(" ") and not re.match(
|
||||
r" +\d+\) ", after), (cols, line, after))
|
||||
|
||||
def test_a_row_that_fits_keeps_one_line(self):
|
||||
lines, _systems, _files = self.question(80)
|
||||
@@ -13290,5 +13327,632 @@ class TheSystemsQuestionFits(unittest.TestCase):
|
||||
self.assertTrue(re.match(r" +\d+\) ", lines[row + 1]))
|
||||
|
||||
|
||||
class AuditTwentyThreeAndSixteen(unittest.TestCase):
|
||||
"""code_audit_23 and tui_audit_16: a card its markers prove is that
|
||||
system's card everywhere, counts and states that tell the truth, one
|
||||
width for every layout, line mode's order and words as the screen's,
|
||||
and a tap that shows it was seen."""
|
||||
|
||||
setUp = LineModeAndScreenDecideAlike.setUp
|
||||
line_run = LineModeAndScreenDecideAlike.line_run
|
||||
listing = LineModeAndScreenDecideAlike.listing
|
||||
entry = staticmethod(LineModeAndScreenDecideAlike.entry)
|
||||
both = LineModeAndScreenDecideAlike.both
|
||||
drive = AuditTwentyTwoAndFifteen.drive
|
||||
first_screen = AuditTwentyTwoAndFifteen.first_screen
|
||||
folder_screen = AuditTwentyTwoAndFifteen.folder_screen
|
||||
game_listing = AuditTwentyOneAndFourteen.game_listing
|
||||
game_manifest = AuditTwentyAndThirteen.game_manifest
|
||||
receive = staticmethod(AuditTwentyAndThirteen.receive)
|
||||
screen = staticmethod(AuditTwentyOneAndFourteen.screen)
|
||||
|
||||
def amberelec(self, name: str = "GAMES") -> Path:
|
||||
return games_part(self.root / "media" / name)
|
||||
|
||||
def emuelec(self, name: str = "EEROMS") -> Path:
|
||||
card = self.drive(name, ("bios", "nes", "bezels"))
|
||||
(card / "bezels" / "default.cfg").write_text("")
|
||||
return card
|
||||
|
||||
def line_from(self, args: argparse.Namespace, answers: list,
|
||||
folders: list[Path] = ()) -> tuple[str, list]:
|
||||
"""(text, prompts) of line mode at a terminal, the result included,
|
||||
the folders --from names read first, as main() reads them."""
|
||||
given, asked = iter(answers), []
|
||||
|
||||
def answer(prompt: str) -> str:
|
||||
asked.append(prompt)
|
||||
try:
|
||||
return next(given)
|
||||
except StopIteration:
|
||||
raise _Decided(prompt) from None
|
||||
|
||||
install.LOCAL.reset()
|
||||
self.addCleanup(install.LOCAL.reset)
|
||||
if folders:
|
||||
setattr(args, "from", [str(folder) for folder in folders])
|
||||
invocation = install.Invocation()
|
||||
invocation.os_type = "linux"
|
||||
invocation.record(args)
|
||||
stream = io.StringIO()
|
||||
with mock.patch.object(install, "_INVOCATION", invocation), \
|
||||
mock.patch.object(install, "_mounted_cards", return_value=[]), \
|
||||
mock.patch.object(install, "_mount_points", return_value=frozenset()), \
|
||||
mock.patch.object(install, "detect_platforms", return_value=[]), \
|
||||
mock.patch.object(install, "detect_frontends", return_value=[]), \
|
||||
mock.patch.object(install, "detect_os", return_value="linux"), \
|
||||
mock.patch.object(install.sys.stdin, "isatty", return_value=True), \
|
||||
mock.patch.object(install, "_is_terminal", return_value=True), \
|
||||
mock.patch.object(install, "_ask", side_effect=answer), \
|
||||
contextlib.redirect_stdout(io.StringIO()) as out, \
|
||||
contextlib.redirect_stderr(io.StringIO()) as err, \
|
||||
contextlib.suppress(_Decided, SystemExit):
|
||||
install._install(args, stream)
|
||||
return out.getvalue() + err.getvalue() + stream.getvalue(), asked
|
||||
|
||||
# Root cause 1: a card its markers prove is that system's card.
|
||||
|
||||
def test_a_games_part_is_its_systems_card_in_both_modes(self):
|
||||
"""tui_audit_16 P2-1: the GAMES card AmberELEC's folders prove, and
|
||||
the EEROMS card EmuELEC's prove, read "A card is in the reader:
|
||||
choose its system" with RetroArch focused, and two presses of Enter
|
||||
put RetroArch's list on them."""
|
||||
for plat, name, make in (("amberelec", "AmberELEC", self.amberelec),
|
||||
("emuelec", "EmuELEC", self.emuelec)):
|
||||
with self.subTest(system=name):
|
||||
card = make()
|
||||
state = self.first_screen([card])
|
||||
text = self.screen(state)
|
||||
self.assertIn(f"{name} SD card ({card.name})", text)
|
||||
self.assertNotIn("in the reader", text)
|
||||
self.assertIn(f"BIOSfolder:{card / 'bios'}", "".join(text.split()))
|
||||
(line, screen, said) = self.both([card], [])
|
||||
self.assertEqual(line, (plat, card))
|
||||
self.assertEqual(screen, (plat, card))
|
||||
self.assertIn(f"Found {name}", said)
|
||||
shutil.rmtree(card)
|
||||
|
||||
def test_their_own_routes_take_the_card_they_prove(self):
|
||||
"""tui_audit_16 P2-1: --platform amberelec said it "cannot tell an
|
||||
AmberELEC card by its files" of the card holding gamedata/ and
|
||||
homebrew/, and line mode offered no Enter for it."""
|
||||
for plat, name, make in (("amberelec", "AmberELEC", self.amberelec),
|
||||
("emuelec", "EmuELEC", self.emuelec)):
|
||||
with self.subTest(system=name):
|
||||
card = make()
|
||||
stick = self.drive(f"{name}STICK", ("bios",))
|
||||
with mock.patch.object(install, "_mounted_cards", return_value=[card, stick]), \
|
||||
mock.patch.object(install, "_mount_points", return_value=frozenset()):
|
||||
self.assertEqual(install.mounted_cards_of(name, plat), [card])
|
||||
self.assertEqual(install.blank_cards_of(name, plat), [stick])
|
||||
choice = install.card_choice(name, plat, card)
|
||||
self.assertEqual((choice.refused, choice.folder), ("", card))
|
||||
self.assertNotIn("cannot tell", choice.note)
|
||||
(line, screen, said) = self.both([card, stick], [], platform=plat)
|
||||
self.assertEqual(line, (plat, card))
|
||||
self.assertEqual(screen, (plat, card))
|
||||
self.assertIn(f"Found {name} at {card / 'bios'}", said)
|
||||
self.assertNotIn("cannot tell", said)
|
||||
# Asked for its card, the one its files prove is offered.
|
||||
with mock.patch.object(install, "_mounted_cards", return_value=[card, stick]), \
|
||||
mock.patch.object(install, "_mount_points", return_value=frozenset()), \
|
||||
contextlib.redirect_stdout(io.StringIO()) as out:
|
||||
dest = install.card_install_dest(name, plat, True, False)
|
||||
self.assertEqual(dest, card)
|
||||
self.assertIn(f"{name} card found at {card.name}", out.getvalue())
|
||||
with mock.patch.object(install, "_mounted_cards", return_value=[card, stick]), \
|
||||
mock.patch.object(install, "_mount_points", return_value=frozenset()):
|
||||
state = screen_keys(_args(platform=plat, declared_only=False), [])
|
||||
view = " ".join(install.tui_view(state, 80, 24))
|
||||
self.assertNotIn("cannot tell", view)
|
||||
shutil.rmtree(card)
|
||||
shutil.rmtree(stick)
|
||||
|
||||
def test_an_arkos_card_from_any_year_is_a_card(self):
|
||||
"""code_audit_23 P3-1: ArkOS's default trees of 2020 hold no themes/
|
||||
(9664c869 none of themes and launchimages, 495eb210 and c14afbe5
|
||||
launchimages only), and the 12262020 update skipped the themes of a
|
||||
card with under 1 GB free. Every tree holds bgmusic/. A data drive
|
||||
holding neither stays no card."""
|
||||
layouts = {
|
||||
"ARK_9664c869": ("bios", "bgmusic", "ports", "snes", "System Volume Information"),
|
||||
"ARK_495eb210": ("bios", "bgmusic", "launchimages", "ports", "snes"),
|
||||
"ARK_c14afbe5": ("bios", "bgmusic", "launchimages", "psx"),
|
||||
"ARK_f41b9485": ("bios", "bgmusic", "launchimages", "themes", "backup", "nes"),
|
||||
"ARK_FULL1226": ("bios", "launchimages", "nes"),
|
||||
}
|
||||
cards = [self.drive(name, folders) for name, folders in layouts.items()]
|
||||
data = self.drive("DATA", ("bios", "snes", "Music", "themes"))
|
||||
music = self.drive("MUSIC", ("bgmusic", "launchimages"))
|
||||
mounts = [*cards, data, music]
|
||||
with mock.patch.object(install, "_mounted_cards", return_value=mounts), \
|
||||
mock.patch.object(install, "_mount_points", return_value=frozenset()):
|
||||
self.assertEqual(install.unnamed_cards(), cards)
|
||||
self.assertEqual([install.games_part(card).name for card in cards],
|
||||
["ArkOS"] * len(cards))
|
||||
self.assertIsNone(install.games_part(data))
|
||||
self.assertIsNone(install.games_part(music))
|
||||
self.assertEqual(install.unproven_drives(), [data])
|
||||
with mock.patch.object(install, "_drive_not_removable", return_value=True):
|
||||
self.assertEqual(install.unnamed_cards(), [])
|
||||
|
||||
# Root cause 2: counts and states that tell the truth.
|
||||
|
||||
def wrong_copy_run(self, answers: list) -> tuple[str, list, Path]:
|
||||
"""An offline run whose BIOS folder holds a wrong copy of the right
|
||||
size of a.bin, a folder named with --from holding b.bin."""
|
||||
good_a, good_b = b"A" * 64, b"B" * 64
|
||||
listing = self.listing("retroarch", [self.entry("a.bin", good_a, ["nintendo-gba"]),
|
||||
self.entry("b.bin", good_b, ["nintendo-gba"])])
|
||||
dest = self.root / "dest"
|
||||
dest.mkdir()
|
||||
(dest / "a.bin").write_bytes(b"Z" * 64)
|
||||
old = self.root / "old"
|
||||
old.mkdir()
|
||||
(old / "b.bin").write_bytes(good_b)
|
||||
with mock.patch.dict(os.environ, {install.OFFLINE_VARIABLE: "1"}):
|
||||
text, asked = self.line_from(_args(manifest=listing, dest=dest, platform="retroarch",
|
||||
declared_only=False), answers, [old])
|
||||
return text, asked, dest
|
||||
|
||||
def test_the_head_never_calls_a_wrong_copy_in_place(self):
|
||||
"""code_audit_23 P3-2: a wrong copy of the right size was in place
|
||||
for the head, which said "1 found in old, nothing to download" over
|
||||
a run that left it."""
|
||||
text, _asked, dest = self.wrong_copy_run([""])
|
||||
self.assertIn("RetroArch: 1 found in old, 1 needs the internet.", text)
|
||||
self.assertNotIn("nothing to download", text)
|
||||
self.assertEqual((dest / "a.bin").read_bytes(), b"Z" * 64)
|
||||
|
||||
def test_a_wrong_copy_left_is_said_as_one(self):
|
||||
"""code_audit_23 P3-3: the result said "1 still missing" of a file
|
||||
--check counts as a wrong copy."""
|
||||
text, _asked, _dest = self.wrong_copy_run([""])
|
||||
self.assertIn("Finished with files missing.", text)
|
||||
self.assertIn("1 file copied from", text)
|
||||
self.assertIn(", 1 wrong copy left.", text)
|
||||
self.assertNotIn("still missing", text.rsplit("Finished", 1)[1])
|
||||
|
||||
def test_a_count_agrees_with_its_verb(self):
|
||||
"""code_audit_23 P3-4: "1 need the internet" on the plan, and on
|
||||
line mode's data tree line."""
|
||||
self.assertEqual(install.agree(1, "needs", "need"), "1 needs")
|
||||
self.assertEqual(install.agree(2, "needs", "need"), "2 need")
|
||||
self.assertEqual(install._plural(2, "wrong copy"), "2 wrong copies")
|
||||
self.assertEqual(install._plural(1, "wrong copy"), "1 wrong copy")
|
||||
self.assertEqual(install._plural(2, "day"), "2 days")
|
||||
state = checked_state()
|
||||
folder = "/media/OLD"
|
||||
state.from_folders = [Path(folder)]
|
||||
state.found = [found(dest, folder) for dest in ("scph5500.bin", "pcsx/extra.bin",
|
||||
"gba_bios.bin")]
|
||||
with mock.patch.dict(os.environ, {install.OFFLINE_VARIABLE: "1"}):
|
||||
text = self.screen(state, 100, 30)
|
||||
self.assertIn("3 found in OLD, 1 needs the internet", text)
|
||||
source = (REPO_ROOT / "install.py").read_text(encoding="utf-8")
|
||||
self.assertNotRegex(source, r"\} need the internet")
|
||||
|
||||
def test_line_mode_says_what_is_still_missing_before_the_remedy(self):
|
||||
"""tui_audit_16 P3-3: "They are not in OLD" followed "Installed: 6
|
||||
BIOS files", where the screen puts "Still missing:" between them."""
|
||||
bios, game = b"B" * 32, b"G" * 32
|
||||
listing = self.listing("retroarch", [
|
||||
self.entry("a.bin", bios, ["nintendo-gba"]),
|
||||
self.entry("b.bin", b"C" * 32, ["nintendo-gba"]),
|
||||
self.entry("g.dat", game, ["sega-dreamcast"], category="game_data")],
|
||||
categorized=True)
|
||||
dest = self.root / "dest"
|
||||
dest.mkdir()
|
||||
old = self.root / "OLD"
|
||||
old.mkdir()
|
||||
(old / "a.bin").write_bytes(bios)
|
||||
with mock.patch.dict(os.environ, {install.OFFLINE_VARIABLE: "1"}):
|
||||
text, _asked = self.line_from(_args(manifest=listing, dest=dest,
|
||||
platform="retroarch", declared_only=False),
|
||||
[""], [old])
|
||||
end = text.rsplit("Finished with files missing", 1)[-1]
|
||||
self.assertIn("Still missing: 1 BIOS file and 1 game data file.", end)
|
||||
self.assertLess(end.index("Still missing:"), end.index(f"They are not in {old}"))
|
||||
self.assertLess(end.index("Installed:"), end.index("Still missing:"))
|
||||
|
||||
def test_a_rerun_with_everything_in_place_offers_nothing(self):
|
||||
"""tui_audit_16 P3-4: line mode offered "Enter) install what is
|
||||
found", then said "Everything is in place." twice."""
|
||||
data = b"A" * 64
|
||||
listing = self.listing("retroarch", [self.entry("a.bin", data, ["nintendo-gba"])])
|
||||
dest = self.root / "dest"
|
||||
dest.mkdir()
|
||||
(dest / "a.bin").write_bytes(data)
|
||||
text, asked = self.line_from(_args(manifest=listing, dest=dest, platform="retroarch",
|
||||
declared_only=False), [])
|
||||
self.assertEqual(asked, [])
|
||||
self.assertNotIn("Enter)", text)
|
||||
self.assertIn("RetroArch: 1 file, every one in place: nothing to install.", text)
|
||||
self.assertEqual(text.count(install.EVERYTHING_IN_PLACE), 1)
|
||||
|
||||
def test_line_mode_names_the_files_it_cannot_supply(self):
|
||||
"""tui_audit_16 P3-6: "Not installable: 37 files (1 required, not
|
||||
found: 37)" read as a sum, and line mode never named the file the
|
||||
screen names, nor its folder."""
|
||||
listing = self.listing("retroarch", [
|
||||
self.entry("a.bin", b"A" * 8, ["nintendo-gba"])], categorized=True,
|
||||
omitted_files=[
|
||||
{"dest": "jazz2/Source/Anims.j2a", "name": "Anims.j2a",
|
||||
"system": "jazz-jackrabbit-2", "required": True, "reason": "not_found",
|
||||
"category": "game_data"},
|
||||
{"dest": "x.bin", "name": "x.bin", "system": "nintendo-gba",
|
||||
"required": False, "reason": "not_found"}])
|
||||
dest = self.root / "dest"
|
||||
dest.mkdir()
|
||||
text, _asked = self.line_run(_args(manifest=listing, dest=dest, platform="retroarch",
|
||||
declared_only=False, dry_run=True), [])
|
||||
self.assertIn("Not available here: jazz2/Source/Anims.j2a (Jazz Jackrabbit 2), game "
|
||||
"data its game reads. Copy it from your own copy of the game into "
|
||||
f"{dest / 'jazz2' / 'Source'}{os.sep}.", text)
|
||||
self.assertEqual(install.not_installable_words(37, 1, {"not_found": 37}),
|
||||
"Not installable: 37 files are not in the collection, 1 of them "
|
||||
"required.")
|
||||
self.assertEqual(install.not_installable_words(1, 1, {"not_found": 1}),
|
||||
"Not installable: 1 file is not in the collection, required.")
|
||||
self.assertIn("Why: no save directory (2), not found (3).",
|
||||
install.not_installable_words(5, 0, {"not_found": 3,
|
||||
"no_save_directory": 2}))
|
||||
|
||||
def test_a_system_emptied_by_no_game_data_is_named(self):
|
||||
"""tui_audit_16 P3-7: --system nintendo-ds,sega-dreamcast with
|
||||
--no-game-data: "For 1 of 8 systems (--system)", Dreamcast unsaid
|
||||
until after Enter."""
|
||||
manifest = self.game_manifest()
|
||||
words = (f"{install.system_title('sega-dreamcast', manifest)} holds only game data: "
|
||||
"left out (--no-game-data).")
|
||||
listing = self.game_listing()
|
||||
text, _asked = self.line_run(_args(manifest=listing, dest=self.here,
|
||||
declared_only=False, dry_run=True,
|
||||
system=["nintendo-ds", "sega-dreamcast"],
|
||||
no_game_data=True), [])
|
||||
head = text.split("Enter)", 1)[0]
|
||||
self.assertIn(words, head)
|
||||
state = install.TuiState(os_type="linux", home=HOME)
|
||||
state.manifest = manifest
|
||||
state.no_game_data = True
|
||||
state.cli_systems = ["nintendo-ds", "sega-dreamcast"]
|
||||
state.systems = [{"system": "nintendo-ds", "name": "Nintendo DS", "files": 1,
|
||||
"present": 0, "missing": 1, "wrong_hash": 0, "bytes_needed": 1}]
|
||||
state.ticked = {"nintendo-ds"}
|
||||
state.dest = self.here
|
||||
state.platform = "retroarch"
|
||||
state.check = {**CHECK, "files": 1, "present": 0, "missing": 1, "wrong_hash": 0}
|
||||
state.stack = ["plan"]
|
||||
self.assertIn(words, self.screen(state, 100, 40))
|
||||
|
||||
def test_a_run_with_failures_counts_once(self):
|
||||
"""tui_audit_16 P3-11: "Done. 44 files installed." then "38 files
|
||||
copied from E:\\, 4 downloaded, 2 still missing." gave two counts,
|
||||
the two that failed as missing. Each mode says one, failures named."""
|
||||
out = io.StringIO()
|
||||
sources = install.sources_line([("/media/OLD", 38)], 0, 4, 0, failed=2)
|
||||
self.assertEqual(sources, "38 files copied from /media/OLD, 4 downloaded, 2 failed.")
|
||||
with contextlib.redirect_stdout(out), contextlib.suppress(SystemExit):
|
||||
install._report_outcome([self.here], 42, 0, 2, 0, False,
|
||||
failures=[("x.bin", "timed out"), ("y.bin", "timed out")],
|
||||
sources=sources)
|
||||
text = out.getvalue()
|
||||
self.assertIn(f"Finished with errors. {sources}", text)
|
||||
self.assertNotIn("42 files installed", text)
|
||||
self.assertNotIn("still missing", text)
|
||||
state = checked_state()
|
||||
state.from_folders = [Path("/media/OLD")]
|
||||
state.local_dests = {"gba_bios.bin": ("/media/OLD", "")}
|
||||
state.finished = [("gba_bios.bin", True, ""), ("scph5500.bin", False, "timed out")]
|
||||
state.stack, state.run = ["result"], "install"
|
||||
state.summary = {"event": "summary", "mode": "install", "installed": 1,
|
||||
"up_to_date": 0, "pending": 1,
|
||||
"failed": [{"dest": "scph5500.bin", "reason": "timed out"}],
|
||||
"skipped": [], "left_out": [], "kept": [], "interrupted": False}
|
||||
title, lines = install.tui_outcome(state)
|
||||
self.assertEqual(title, "Finished with errors")
|
||||
self.assertEqual(lines[0], "1 file copied from OLD, 1 failed.")
|
||||
self.assertNotIn("1 installed, 1 failed.", lines)
|
||||
|
||||
def test_check_never_says_a_missing_file_was_opened(self):
|
||||
"""tui_audit_16 P3-12: "missing: nintendo-ds_0.bin" then "opened at
|
||||
..." read as a file that was opened."""
|
||||
entry = {"dest": "a.bin", "systems": ["nintendo-gba"], "cores": None}
|
||||
self.assertEqual(install.opened_line(entry, {}, self.here),
|
||||
f"expected at {self.here / 'a.bin'}")
|
||||
named = {**entry, "cores": ["mgba"]}
|
||||
self.assertEqual(install.opened_line(named, {}, self.here),
|
||||
f"read by mgba at {self.here / 'a.bin'}")
|
||||
|
||||
# Root cause 3: one width with a floor.
|
||||
|
||||
def test_a_terminal_of_no_size_has_the_fallback(self):
|
||||
"""code_audit_23 P3-5: Python 3.8 gives a pty of no size as 0 and 0.
|
||||
The plan printed "0 systems, the largest first:" and the progress
|
||||
line lost every figure but its percentage."""
|
||||
with mock.patch.object(install.shutil, "get_terminal_size",
|
||||
return_value=os.terminal_size((0, 0))):
|
||||
self.assertEqual(install.terminal_size(), (80, 24))
|
||||
out = io.StringIO()
|
||||
term = types.SimpleNamespace(live=True, quiet=False, stream=out,
|
||||
bold=str, dim=str)
|
||||
progress = install.Progress(1, 1400, term)
|
||||
progress.bytes = progress.files = 1400
|
||||
progress.files = 1
|
||||
progress._draw()
|
||||
self.assertIn("(1/1 files)", out.getvalue())
|
||||
self.assertIn("[####", out.getvalue())
|
||||
with contextlib.redirect_stdout(io.StringIO()) as plan:
|
||||
install._print_plan([], self.here, term, copied=[" 1 file copied"])
|
||||
self.assertNotIn("the largest first", plan.getvalue())
|
||||
with mock.patch.object(install.shutil, "get_terminal_size",
|
||||
return_value=os.terminal_size((8, 3))):
|
||||
self.assertEqual(install.terminal_size(), (install.LINE_MIN_COLS, 3))
|
||||
|
||||
def systems_question(self, cols: int) -> list[str]:
|
||||
manifest = json.loads((REPO_ROOT / "install" / "retroarch.json").read_text())
|
||||
out = io.StringIO()
|
||||
with mock.patch.object(install.shutil, "get_terminal_size",
|
||||
return_value=os.terminal_size((cols, 24))), \
|
||||
mock.patch.object(install, "_ask", return_value=""), \
|
||||
contextlib.redirect_stdout(out):
|
||||
install._choose_narrowing(manifest["files"], [], manifest, None)
|
||||
text = out.getvalue()
|
||||
ends = [at for at in (text.find("\nCores:"), text.find("\nThe platform's own"))
|
||||
if at >= 0]
|
||||
return text[text.index("Systems:"):min(ends, default=len(text))].splitlines()
|
||||
|
||||
def test_the_systems_question_stays_inside_the_terminal(self):
|
||||
"""tui_audit_16 P3-5: 6 lines of 81 cells at 80 columns, 16 of 41 at
|
||||
40, "shared" and "platform" alone on a line."""
|
||||
for cols in (100, 80, 60, 40, 30):
|
||||
with self.subTest(cols=cols):
|
||||
lines = self.systems_question(cols)
|
||||
for line in lines:
|
||||
self.assertLess(install.cell_width(line), cols, line)
|
||||
if line.strip() and not line.endswith(":"):
|
||||
self.assertTrue(len(install._glued_words(line)) > 1
|
||||
or re.match(r" *\d+\) ", line), (cols, line))
|
||||
note = " ".join(line.strip() for line in lines[lines.index(
|
||||
next(line for line in lines if line.startswith("'Other"))):])
|
||||
self.assertIn("this platform does not list", note)
|
||||
|
||||
def test_the_setup_list_never_folds_inside_a_word(self):
|
||||
"""tui_audit_16 P3-15: at 39 columns "Miy" / "oo Flip"."""
|
||||
for cols in (80, 39, 30):
|
||||
with self.subTest(cols=cols):
|
||||
with mock.patch.object(install.shutil, "get_terminal_size",
|
||||
return_value=os.terminal_size((cols, 11))):
|
||||
text, _asked = self.line_run(_args(declared_only=False), [])
|
||||
block = text.split("Which setup?", 1)[1].split(" q) quit", 1)[0]
|
||||
lines = [line for line in block.splitlines() if line.strip()]
|
||||
self.assertTrue(lines)
|
||||
for line in lines:
|
||||
self.assertLess(install.cell_width(line), cols, line)
|
||||
self.assertIn("Miyoo Flip", " ".join(" ".join(lines).split()))
|
||||
|
||||
# Root cause 4: line mode in the screen's order and words.
|
||||
|
||||
def test_on_wsl_the_card_comes_first_in_both_modes(self):
|
||||
"""code_audit_23 P3-6: line mode numbered Windows RetroArch 1) and
|
||||
the card 2), where the screen put the card first."""
|
||||
card = games_part(self.root / "media" / "EASYROMS")
|
||||
windows = Path("/mnt/c/RetroArch-Win64/system")
|
||||
side = [("Windows RetroArch: C:\\RetroArch-Win64\\system", windows)]
|
||||
with mock.patch.object(install, "_mounted_cards", return_value=[card]), \
|
||||
mock.patch.object(install, "_mount_points", return_value=frozenset()), \
|
||||
mock.patch.object(install, "other_side", return_value=side), \
|
||||
mock.patch.object(install, "_ask", return_value="q"), \
|
||||
contextlib.redirect_stdout(io.StringIO()) as out, \
|
||||
contextlib.suppress(SystemExit):
|
||||
install.ask_platform_folder("wsl", "retroarch")
|
||||
state = self.first_screen([card])
|
||||
self.assertRegex(out.getvalue(), r"\n 1\) EASYROMS: bios \(SD card")
|
||||
self.assertRegex(out.getvalue(), r"\n 2\) Windows RetroArch")
|
||||
with mock.patch.object(install, "_mounted_cards", return_value=[card]), \
|
||||
mock.patch.object(install, "_mount_points", return_value=frozenset()), \
|
||||
mock.patch.object(install, "other_side", return_value=side):
|
||||
state.os_type = "wsl"
|
||||
install.tui_update(state, Key("enter"))
|
||||
rows = [row for row in install.tui_rows(state) if row.action == "drive"]
|
||||
self.assertEqual([row.value for row in rows], [card / "bios", windows])
|
||||
|
||||
def test_nothing_found_is_said_once(self):
|
||||
"""tui_audit_16 P3-2: "Nothing was found here." twice, and after "A
|
||||
card is in the reader"."""
|
||||
text, _asked = self.line_run(_args(declared_only=False), [])
|
||||
self.assertEqual(text.count("Nothing was found here."), 1)
|
||||
card = games_part(self.root / "media" / "EASYROMS")
|
||||
text, _asked = self.line_run(_args(declared_only=False), [], mounts=[card])
|
||||
self.assertIn("A card is in the reader (EASYROMS): choose its system.", text)
|
||||
self.assertNotIn("Nothing was found here", text)
|
||||
|
||||
def test_the_bios_only_drive_note_is_one_plain_sentence(self):
|
||||
"""tui_audit_16 P3-9: "listed, not chosen", "(card or drive)" under
|
||||
a note saying no card, two parentheses side by side, and "keeps
|
||||
them" after a title."""
|
||||
data = self.drive("DATA", ("bios", "snes", "Music"))
|
||||
stick = self.drive("STICK", ("bios",))
|
||||
card = games_part(self.root / "media" / "EASYROMS")
|
||||
mounts = [card, data, stick]
|
||||
state, text, rows = self.folder_screen(mounts)
|
||||
self.assertIn("DATA and STICK have a bios folder but no folder a handheld system "
|
||||
"writes. Pick one below if your files go there.", text)
|
||||
self.assertIn("The card in the reader keeps BIOS files in its bios folder", text)
|
||||
labels = [row.label for row in rows]
|
||||
self.assertIn("DATA: bios (drive)", labels)
|
||||
self.assertIn("EASYROMS: bios (SD card)", labels)
|
||||
line, _asked = self.line_run(_args(manifest=self.game_listing(), dry_run=True,
|
||||
declared_only=False), ["1", ""], mounts=mounts)
|
||||
for said in (text, line):
|
||||
self.assertNotIn("listed, not chosen", said)
|
||||
self.assertNotIn("card or drive", said)
|
||||
self.assertNotIn(") (", said)
|
||||
self.assertNotIn("keeps them", said)
|
||||
|
||||
def test_the_same_choice_is_one_command_in_both_modes(self):
|
||||
"""tui_audit_16 P3-14: the screen wrote --manifest before --from,
|
||||
line mode after it."""
|
||||
hint = install.Invocation()
|
||||
hint.os_type = "linux"
|
||||
hint.options = [("--from", "/media/OLD"), ("--offline", None),
|
||||
("--manifest", "/x/list.json"), ("--system", "a")]
|
||||
self.assertEqual(hint.command("retroarch", "/dest"),
|
||||
"python3 install.py --platform retroarch --dest /dest --manifest "
|
||||
"/x/list.json --system a --from /media/OLD --offline")
|
||||
state = checked_state()
|
||||
state.manifest_given, state.manifest_path = True, Path("/x/list.json")
|
||||
state.from_folders = [Path("/media/OLD")]
|
||||
args = _args(manifest="/x/list.json", platform="retroarch", dest=SYSTEM_DIR,
|
||||
declared_only=False, offline=False)
|
||||
setattr(args, "from", ["/media/OLD"])
|
||||
line = install.Invocation()
|
||||
line.os_type = "linux"
|
||||
line.record(args)
|
||||
with mock.patch.dict(os.environ, {install.OFFLINE_VARIABLE: "1"}):
|
||||
line.options.append(("--offline", None))
|
||||
self.assertEqual(install.tui_command(state), line.command("retroarch", SYSTEM_DIR))
|
||||
|
||||
# Root cause 5: interaction.
|
||||
|
||||
def test_a_tap_on_a_focused_row_shows_it_was_seen(self):
|
||||
"""tui_audit_16 P3-8: one tap on the focused Onion row showed
|
||||
nothing, a second continued."""
|
||||
state = fresh_state()
|
||||
state.stack = ["setup"]
|
||||
state.mouse = True
|
||||
lines = drawn(state, 80, 24)
|
||||
row = next(index for index, line in enumerate(lines)
|
||||
if str(line).lstrip().startswith("> "))
|
||||
self.assertEqual(tap(state, 4, row), [])
|
||||
lines = drawn(state, 80, 24)
|
||||
self.assertIn(f"A/Enter Continue: {install.TUI_ARMED}", str(lines[-1]))
|
||||
self.assertIn(f"RetroArch: {install.TUI_ARMED}", str(lines[row]))
|
||||
self.assertNotEqual(tap(state, 4, row), [])
|
||||
|
||||
def test_a_phone_bar_names_the_enter_key(self):
|
||||
"""tui_audit_16 P3-13: Termux at 40 columns said "A Continue", and
|
||||
the a key does nothing."""
|
||||
state = install.TuiState(os_type="android", home=HOME)
|
||||
state.pad = install.tui_pad_route("android", {})
|
||||
self.assertEqual(state.pad, "both")
|
||||
bar = str(install.tui_view(state, 40, 12)[-1])
|
||||
self.assertIn("Enter", bar)
|
||||
self.assertNotRegex(bar, r"(^| )A ")
|
||||
self.assertIn("A/Enter", str(install.tui_view(state, 80, 24)[-1]))
|
||||
state.pad = "gptokeyb"
|
||||
self.assertRegex(str(install.tui_view(state, 40, 12)[-1]), r"(^| )A ")
|
||||
|
||||
def test_which_folder_keeps_its_folder_at_40_by_12(self):
|
||||
"""tui_audit_16 P3-1: with two drives holding bios, Which folder?
|
||||
at 40x12 dropped the folder "Use this folder" stands for."""
|
||||
data = self.drive("DATA", ("bios", "snes", "Music"))
|
||||
stick = self.drive("STICK", ("bios",))
|
||||
for mounts in ([data, stick], [games_part(self.root / "media" / "EASYROMS"), data]):
|
||||
with self.subTest(mounts=[mount.name for mount in mounts]):
|
||||
state, _text, _rows = self.folder_screen(mounts)
|
||||
with mock.patch.object(install, "_mounted_cards", return_value=mounts), \
|
||||
mock.patch.object(install, "_mount_points", return_value=frozenset()):
|
||||
small = " ".join(str(line) for line in install.tui_view(state, 40, 12))
|
||||
folder = str(state.folder_default)
|
||||
self.assertIn("reads its BIOS files", small)
|
||||
self.assertIn(folder[-12:], small)
|
||||
|
||||
# The owner's note: Cores drew every box empty when no core narrows the
|
||||
# run, read as "nothing is ticked, tick them all".
|
||||
|
||||
def cores_screen(self, **given) -> install.TuiState:
|
||||
state = checked_state()
|
||||
state.cores = list(given.get("cores", []))
|
||||
state.cli_cores = list(state.cores)
|
||||
press(state, "o")
|
||||
state.focus["options"] = next(index for index, row in enumerate(
|
||||
install.tui_rows(state)) if row.action == "cores")
|
||||
press(state, "enter")
|
||||
self.assertEqual(state.screen, "cores")
|
||||
return state
|
||||
|
||||
@staticmethod
|
||||
def boxes(state: install.TuiState) -> dict:
|
||||
return {row.value: row.label[:3] for row in install.tui_rows(state)
|
||||
if row.action == "core"}
|
||||
|
||||
def test_cores_open_every_one_ticked(self):
|
||||
state = self.cores_screen()
|
||||
self.assertEqual(self.boxes(state), {"mesen": "[x]", "pcsx_rearmed": "[x]"})
|
||||
self.assertEqual(install.tui_rows(state)[state.focus["cores"]].value, "mesen")
|
||||
self.assertEqual(install.tui_flags(state), [])
|
||||
|
||||
def test_one_untick_narrows_to_the_others(self):
|
||||
state = self.cores_screen()
|
||||
press(state, " ")
|
||||
self.assertEqual(self.boxes(state), {"mesen": "[ ]", "pcsx_rearmed": "[x]"})
|
||||
self.assertEqual(install.tui_flags(state), [("--core", "pcsx_rearmed")])
|
||||
press(state, " ")
|
||||
self.assertEqual(self.boxes(state), {"mesen": "[x]", "pcsx_rearmed": "[x]"})
|
||||
self.assertEqual(state.cores, [])
|
||||
press(state, " ", "enter")
|
||||
self.assertEqual(state.screen, "options")
|
||||
row = next(row for row in install.tui_rows(state) if row.action == "cores")
|
||||
self.assertEqual(row.label, "Cores: 1 of 2")
|
||||
state.stack = ["setup", "plan"]
|
||||
self.assertIn("1 of 2 cores", " ".join(install.tui_view(state, 100, 30)))
|
||||
|
||||
def test_none_then_all_as_the_systems_list(self):
|
||||
state = self.cores_screen()
|
||||
rows = install.tui_rows(state)
|
||||
state.focus["cores"] = next(i for i, row in enumerate(rows) if row.action == "none")
|
||||
press(state, "enter")
|
||||
self.assertEqual(self.boxes(state), {"mesen": "[ ]", "pcsx_rearmed": "[ ]"})
|
||||
press(state, "enter")
|
||||
self.assertEqual(state.screen, "cores")
|
||||
self.assertIn("No core is ticked", str(state.status))
|
||||
state.focus["cores"] = next(i for i, row in enumerate(rows) if row.action == "all")
|
||||
press(state, "enter")
|
||||
self.assertEqual(self.boxes(state), {"mesen": "[x]", "pcsx_rearmed": "[x]"})
|
||||
self.assertEqual(install.tui_flags(state), [])
|
||||
|
||||
def test_core_ticks_only_the_cores_it_names(self):
|
||||
state = self.cores_screen(cores=["pcsx_rearmed"])
|
||||
self.assertEqual(self.boxes(state), {"mesen": "[ ]", "pcsx_rearmed": "[x]"})
|
||||
state.stack = ["setup", "plan"]
|
||||
self.assertIn("--core", " ".join(install.tui_view(state, 100, 30)))
|
||||
|
||||
def test_both_modes_count_the_cores_kept_alike(self):
|
||||
listing = self.listing("retroarch", [
|
||||
self.entry("a.bin", b"A" * 8, ["nintendo-gba"]),
|
||||
self.entry("m.bin", b"M" * 8, ["nintendo-gba"], cores=["mgba"]),
|
||||
self.entry("v.bin", b"V" * 8, ["nintendo-gba"], cores=["vba_next"]),
|
||||
self.entry("p.bin", b"P" * 8, ["sony-playstation"])])
|
||||
text, _asked = self.line_run(_args(manifest=listing, dest=self.here,
|
||||
declared_only=False, dry_run=True),
|
||||
["c", "", "2"])
|
||||
self.assertIn("Every core's extra files are kept: Enter keeps them all", text)
|
||||
head = text.rsplit("Counted again for your choices", 1)[1]
|
||||
self.assertIn("1 of 2 cores", head)
|
||||
self.assertEqual(install.cores_words(0, 2), "all cores")
|
||||
self.assertEqual(install.cores_words(2, 2), "all cores")
|
||||
|
||||
# Root cause 6: the pages say what the installer shows.
|
||||
|
||||
@unittest.skipIf(sys.version_info < (3, 9),
|
||||
"the site generator needs Python 3.9")
|
||||
def test_which_pack_names_the_first_screen(self):
|
||||
"""tui_audit_16 P3-10: which-pack said the command opens a screen
|
||||
where Install and Choose systems are, the second screen."""
|
||||
sys.path.insert(0, str(REPO_ROOT / "scripts"))
|
||||
self.addCleanup(sys.path.remove, str(REPO_ROOT / "scripts"))
|
||||
import generate_site # noqa: PLC0415
|
||||
|
||||
words = " ".join(generate_site.first_screen_words())
|
||||
found, nothing = fresh_state(), install.TuiState(os_type="linux", home=HOME)
|
||||
found.stack = ["setup"]
|
||||
self.assertIn(install.tui_view(found, 80, 24)[0].split(": ", 1)[1].strip(), words)
|
||||
self.assertIn(install.tui_view(nothing, 80, 24)[0].split(": ", 1)[1].strip(), words)
|
||||
self.assertLess(words.index(install.TUI_FOUND_TITLE),
|
||||
words.index(install.TUI_INSTALL_ROW))
|
||||
self.assertNotIn("opens a screen", words)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -167,7 +167,7 @@ class GetYourFilesOrder(unittest.TestCase):
|
||||
text = _page("which-pack.md")
|
||||
order = [text.index(mark) for mark in (
|
||||
"## Pick your setup", "| Setup | Runs on | BIOS folder | ZIP |", "<FilePicker",
|
||||
"## Not in the list? One command finds it", "The command opens a screen",
|
||||
"## Not in the list? One command finds it", "It asks **",
|
||||
"<summary>Is it safe?</summary>",
|
||||
)]
|
||||
self.assertEqual(order, sorted(order))
|
||||
|
||||
+31
-16
@@ -210,7 +210,9 @@ in the names of what is held. On a computer it names the keys (`Enter Install`,
|
||||
launcher (`A Install`, `B Back`, see `RETROBIOS_PAD` below), and `?` shows
|
||||
both the buttons and the keys. Where neither is known, in SteamOS game mode or
|
||||
on a console no launcher named, it gives both spellings (`A/Enter`, `B/Esc`),
|
||||
and a narrow screen shortens them to `A`, `B` and `X`. On the
|
||||
and a narrow screen shortens them to `A`, `B` and `X`. In Termux on Android,
|
||||
with no launcher named, a narrow screen keeps the keys (`Enter`, `Esc`) instead,
|
||||
a phone having an Enter key and no A button. On the
|
||||
regions screen, Left and Right move the region under the cursor up and down the
|
||||
order of preference. During the download, a stop waits for the files in
|
||||
progress, and a second one stops at once. Select+Start on a handheld ends the
|
||||
@@ -267,7 +269,8 @@ says why.
|
||||
A mouse or a touch screen works too, beside the keys and buttons, in a
|
||||
terminal that reports clicks: those of Linux, macOS, WSL and Termux. A click
|
||||
or a tap on a box (a system, a core, a region) ticks or unticks it, as Space
|
||||
does. On any other row it moves the cursor there, and a second one on that
|
||||
does. On any other row it moves the cursor there and adds `click or tap
|
||||
again` to the row and the bottom line, and a second one on that
|
||||
row does what Enter does: one row of a terminal is far smaller than a finger,
|
||||
and the row a screen opens on (**Install** on Confirm) is never chosen by one
|
||||
tap. The entries of the bottom line press their key, **Exit** on the result
|
||||
@@ -732,6 +735,7 @@ RetroArch: 10994 files, 6.7 GB.
|
||||
3269 BIOS files (4.1 GB), 5089 game data files (2.5 GB) and 2636 data files (38.5 MB).
|
||||
Game data: files a game or a game engine reads, of no use to the other cores. Data files: the files an emulator reads from a data folder of its own, such as Dolphin's Sys and PPSSPP's assets.
|
||||
BIOS folder: /home/me/.config/retroarch/system
|
||||
Not available here: jazz2/Source/Anims.j2a (Jazz Jackrabbit 2), game data its game reads. Copy it from your own copy of the game into /home/me/.config/retroarch/system/jazz2/Source/.
|
||||
Enter) install everything
|
||||
c) choose systems, cores and regions
|
||||
f) copy from a folder or an old card
|
||||
@@ -786,7 +790,11 @@ answer is not asked.
|
||||
chosen too, as `generate_pack.py --system` does.
|
||||
- **Cores.** The platform's own BIOS list for the chosen systems is always
|
||||
kept. This narrows only the extra files each emulator core loads beyond it.
|
||||
Asked only when the chosen systems have such files.
|
||||
Asked only when the chosen systems have such files. Every core is kept
|
||||
until numbers name some, and the head then says how many of how many
|
||||
(`1 of 2 cores`). The full screen's **Cores** opens with every core
|
||||
ticked, as Choose systems does: untick the ones you do not use, **All**
|
||||
and **None** tick or untick them all.
|
||||
- **Regions.** Asked only when a chosen system has one BIOS per region. The
|
||||
numbers give an order of preference: `2,1` keeps the second region where a
|
||||
file for it exists, and the first one elsewhere.
|
||||
@@ -1048,6 +1056,8 @@ gives for the device, below the card's root instead of its mount point:
|
||||
| `.tmp_update/onionVersion/version.txt` | Onion | `BIOS`, RetroArch's list |
|
||||
| `.allium/` | Allium | `BIOS`, RetroArch's list |
|
||||
| `Koriki/version.txt` | Koriki | `BIOS`, RetroArch's list |
|
||||
| `gamedata/`, `homebrew/` beside `bios/`, on a drive that is not a fixed disk | AmberELEC | `bios`, AmberELEC's list |
|
||||
| `bezels/default.cfg` beside `bios/`, on a drive that is not a fixed disk | EmuELEC | `bios`, EmuELEC's list |
|
||||
| `system/batocera.conf` holding `system.hostname=BATOCERA` or no hostname line, and no KNULLI file above | Batocera SHARE drive | `bios`, Batocera's list |
|
||||
| `system/recalbox.conf` | Recalbox SHARE drive | `bios`, Recalbox's list |
|
||||
| `system/batocera.conf` with any other hostname, and no KNULLI file above, or the files of two SHARE drives | named by neither: the run says which systems it could be | the folder of the system named with `--platform` |
|
||||
@@ -1186,9 +1196,10 @@ folder inside another system's card (ROCKNIX's `roms/bios` named for KNULLI).
|
||||
A card whose own files name it is that card whatever its name: an Onion card
|
||||
mounted as `BIOS` gets `BIOS/BIOS`. One without the system's own files is
|
||||
refused for the MinUI family, Onion, muOS, spruceOS, CrossMix-OS, Allium and
|
||||
Koriki. KNULLI and ROCKNIX fill their card when they first start, and no file
|
||||
on the card names ArkOS, dArkOS, JELOS, KOLOS, UnofficialOS, ArchR, RetroOZ,
|
||||
plumOS, MiyooCFW, AmberELEC, EmuELEC or the Anbernic firmware: such a folder
|
||||
Koriki. KNULLI, ROCKNIX, AmberELEC and EmuELEC fill their card when they first
|
||||
start (AmberELEC's `gamedata` and `homebrew`, EmuELEC's `bezels/default.cfg`),
|
||||
and no file on the card names ArkOS, dArkOS, JELOS, KOLOS, UnofficialOS, ArchR,
|
||||
RetroOZ, plumOS, MiyooCFW or the Anbernic firmware: such a folder
|
||||
gets the system's folder below it, and a note says so, kept on **Create the
|
||||
folder?** and the plan. No to creating its folders asks for the card again.
|
||||
Under WSL a drive letter (`D:`, `D:\`) is that Windows drive, typed or given
|
||||
@@ -1217,16 +1228,20 @@ that question a drive is numbered by the folder its system reads (`ONION:
|
||||
BIOS`), a drive nothing names by its `bios` folder (`EASYROMS: bios`), never
|
||||
by its root, which no setup reads. A handheld's card whose own files sit on a
|
||||
part a computer does not open is told by the folders its system writes beside
|
||||
`bios` on the games part: `themes` and `launchimages` on ArkOS's `EASYROMS`,
|
||||
`gamedata` and `homebrew` on AmberELEC's `GAMES`, `bezels/default.cfg` on
|
||||
EmuELEC's `EEROMS`. A disk Windows or Linux calls fixed is never one. With
|
||||
nothing found here the first screen and line mode say `A card is in the reader
|
||||
(EASYROMS): choose its system` (two cards: `choose their systems`), and its
|
||||
`bios` folder comes first at the folder question, under Enter, before this
|
||||
computer's usual folder. A drive with a `bios` folder and none of those
|
||||
folders, a data drive or a stick, is numbered with a note (`DATA has a bios
|
||||
folder, and nothing on it shows a handheld's card: listed, not chosen.`) and
|
||||
never taken under Enter. Another system's card or SHARE drive, and a
|
||||
`bios` on the games part: `bgmusic` or `launchimages` on ArkOS's `EASYROMS`
|
||||
(every ArkOS card has one of them from its first images, `themes` only since
|
||||
an update a full card skipped), `gamedata` and `homebrew` on AmberELEC's
|
||||
`GAMES`, `bezels/default.cfg` on EmuELEC's `EEROMS`. A disk Windows or Linux
|
||||
calls fixed is never one. AmberELEC's and EmuELEC's card is found as theirs
|
||||
(`AmberELEC SD card (GAMES)` under **Found on this machine**), in both modes
|
||||
and on their own setup's card question, and gets their list. An ArkOS card
|
||||
reads RetroArch's list: with nothing found here the first screen and line mode
|
||||
say `A card is in the reader (EASYROMS): choose its system` (two cards: `choose
|
||||
their systems`), and its `bios` folder comes first at the folder question,
|
||||
under Enter, before this computer's usual folder. A drive with a `bios` folder
|
||||
and none of those folders, a data drive or a stick, is numbered with a note
|
||||
(`DATA has a bios folder but no folder a handheld system writes. Pick it below
|
||||
if your files go there.`) and never taken under Enter. Another system's card or SHARE drive, and a
|
||||
drive two systems fit, are left out, and a line names them: each is reached
|
||||
through its own setup. A folder typed is read from the current
|
||||
one when it is not a full path, and named in full after. `q` quits there too
|
||||
|
||||
Reference in new issue
Block a user