Compare commits

...

108 Commits

Author SHA1 Message Date
Carter Li 6b92659512 Merge pull request #1752 from fastfetch-cli/dev
Release: v2.43.0
2025-05-14 09:41:33 +08:00
Carter Li 7e04305d1c CI: silence spell check errors 2025-05-14 09:25:15 +08:00
Carter Li 87e13543da GPU (Linux): embed asahi_drm.h 2025-05-14 08:59:53 +08:00
Carter Li 7a2cbc060f 3rdparty (yyjson): upgrade to 0.11.1 2025-05-14 08:52:06 +08:00
Carter Li f22d73d473 PhysicalDisk: trim white spaces of serial 2025-05-13 18:29:46 +08:00
李通洲 e629126d73 Doc: update changelog 2025-05-13 15:52:30 +08:00
李通洲 9ac635e2e6 Media (Windows): detect player name (UMP apps only) 2025-05-13 15:46:33 +08:00
李通洲 1b1b0521f4 Doc: update changelog 2025-05-13 13:49:54 +08:00
李通洲 41d0f61ee0 GPU (AMD): remove usage of ADL2_Adapter_VRAMUsage_Get
It reports dedicated GPU memory usage too.

Ref: https://github.com/GPUOpen-LibrariesAndSDKs/display-library/issues/48
2025-05-13 13:39:42 +08:00
李通洲 9de5d9008b Release: v2.43.0 2025-05-13 10:37:52 +08:00
李通洲 576a9cc6fe Revert "Vulkan: use VK_API_VERSION_* instead of deprecated VK_VERSION_*"
Breaks building with old vulkan-headers

This reverts commit 36b0fdbcda.
2025-05-13 10:02:38 +08:00
李通洲 bd61d08afe Sound (macOS): report the volume of muted device as 0% 2025-05-13 09:35:13 +08:00
李通洲 4672b78481 Sound: don't show 255 in custom format
Fix #1750
2025-05-13 09:30:30 +08:00
李通洲 36b0fdbcda Vulkan: use VK_API_VERSION_* instead of deprecated VK_VERSION_* 2025-05-13 09:29:21 +08:00
Carter Li 7626ef6eaa GPU (Linux): fix CI errors
F**k Ubuntu
2025-05-10 21:40:33 +08:00
Carter Li 115108b3f1 GPU (Linux): detect core usage when libamdgpu is not available 2025-05-10 20:57:51 +08:00
Carter Li 154f9f462b GPU (Linux): detect VRAM type of AMD GPUs 2025-05-10 20:57:51 +08:00
Marvin Friedrich a96a9fc31d Smbios: fix transitive include for loff_t (#1746) 2025-05-10 10:49:22 +08:00
李通洲 23b43244c5 GPU (AMD): seems ADL2_Adapter_VRAMUsage_Get reports system mem usage only, not full memory usage
Because VRAMUsage reports a value which is smaller than DedicatedVRAMUsage
2025-05-09 22:46:31 +08:00
Carter Li 9dfb404a0d GPU (AMD): more verbose logs 2025-05-09 22:01:29 +08:00
Carter Li ff3028c656 GPU: don't hide unknown type of GPUs by default
Fix #1742
2025-05-09 21:58:41 +08:00
Carter Li 2f706ed494 Smbios: discard usless values 2025-05-09 21:55:31 +08:00
Carter Li 06427ee62b Media (Linux): fix duplicated playback status 2025-05-09 19:23:28 +08:00
李通洲 fe66eb3df0 GPU (Windows): fix incorrect used shared memory size 2025-05-08 23:20:53 +08:00
李通洲 6e1ab12399 Memory / Swap: always initialize local variables 2025-05-08 23:17:22 +08:00
Samuli Thomasson 484e05eae3 GPU: optionally hide unknown GPUs (#1742)
The current default behavior of not hiding any GPUs is retained. The new
feature of hiding unknown or unrecognized GPUs can be enabled with
hide-type = "unknown".
2025-05-07 22:06:47 +08:00
Joe_ 5d3fb98072 Logo (Builtin): add Hydra Framework logo (#1740)
* Added: Hydra Framework logo

* Remove extra line: hydra.txt
2025-05-07 03:02:36 -05:00
李通洲 0c30590088 Builtin (Logo): new AthenaOS logo
Fix #1741
2025-05-07 10:45:21 +08:00
李通洲 20cd4ce125 Logo (Builtin): sd '\$\{c(\d)\}' '$$$1' * 2025-05-07 10:44:05 +08:00
apocelipes 1c7aa89228 TerminalShell: use ffBinaryExtractStrings result as possible (#1739) 2025-05-06 18:49:29 +08:00
apocelipes f270255770 DisplayServer (Linux): fix xcb_connect error handling (#1735) 2025-05-06 03:18:53 -05:00
李通洲 4b62a3c75b 3rdparty: upgrade yyjson to 0.11.0 2025-05-06 16:12:58 +08:00
李通洲 1557f0c556 Media (macOS): support macOS 15.4
Fix #1737
2025-05-06 16:12:58 +08:00
Carter Li ef7f61309f GPU (Linux): fix asahi linux support again
Found in kernel-headers-6.14.4-400.asahi.fc42.aarch64
2025-05-06 09:27:54 +08:00
李通洲 f59491b25d Disk (Linux): fix possible bug on 32-bit platforms
Fix #1734
2025-05-05 22:05:22 +08:00
李通洲 e3592eb2c3 CPU (FreeBSD): simplify physical core count detection 2025-05-05 13:41:12 +08:00
Carter Li 305776eb94 CPU (SunOS): support physical core count and package count detection 2025-05-02 14:24:30 +08:00
Carter Li 599e0d393d Display: use height to calculate scale factor
Seems more accurate
2025-05-01 21:28:04 +08:00
李通洲 561574ae94 CPU (Windows): always use XxxW 2025-04-30 16:10:53 +08:00
李通洲 3dd78422eb Global: Improve ARRAY_SIZE macro using __is_array 2025-04-30 14:47:37 +08:00
李通洲 5c546ab8e7 Parsing: silence compiler warnings 2025-04-30 14:14:28 +08:00
Carter Li 3e9274040d Packaging: update debian stuff [ci skip] 2025-04-30 14:12:26 +08:00
Carter Li 630d876e2d Merge pull request #1722 from fastfetch-cli/dev
Release: v2.42.0
2025-04-29 14:05:36 +08:00
李通洲 1938be86ff Wifi (NetBSD): fix the ambiguous comment 2025-04-29 13:53:45 +08:00
李通洲 0980d5f0ad Wifi (BSD): correctly prioritize Wi-Fi protocol detection
by using an `if-else if` chain
2025-04-29 13:50:53 +08:00
李通洲 d8c1b3b61b Release: v2.42.0 2025-04-29 10:38:07 +08:00
李通洲 969523ae8a BIOS: normalize the module name
Fix #1721
2025-04-29 10:26:19 +08:00
李通洲 5d960ec744 Uptime: fix non-normalized time being shown
Fix #1720
2025-04-29 10:22:19 +08:00
apocelipes 3b36b8ca57 Global: use ARRAY_SIZE (#1718) 2025-04-28 21:22:04 -05:00
apocelipes 05f14764e6 Bluetooth (Linux): silence an unused variable warning (#1717) 2025-04-28 22:50:46 +08:00
apocelipes 3a180b24e3 Platform: fix a memory leak (#1716) 2025-04-28 22:49:31 +08:00
李通洲 02ab58e001 Doc: update changelog [ci skip] 2025-04-24 09:31:05 +08:00
Carter Li fd158b41e1 Logo (Chafa): fix setting chafa.symbols
Fix #1709
2025-04-24 09:02:45 +08:00
李通洲 89e0ede12f Camera (OpenBSD): add support 2025-04-23 20:09:08 +08:00
李通洲 4d7b2410ef CPU (OpenBSD): fix CPU temperature detection 2025-04-22 21:19:22 +08:00
李通洲 c1f6a2f755 Refactor: inline printError into ffPrintError and remove unused static helper 2025-04-22 14:30:39 +08:00
李通洲 9c455c3b0f Wifi (FreeBSD): fix possible mem leaks 2025-04-20 12:41:06 +08:00
Carter Li d4ea9dfd21 Wifi (NetBSD): add support
Untested
2025-04-20 12:40:47 +08:00
李通洲 08071e6e7e Wifi (OpenBSD): fix file name 2025-04-20 11:49:40 +08:00
李通洲 ec87174f30 CPU (NetBSD): add one more method to detect CPU frequency 2025-04-20 11:43:39 +08:00
李通洲 835e5b51c9 CPU (SunOS): detect CPU temp
Untested
2025-04-20 11:12:08 +08:00
Noa Himesaka 07c5ef255e Logo (Builtin): Add Codex Linux support (#1701)
* feat: add Codex Linux

* Codex.txt: remove empty lines

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-04-19 21:22:28 +08:00
李通洲 476b55c17d Logo (Builtin): remove GoralixOS
Ref: #1699
2025-04-19 21:18:13 +08:00
李通洲 4a53cfa312 Logo (Builtin): add Aurora
Fix #1700
2025-04-19 21:11:54 +08:00
李通洲 50ea515476 PhysicalDisk (Linux): don't detect disk type of virtual disks
Fix #1697
2025-04-18 16:10:01 +08:00
xzvf cbd9f72bc8 T2/SDE: upstreaming downstream's logo change (#1695)
* T2/SDE: upstreaming downstream's logo change

T2/SDE port of fastfetch applies two patches, improving the
distribution's logo and adding alternative names. I see no point not
having these upstream.

Downstream's patches are found here:
https://github.com/rxrbln/t2sde/tree/main/package/contrib/fastfetch

The old logo has been renamed to "T2_small".

* Fix ASCII art alignment in t2.txt

---------

Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-04-17 22:52:45 +08:00
李通洲 29eaa35f4c Color: support #RGB and #RRGGBB
Fix #1694
2025-04-17 10:48:18 +08:00
Carter Li 97c89c39d3 Packaging: update debian stuff [ci skip] 2025-04-16 13:51:09 +08:00
Carter Li 5769791185 Merge pull request #1691 from fastfetch-cli/dev
Release: v2.41.0
2025-04-16 13:29:07 +08:00
李通洲 894c66d793 Processing (Windows): fix macro name __aarch64__
Found by AI
2025-04-16 11:12:36 +08:00
李通洲 75290154b0 Chore: remove Chinese comments [ci skip] 2025-04-16 11:09:03 +08:00
李通洲 b08eea76b1 CI (Linux): enable chafa on Linux aarch64 2025-04-16 10:45:25 +08:00
李通洲 61d83af9ea CI (Linux): bump GH runner for linux-amd64
Ref: https://github.com/actions/runner-images/issues/11101
2025-04-16 10:45:02 +08:00
李通洲 2d497038eb Release: v2.41.0 2025-04-16 09:24:20 +08:00
李通洲 f8a5d5561a Bluetooth (NetBSD): add base implementation
Ref: #1690
2025-04-15 19:06:39 +08:00
李通洲 2e7e68ef23 Doc: add installation instructions for pkgsrc [ci skip]
Fix #1689
2025-04-15 19:04:19 +08:00
李通洲 b812f3ccde Uptime (Windows): use QueryUnbiasedInterruptTime
As suggested by MSDN
2025-04-15 16:41:38 +08:00
李通洲 6da8181bbe CMake: use mincore on WoA 2025-04-15 16:41:38 +08:00
李通洲 a51dd641c1 Processing (Windows): use GetOverlappedResultEx on WoA 2025-04-15 16:41:38 +08:00
李通洲 0d20164d40 CI (Windows): add WoA 2025-04-15 10:59:10 +08:00
李通洲 3320532668 GPU (Linux): add temp detection for Intel GPU
Untested
2025-04-14 18:57:15 +08:00
Carter Li bcc6492115 NetIO (Linux): use openat 2025-04-14 18:48:04 +08:00
naix c60bc8ee5b Logo (Builtin): Add 2 more Alpine logos (#1687)
* Logo (Builtin): Add 2 more Alpine logos

* Remove unnecessary $1 in ASCII logo file

* Add type field to Alpine2 logo configuration

---------

Co-authored-by: naix <naix@noreply.codeberg.org>
Co-authored-by: Carter Li <CarterLi@users.noreply.github.com>
2025-04-14 00:50:45 -05:00
李通洲 4eefab8ccf CPU (Linux): fix build 2025-04-14 10:54:35 +08:00
李通洲 9cda7e20fb Chore: simplify fastfetch.h 2025-04-14 10:28:01 +08:00
李通洲 79d0197dcf Wifi (FreeBSD): remove unused sys headers 2025-04-14 10:04:11 +08:00
李通洲 ba01b1e4ce CPU (Linux): add new ARM part numbers 2025-04-14 09:27:01 +08:00
李通洲 58908f69ba Wifi (OpenBSD): add support
Completely untested.
2025-04-13 00:37:40 +08:00
李通洲 114088b845 Doc: add comments about displaying image logo on Windows [ci skip]
Fix  #1686
2025-04-12 20:38:42 +08:00
李通洲 6e77b592cb WM (FreeBSD): enable Hyprland version detection 2025-04-12 10:48:26 +08:00
李通洲 73bc71e922 CPU (Windows): use PDH to detect thermal temp
No Administrator privileges needed
2025-04-12 10:47:57 +08:00
Anduin Xue 090529ffef Logo (Builtin): Add support for anduinos (#1684)
* Add anduinos

* fix logo.

* Update anduinos.txt
2025-04-10 23:13:26 +08:00
李通洲 3c291f1af9 Platform: retrieve full user name 2025-04-09 16:15:23 +08:00
李通洲 fc31fe4aa4 Merge branch 'master' into dev 2025-04-09 14:39:51 +08:00
李通洲 563f9598be Release: v2.40.4 2025-04-09 14:24:27 +08:00
Carter Li 03bc2dade9 Fastfetch: fix loading presets in {exePath}/presets
Regression of v2.40.0
2025-04-09 14:15:06 +08:00
Carter Li 09d683b706 WM (Linux): remove v from Hyprland version 2025-04-09 14:14:56 +08:00
Carter Li 523a9590b8 Fastfetch: fix loading presets in {exePath}/presets
Regression of v2.40.0
2025-04-08 15:42:58 +08:00
李通洲 3c3188eb05 IO (Windows): support ~ expanding 2025-04-07 16:43:48 +08:00
李通洲 354062118f Chore: update comment 2025-04-07 16:43:48 +08:00
李通洲 85d7390fa8 Util (Windows): use native win32 functions 2025-04-07 16:38:54 +08:00
Carter Li 8509f97054 WM (Linux): remove v from Hyprland version 2025-04-06 17:21:32 +08:00
Rabindra Dhakal 8d5d8b4c90 Packages (Linux): add soar packages count (#1531)
* add soar packages count

* use || instead of concat for better compatibility with older SQLite versions

* convert package flags to 64-bit
2025-04-05 23:54:27 +08:00
李通洲 536ad9594e PhysicalDisk (Linux): add more disk types 2025-04-05 22:35:42 +08:00
李通洲 a57bbbadf4 PhysicalDisk (Linux): don't detect disk type for virtual disks
Fix #1669
2025-04-05 22:35:42 +08:00
李通洲 3def466ee0 Revert "CPU (FreeBSD): remove using of freq_levels"
This reverts commit ed2dd8f2ec.
2025-04-05 13:54:20 +08:00
李通洲 59868c66a0 CPU (FreeBSD): don't assume one SMT group has only two threads
Fix #1670
2025-04-05 13:48:18 +08:00
Carter Li e13eb05073 CPU (Linux): detect physical core count on non-x86 platforms 2025-04-05 12:08:35 +08:00
233 changed files with 7794 additions and 3874 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
[codespell]
check-filenames =
builtin = clear,rare,usage,informal
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii
skip = */.git,*/cmake-build-*,*/.idea,*/completions,*/presets,*/screenshots,*/tests,*/3rdparty,*/logo/ascii,./src/detection/gpu/asahi_drm.h
ignore-words-list = iterm,compiletime,unknwn,pengwin,siduction,master,slave,sur,doas,conexant,ags,bu
+72 -4
View File
@@ -60,7 +60,7 @@ jobs:
linux-amd64:
name: Linux-amd64
runs-on: ubuntu-20.04
runs-on: ubuntu-22.04
permissions:
security-events: write
contents: read
@@ -80,12 +80,12 @@ jobs:
run: cat /proc/cpuinfo
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev libddcutil-dev directx-headers-dev
- name: install linuxbrew packages
run: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa ddcutil --ignore-dependencies
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
@@ -151,8 +151,13 @@ jobs:
- name: install required packages
run: sudo apt-get update && sudo apt-get install -y libvulkan-dev libwayland-dev libxrandr-dev libxcb-randr0-dev libdconf-dev libdbus-1-dev libmagickcore-dev libxfconf-0-dev libsqlite3-dev librpm-dev libegl-dev libglx-dev ocl-icd-opencl-dev libpulse-dev libdrm-dev libelf-dev directx-headers-dev libchafa-dev libddcutil-dev rpm
- name: install linuxbrew packages
run: |
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
/home/linuxbrew/.linuxbrew/bin/brew install imagemagick chafa --ignore-dependencies
- name: configure project
run: cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
run: PKG_CONFIG_PATH=/home/linuxbrew/.linuxbrew/lib/pkgconfig:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On -DENABLE_EMBEDDED_PCIIDS=On -DENABLE_EMBEDDED_AMDGPUIDS=On -DCMAKE_INSTALL_PREFIX=/usr .
- name: build project
run: cmake --build . --target package --verbose -j4
@@ -654,6 +659,68 @@ jobs:
name: fastfetch-windows-amd64
path: ./fastfetch-windows-amd64.*
windows-aarch64:
name: Windows-aarch64
runs-on: windows-11-arm
permissions:
security-events: write
contents: read
defaults:
run:
shell: msys2 {0}
steps:
- name: checkout repository
uses: actions/checkout@v4
- name: setup-msys2
uses: msys2/setup-msys2@v2
with:
msystem: CLANGARM64
update: true
install: git mingw-w64-clang-aarch64-7zip mingw-w64-clang-aarch64-cmake mingw-w64-clang-aarch64-clang mingw-w64-clang-aarch64-vulkan-loader mingw-w64-clang-aarch64-vulkan-headers mingw-w64-clang-aarch64-opencl-icd mingw-w64-clang-aarch64-opencl-headers mingw-w64-clang-aarch64-cppwinrt mingw-w64-clang-aarch64-imagemagick
- name: print msys version
run: uname -a
- name: configure project
run: env PKG_CONFIG_PATH=/clangarm64/lib/pkgconfig/:$PKG_CONFIG_PATH cmake -DSET_TWEAK=Off -DBUILD_TESTS=On .
- name: build project
run: cmake --build . --verbose -j4
- name: copy necessary dlls
run: cp /clangarm64/bin/{OpenCL,vulkan-1}.dll .
- name: list features
run: ./fastfetch --list-features
- name: run fastfetch
run: time ./fastfetch -c presets/ci.jsonc --stat false
- name: run fastfetch --format json
run: time ./fastfetch -c presets/ci.jsonc --format json
- name: run flashfetch
run: time ./flashfetch
- name: print dependencies
run: ldd fastfetch
- name: run tests
run: ctest --output-on-failure
- name: create zip archive
run: 7z a -tzip -mx9 -bd -y fastfetch-windows-aarch64.zip LICENSE *.dll fastfetch.exe flashfetch.exe presets
- name: create 7z archive
run: 7z a -t7z -mx9 -bd -y fastfetch-windows-aarch64.7z LICENSE *.dll fastfetch.exe flashfetch.exe presets
- name: upload artifacts
uses: actions/upload-artifact@v4
with:
name: fastfetch-windows-aarch64
path: ./fastfetch-windows-aarch64.*
release:
if: github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'fastfetch-cli/fastfetch'
name: Release
@@ -673,6 +740,7 @@ jobs:
- netbsd-amd64
- sunos-amd64
- windows-amd64
- windows-aarch64
permissions:
contents: write
steps:
+82 -1
View File
@@ -1,3 +1,84 @@
# 2.43.0
Features:
* Support physical core count and package count detection on Solaris (CPU, SunOS)
* Improve physical core count detection on FreeBSD (CPU, FreeBSD)
* Add option to hide unknown GPUs (GPU)
* Detect VRAM type of AMD GPUs on Linux (GPU, Linux)
* Support playing media detection on macOS 15.4 (#1737, Media, macOS)
* Whether it works on newer versions is unknown
* Detect player name for Windows UMP apps (Media, Windows)
Bugfixes:
* Fix disk usage detection on 32-bit Linux (#1734, Disk, Linux)
* Fix compiling on Asahi Linux (GPU, Linux)
* Fix duplicated playback status (Media, Linux)
* Don't show 255 in custom format when muted on macOS (#1750, Sound, macOS)
* Remove shared memory detection for AMD GPUs, which doesn't work as expected (GPU, Windows)
Logos:
* new AthenaOS
* add Hydra Framework
# 2.42.0
Changes:
* Normalize the module name `Bios` to `BIOS` (#1721)
* No configuration file changes are required because fastfetch parses module names case-insensitively.
Bugfixes:
* Disable disk type detection for virtual disks (PhysicalDisk, Linux, #1669)
* Fix incorrect CPU temperature reporting (CPU, OpenBSD)
* Fix setting `logo.chafa.symbols` in JSON configuration (Logo, #1709)
* Fix non-normalized time display (Uptime, #1720)
* Miscellaneous minor fixes
Features:
* Add CPU temperature detection support (CPU, SunOS)
* Improve CPU frequency detection (CPU, NetBSD)
* Add Wi-Fi detection support (Wifi, NetBSD)
* Add Webcam detection support (Camera, OpenBSD)
* Requires root privileges
Logos:
* Remove GoralixOS logo (#1699)
* Add Aurora logo (#1700)
* Add Codex Linux logo (#1701)
# 2.41.0
Changes:
* Due to [the deprecation](https://github.com/actions/runner-images/issues/11101), Linux x86_64 binaries are now built with Ubuntu 22.04 (Glibc 2.35, Debian 12)
* You can always build fastfetch yourself on your own. Please don't report bugs related to this change.
Features:
* Support physical core count detection on non-x86 platforms (CPU, Linux / FreeBSD)
* Support CPU frequency detection on PPC64 (CPU, FreeBSD)
* Support soar packages count detection (Packages, Linux)
* Support `~` path expanding on Windows (Logo, Windows)
* Support retrieving full user name (Title)
* Exposed with `--title-format '{full-user-name}'`
* Improve CPU (thermal zone) temperature detection on Windows (CPU, Windows)
* Administrator privileges are no longer needed
* Support base Wifi info detection on OpenBSD (Wifi, OpenBSD)
* To be tested
* Support GPU temperature detection for Intel dGPU on Linux (GPU, Linux)
* To be tested
* Add new ARM CPU part numbers (CPU, Linux)
* Add base implementation of Bluetooth device detection (Bluetooth, NetBSD, #1690)
* Some small improvements
Logo:
* Add anduinos
* Add 2 more Alpine logos
# 2.40.4
Bugfixes:
* Fix loading presets config on Windows (Windows, #1682)
* Regression of v2.40.0
* Remove the prefix `v` of Hyprland version on Arch Linux (WM, Linux)
# 2.40.3
Bugfixes:
@@ -844,7 +925,7 @@ Bugfixes:
* Fix some presets
* Better detection for XTerm terminal fonts (#1095, TerminalFont, Linux)
* Remove debug output (#1097, Windows)
* Fix command line option `--gpu-hide-type` doesn't work (#1098, GPU)
* Fix flag `--gpu-hide-type` doesn't work (#1098, GPU)
* Fix wrong date on Raspbian 10 (#1108, DateTime, Linux)
* Use `brightness` instead of `actuall_brightness` when detecting current brightness level (Brightness, Linux)
* Ref: https://bugzilla.kernel.org/show_bug.cgi?id=203905
+36 -8
View File
@@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.12.0) # target_link_libraries with OBJECT libs & project homepage url
project(fastfetch
VERSION 2.40.3
VERSION 2.43.0
LANGUAGES C
DESCRIPTION "Fast neofetch-like system information tool"
HOMEPAGE_URL "https://github.com/fastfetch-cli/fastfetch"
@@ -102,7 +102,7 @@ if(NOT BINARY_LINK_TYPE IN_LIST BINARY_LINK_TYPE_OPTIONS)
message(FATAL_ERROR "BINARY_LINK_TYPE must be one of ${BINARY_LINK_TYPE_OPTIONS}")
endif()
set(PACKAGE_MANAGERS AM APK BREW CHOCO DPKG EMERGE EOPKG FLATPAK GUIX LINGLONG LPKG LPKGBUILD MACPORTS NIX OPKG PACMAN PACSTALL PALUDIS PISI PKG PKGTOOL RPM SCOOP SNAP SORCERY WINGET XBPS)
set(PACKAGE_MANAGERS AM APK BREW CHOCO DPKG EMERGE EOPKG FLATPAK GUIX LINGLONG LPKG LPKGBUILD MACPORTS NIX OPKG PACMAN PACSTALL PALUDIS PISI PKG PKGTOOL RPM SCOOP SNAP SOAR SORCERY WINGET XBPS)
foreach(package_manager ${PACKAGE_MANAGERS})
if(package_manager STREQUAL "WINGET")
option(PACKAGES_DISABLE_${package_manager} "Disable ${package_manager} package manager detection by default" ON)
@@ -326,6 +326,11 @@ endif()
fastfetch_encode_c_string("${DATATEXT_JSON_HELP}" DATATEXT_JSON_HELP)
fastfetch_load_text(src/data/structure.txt DATATEXT_STRUCTURE)
if(APPLE)
# See src/detection/media/media_apple.m
fastfetch_load_text(src/data/nowPlaying.scptd DATATEXT_NOWPLAYING)
endif()
configure_file(src/fastfetch_config.h.in fastfetch_config.h @ONLY)
configure_file(src/fastfetch_datatext.h.in fastfetch_datatext.h @ONLY)
if(APPLE)
@@ -342,7 +347,6 @@ foreach(file ${LOGO_FILES})
fastfetch_load_text("${file}" content)
get_filename_component(file "${file}" NAME_WE)
string(TOUPPER "${file}" file)
string(REGEX REPLACE "\\$\\{c([0-9]+)\\}" "$\\1" content "${content}")
set(LOGO_BUILTIN_H "${LOGO_BUILTIN_H}#define FASTFETCH_DATATEXT_LOGO_${file} ${content}\n")
endforeach()
file(GENERATE OUTPUT logo_builtin.h CONTENT "${LOGO_BUILTIN_H}")
@@ -705,7 +709,7 @@ elseif(FreeBSD)
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_linux.c
src/detection/wm/wm_nosupport.c
src/detection/wm/wm_linux.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
src/detection/camera/camera_linux.c
@@ -734,7 +738,7 @@ elseif(NetBSD)
src/common/sysctl.c
src/detection/battery/battery_nbsd.c
src/detection/bios/bios_nbsd.c
src/detection/bluetooth/bluetooth_nosupport.c
src/detection/bluetooth/bluetooth_bsd.c
src/detection/bluetoothradio/bluetoothradio_nosupport.c
src/detection/board/board_nbsd.c
src/detection/bootmgr/bootmgr_bsd.c
@@ -797,7 +801,7 @@ elseif(NetBSD)
src/detection/uptime/uptime_bsd.c
src/detection/users/users_linux.c
src/detection/wallpaper/wallpaper_linux.c
src/detection/wifi/wifi_nosupport.c
src/detection/wifi/wifi_nbsd.c
src/detection/wm/wm_nosupport.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
@@ -879,7 +883,7 @@ elseif(OpenBSD)
src/detection/uptime/uptime_bsd.c
src/detection/users/users_obsd.c
src/detection/wallpaper/wallpaper_linux.c
src/detection/wifi/wifi_nosupport.c
src/detection/wifi/wifi_obsd.c
src/detection/wm/wm_nosupport.c
src/detection/de/de_linux.c
src/detection/wmtheme/wmtheme_linux.c
@@ -977,7 +981,6 @@ elseif(WIN32)
src/detection/btrfs/btrfs_nosupport.c
src/detection/chassis/chassis_windows.c
src/detection/cpu/cpu_windows.c
src/detection/cpu/cpu_windows.cpp
src/detection/cpucache/cpucache_windows.c
src/detection/cpuusage/cpuusage_windows.c
src/detection/cursor/cursor_windows.c
@@ -1589,7 +1592,15 @@ elseif(WIN32)
PRIVATE "cfgmgr32"
PRIVATE "winbrand"
PRIVATE "propsys"
PRIVATE "secur32"
PRIVATE "pdh"
)
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64")
# WoA only works on Windows 10 or higher
target_link_libraries(libfastfetch
PRIVATE "mincore"
)
endif()
elseif(FreeBSD)
target_link_libraries(libfastfetch
PRIVATE "m"
@@ -1613,6 +1624,7 @@ elseif(OpenBSD)
)
elseif(NetBSD)
target_link_libraries(libfastfetch
PRIVATE "bluetooth"
PRIVATE "m"
PRIVATE "prop"
)
@@ -1826,10 +1838,26 @@ if (BUILD_TESTS)
PRIVATE libfastfetch
)
add_executable(fastfetch-test-color
tests/color.c
)
target_link_libraries(fastfetch-test-color
PRIVATE libfastfetch
)
add_executable(fastfetch-test-duration
tests/duration.c
)
target_link_libraries(fastfetch-test-duration
PRIVATE libfastfetch
)
enable_testing()
add_test(NAME test-strbuf COMMAND fastfetch-test-strbuf)
add_test(NAME test-list COMMAND fastfetch-test-list)
add_test(NAME test-format COMMAND fastfetch-test-format)
add_test(NAME test-color COMMAND fastfetch-test-color)
add_test(NAME test-duration COMMAND fastfetch-test-duration)
endif()
##################
+54
View File
@@ -71,6 +71,10 @@ You may also download the program directly from [the GitHub releases page](https
* `pkg install fastfetch`
### NetBSD
* `pkgin in fastfetch`
### Android (Termux)
* `pkg install fastfetch`
@@ -230,6 +234,56 @@ Set the key to a white space.
}
```
### Q: How can I display images on Windows?
As of April 2025:
#### mintty and Wezterm
mintty (used by Bash on Windows and MSYS2) and Wezterm (nightly build only) support the iTerm image protocol on Windows.
In `config.jsonc`:
```json
{
"logo": {
"type": "iterm",
"source": "C:/path/to/image.png",
"width": <num-in-chars>
}
}
```
#### Windows Terminal
Windows Terminal supports the sixel image protocol only.
* If you installed fastfetch through MSYS2:
1. Install imagemagick: `pacman -S mingw-w64-<subsystem>-x86_64-imagemagick`
2. In `config.jsonc`:
```jsonc
{
"logo": {
"type": "sixel", // DO NOT USE "auto"
"source": "C:/path/to/image.png", // Do NOT use `~` as fastfetch is a native Windows program and doesn't apply cygwin path conversion
"width": <image-width-in-chars>, // Optional
"height": <image-height-in-chars> // Optional
}
}
```
* If you installed fastfetch via scoop or downloaded the binary directly from the GitHub Releases page:
1. Convert your image manually to sixel format using [any online image conversion service](https://www.google.com/search?q=convert+image+to+sixel)
2. In `config.jsonc`:
```jsonc
{
"logo": {
"type": "raw", // DO NOT USE "auto"
"source": "C:/path/to/image.sixel",
"width": <image-width-in-chars>, // Required
"height": <image-height-in-chars> // Required
}
}
```
### Q: I want feature A / B / C. Will fastfetch support it?
Fastfetch is a system information tool. We only accept hardware or system-level software feature requests. For most personal uses, I recommend using the `Command` module to implement custom functionality, which can be used to grab output from a custom shell script:
+24
View File
@@ -1,3 +1,27 @@
fastfetch (2.42.0) jammy; urgency=medium
* Update to 2.42.0
-- Carter Li <zhangsongcui@live.cn> Wed, 30 Apr 2025 14:08:57 +0800
fastfetch (2.41.0) jammy; urgency=medium
* Update to 2.41.0
-- Carter Li <zhangsongcui@live.cn> Wed, 16 Apr 2025 13:42:58 +0800
fastfetch (2.40.4) jammy; urgency=medium
* Update to 2.40.4
-- Carter Li <zhangsongcui@live.cn> Thu, 10 Apr 2025 15:38:21 +0800
fastfetch (2.40.3) jammy; urgency=medium
* Update to 2.40.3
-- Carter Li <zhangsongcui@live.cn> Mon, 07 Apr 2025 09:29:27 +0800
fastfetch (2.40.0) jammy; urgency=medium
* Update to 2.40.0
+1 -1
View File
@@ -1 +1 @@
fastfetch_2.40.0_source.buildinfo universe/utils optional
fastfetch_2.42.0_source.buildinfo universe/utils optional
+2 -1
View File
@@ -279,7 +279,7 @@
"type": "string"
},
"packagesFormat": {
"description": "Output format of the module `Packages`. See Wiki for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop}: Number of scoop packages\n 21. {choco}: Number of choco packages\n 22. {pkgtool}: Number of pkgtool packages\n 23. {paludis}: Number of paludis packages\n 24. {winget}: Number of winget packages\n 25. {opkg}: Number of opkg packages\n 26. {am-system}: Number of am-system packages\n 27. {sorcery}: Number of sorcery packages\n 28. {lpkg}: Number of lpkg packages\n 29. {lpkgbuild}: Number of lpkgbuild packages\n 30. {guix-system}: Number of guix-system packages\n 31. {guix-user}: Number of guix-user packages\n 32. {guix-home}: Number of guix-home packages\n 33. {linglong}: Number of linglong packages\n 34. {pacstall}: Number of pacstall packages\n 35. {mport}: Number of mport packages\n 36. {qi}: Number of qi packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {pkgsrc}: Number of pkgsrc packages\n 39. {hpkg-system}: Number of hpkg-system packages\n 40. {hpkg-user}: Number of hpkg-user packages\n 41. {pisi}: Number of pisi packages\n 42. {nix-all}: Total number of all nix packages\n 43. {flatpak-all}: Total number of all flatpak app packages\n 44. {brew-all}: Total number of all brew packages\n 45. {guix-all}: Total number of all guix packages\n 46. {hpkg-all}: Total number of all hpkg packages",
"description": "Output format of the module `Packages`. See Wiki for formatting syntax\n 1. {all}: Number of all packages\n 2. {pacman}: Number of pacman packages\n 3. {pacman-branch}: Pacman branch on manjaro\n 4. {dpkg}: Number of dpkg packages\n 5. {rpm}: Number of rpm packages\n 6. {emerge}: Number of emerge packages\n 7. {eopkg}: Number of eopkg packages\n 8. {xbps}: Number of xbps packages\n 9. {nix-system}: Number of nix-system packages\n 10. {nix-user}: Number of nix-user packages\n 11. {nix-default}: Number of nix-default packages\n 12. {apk}: Number of apk packages\n 13. {pkg}: Number of pkg packages\n 14. {flatpak-system}: Number of flatpak-system app packages\n 15. {flatpak-user}: Number of flatpak-user app packages\n 16. {snap}: Number of snap packages\n 17. {brew}: Number of brew packages\n 18. {brew-cask}: Number of brew-cask packages\n 19. {macports}: Number of macports packages\n 20. {scoop}: Number of scoop packages\n 21. {choco}: Number of choco packages\n 22. {pkgtool}: Number of pkgtool packages\n 23. {paludis}: Number of paludis packages\n 24. {winget}: Number of winget packages\n 25. {opkg}: Number of opkg packages\n 26. {am-system}: Number of am-system packages\n 27. {sorcery}: Number of sorcery packages\n 28. {lpkg}: Number of lpkg packages\n 29. {lpkgbuild}: Number of lpkgbuild packages\n 30. {guix-system}: Number of guix-system packages\n 31. {guix-user}: Number of guix-user packages\n 32. {guix-home}: Number of guix-home packages\n 33. {linglong}: Number of linglong packages\n 34. {pacstall}: Number of pacstall packages\n 35. {mport}: Number of mport packages\n 36. {qi}: Number of qi packages\n 37. {am-user}: Number of am-user (aka appman) packages\n 38. {pkgsrc}: Number of pkgsrc packages\n 39. {hpkg-system}: Number of hpkg-system packages\n 40. {hpkg-user}: Number of hpkg-user packages\n 41. {pisi}: Number of pisi packages\n 42. {soar}: Number of soar packages\n 43. {nix-all}: Total number of all nix packages\n 44. {flatpak-all}: Total number of all flatpak app packages\n 45. {brew-all}: Total number of all brew packages\n 46. {guix-all}: Total number of all guix packages\n 47. {hpkg-all}: Total number of all hpkg packages",
"type": "string"
},
"physicaldiskFormat": {
@@ -2053,6 +2053,7 @@
"enum": [
"integrated",
"discrete",
"unknown",
"none"
],
"default": "none"
+1 -1
View File
@@ -1,6 +1,6 @@
{
"home": "https://github.com/ibireme/yyjson",
"license": "MIT ( embed in source )",
"version": "0.10.0",
"version": "0.11.1",
"author": "ibireme"
}
+2508 -1264
View File
File diff suppressed because it is too large Load Diff
+800 -570
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -1,4 +1,5 @@
#include "fastfetch.h"
#include "common/init.h"
#include "common/parsing.h"
#include "common/thread.h"
#include "detection/displayserver/displayserver.h"
+7
View File
@@ -0,0 +1,7 @@
#pragma once
void ffInitInstance(void);
void ffStart(void);
void ffFinish(void);
void ffDestroyInstance(void);
void ffListFeatures(void);
+8
View File
@@ -147,6 +147,14 @@ ssize_t ffReadFileDataRelative(HANDLE dfd, const char* fileName, size_t dataSize
bool ffPathExpandEnv(const char* in, FFstrbuf* out)
{
if (in[0] == '~') {
if ((in[1] == '/' || in[1] == '\\' || in[1] == '\0') && !ffStrContainsC(in, '%')) {
ffStrbufSet(out, &instance.state.platform.homeDir);
ffStrbufAppendS(out, in + 1);
return true;
}
}
DWORD length = ExpandEnvironmentStringsA(in, NULL, 0);
if (length <= 1) return false;
+30
View File
@@ -177,6 +177,7 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
if (ffCharIsEnglishAlphabet(value[0]))
{
FF_APPEND_COLOR_CODE_COND(reset_, FF_COLOR_MODE_RESET)
else FF_APPEND_COLOR_CODE_COND(bold_, FF_COLOR_MODE_BOLD)
else FF_APPEND_COLOR_CODE_COND(bright_, FF_COLOR_MODE_BOLD)
else FF_APPEND_COLOR_CODE_COND(dim_, FF_COLOR_MODE_DIM)
else FF_APPEND_COLOR_CODE_COND(italic_, FF_COLOR_MODE_ITALIC)
@@ -212,6 +213,35 @@ void ffOptionParseColorNoClear(const char* value, FFstrbuf* buffer)
exit(479);
}
}
else if (value[0] == '#')
{
// RGB color
++value;
char* pend = NULL;
uint32_t rgb = (uint32_t) strtoul(value, &pend, 16);
if (pend == value) {
fprintf(stderr, "Error: invalid RGB color code found: %s\n", value);
exit(479);
}
if (pend - value > 6) {
fprintf(stderr, "Error: RGB color code too long: %s\n", value);
exit(479);
}
else if (pend - value == 3) {
rgb = ((rgb & 0xF00) >> 8) * 0x110000 +
((rgb & 0x0F0) >> 4) * 0x001100 +
((rgb & 0x00F) >> 0) * 0x000011;
}
else if (pend - value != 6) {
fprintf(stderr, "Error: invalid RGB color code length: %s\n", value);
exit(479);
}
uint32_t r = rgb >> 16, g = (rgb >> 8) & 0xFF, b = rgb & 0xFF;
ffStrbufAppendF(buffer, FF_COLOR_FG_RGB "%u;%u;%u", r, g, b);
value = pend;
continue;
}
ffStrbufAppendC(buffer, *value);
++value;
+15 -8
View File
@@ -190,19 +190,26 @@ void ffParseGTK(FFstrbuf* buffer, const FFstrbuf* gtk2, const FFstrbuf* gtk3, co
}
}
void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result)
void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result)
{
if(days == 0 && hours == 0 && minutes == 0)
if(totalSeconds < 60)
{
ffStrbufAppendF(result, "%u seconds", seconds);
ffStrbufAppendF(result, "%u second", (unsigned) totalSeconds);
if (totalSeconds != 1)
ffStrbufAppendC(result, 's');
return;
}
if(seconds >= 30)
{
minutes++;
seconds = 0;
}
uint32_t seconds = (uint32_t) (totalSeconds % 60);
totalSeconds /= 60;
if (seconds >= 30)
totalSeconds++;
uint32_t minutes = (uint32_t) (totalSeconds % 60);
totalSeconds /= 60;
uint32_t hours = (uint32_t) (totalSeconds % 24);
totalSeconds /= 24;
uint32_t days = (uint32_t) totalSeconds;
if(days > 0)
{
+1 -1
View File
@@ -27,4 +27,4 @@ int8_t ffVersionCompare(const FFVersion* version1, const FFVersion* version2);
void ffParseSize(uint64_t bytes, FFstrbuf* result);
bool ffParseFrequency(uint32_t mhz, FFstrbuf* result);
void ffParseDuration(uint32_t days, uint32_t hours, uint32_t minutes, uint32_t seconds, FFstrbuf* result);
void ffParseDuration(uint64_t totalSeconds, FFstrbuf* result);
+5 -9
View File
@@ -1,5 +1,6 @@
#include "fastfetch.h"
#include "common/printing.h"
#include "logo/logo.h"
#include "util/textModifier.h"
void ffPrintLogoAndKey(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType)
@@ -99,7 +100,7 @@ void ffPrintFormat(const char* moduleName, uint8_t moduleIndex, const FFModuleAr
ffStrbufPutTo(&buffer, stdout);
}
static void printError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, va_list arguments)
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
{
if(!instance.config.display.showErrors)
return;
@@ -109,7 +110,10 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFModu
if(!instance.config.display.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_ERROR, stdout);
va_list arguments;
va_start(arguments, message);
vprintf(message, arguments);
va_end(arguments);
if(!instance.config.display.pipe)
fputs(FASTFETCH_TEXT_MODIFIER_RESET, stdout);
@@ -117,14 +121,6 @@ static void printError(const char* moduleName, uint8_t moduleIndex, const FFModu
putchar('\n');
}
void ffPrintError(const char* moduleName, uint8_t moduleIndex, const FFModuleArgs* moduleArgs, FFPrintType printType, const char* message, ...)
{
va_list arguments;
va_start(arguments, message);
printError(moduleName, moduleIndex, moduleArgs, printType, message, arguments);
va_end(arguments);
}
void ffPrintColor(const FFstrbuf* colorValue)
{
//If the color is not set, this would reset in \033[m, which resets everything.
+11 -2
View File
@@ -130,7 +130,11 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
switch (GetLastError())
{
case ERROR_IO_PENDING:
if (!timeout || WaitForSingleObject(hChildPipeRead, (DWORD) timeout) != WAIT_OBJECT_0)
#if __aarch64__
if (!GetOverlappedResultEx(hChildPipeRead, &overlapped, &nRead, timeout < 0 ? INFINITE : (DWORD) timeout, FALSE))
#else
// To support Windows 7
if (timeout >= 0 && WaitForSingleObject(hChildPipeRead, (DWORD) timeout) != WAIT_OBJECT_0)
{
CancelIo(hChildPipeRead);
TerminateProcess(hProcess, 1);
@@ -138,13 +142,18 @@ const char* ffProcessAppendOutput(FFstrbuf* buffer, char* const argv[], bool use
}
if (!GetOverlappedResult(hChildPipeRead, &overlapped, &nRead, FALSE))
#endif
{
if (GetLastError() == ERROR_BROKEN_PIPE)
return NULL;
CancelIo(hChildPipeRead);
TerminateProcess(hProcess, 1);
return "GetOverlappedResult(hChildPipeRead) failed";
return "GetOverlappedResult"
#if __aarch64__
"Ex"
#endif
"(hChildPipeRead) failed";
}
break;
+2 -1
View File
@@ -1139,12 +1139,13 @@
},
{
"long": "gpu-hide-type",
"desc": "Specify which types of GPUs should not be displayed",
"desc": "Specify which types of GPUs should not be displayed (default: all GPUs are shown, regardless of recognition)",
"arg": {
"type": "enum",
"enum": {
"integrated": "Hide integrated GPUs",
"discrete": "Hide discrete GPUs",
"unknown": "Hide unknown (unrecognized) GPUs",
"none": "Do not hide any GPUs"
},
"default": "none"
+24
View File
@@ -0,0 +1,24 @@
use scripting additions
use framework "/System/Library/PrivateFrameworks/MediaRemote.framework"
set MRNowPlayingRequest to current application's NSClassFromString("MRNowPlayingRequest")
if MRNowPlayingRequest's localNowPlayingItem() is missing value then
return
end if
if MRNowPlayingRequest's localIsPlaying() then
set status to "Playing"
else
set status to "Paused"
end if
set infoDict to MRNowPlayingRequest's localNowPlayingItem()'s nowPlayingInfo()
set bundleObj to MRNowPlayingRequest's localNowPlayingPlayerPath()'s client()
return status & "
" & (infoDict's valueForKey:"kMRMediaRemoteNowPlayingInfoTitle" as text) & "
" & (infoDict's valueForKey:"kMRMediaRemoteNowPlayingInfoArtist" as text) & "
" & (infoDict's valueForKey:"kMRMediaRemoteNowPlayingInfoAlbum" as text) & "
" & (bundleObj's bundleIdentifier() as text) & "
" & (bundleObj's displayName() as text)
+7 -1
View File
@@ -6,7 +6,13 @@
static int enumDev(FF_MAYBE_UNUSED int sockfd, struct bt_devinfo const* dev, FFlist* devices)
{
FFBluetoothResult* device = ffListAdd(devices);
ffStrbufInitS(&device->name, bt_devremote_name_gen(dev->devname, &dev->bdaddr));
ffStrbufInitS(&device->name,
#if __FreeBSD__
bt_devremote_name_gen(dev->devname, &dev->bdaddr)
#else
dev->devname
#endif
);
ffStrbufInitS(&device->address, bt_ntoa(&dev->bdaddr, NULL));
ffStrbufUpperCase(&device->address);
ffStrbufInit(&device->type);
+1 -1
View File
@@ -232,7 +232,7 @@ static uint32_t connectedDevices(void)
#endif
const char* ffDetectBluetooth(FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
const char* ffDetectBluetooth(FF_MAYBE_UNUSED FFBluetoothOptions* options, FF_MAYBE_UNUSED FFlist* devices /* FFBluetoothResult */)
{
#ifdef FF_HAVE_DBUS
int32_t connectedCount = -1;
+10 -1
View File
@@ -7,6 +7,9 @@
#if FF_HAVE_LINUX_VIDEODEV2
#include <linux/videodev2.h>
#elif __has_include(<sys/videoio.h>) // OpenBSD
#include <sys/videoio.h>
#define FF_HAVE_LINUX_VIDEODEV2 1
#endif
const char* ffDetectCamera(FFlist* result)
@@ -19,7 +22,13 @@ const char* ffDetectCamera(FFlist* result)
path[ARRAY_SIZE(path) - 2] = (char) (i + '0');
FF_AUTO_CLOSE_FD int fd = open(path, O_RDONLY);
if (fd < 0)
break;
{
if (errno == ENOENT)
break;
if (errno == ENXIO)
continue;
return "Failed to open /dev/videoN";
}
struct v4l2_capability cap = {};
if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 || !(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE))
+6
View File
@@ -106,9 +106,14 @@ static const char* armPartId2name(uint32_t partId)
case 0xd80: return "Cortex-A520";
case 0xd81: return "Cortex-A720";
case 0xd82: return "Cortex-X4";
case 0xd83: return "Neoverse-V3AE";
case 0xd84: return "Neoverse-V3";
case 0xd85: return "Cortex-X925";
case 0xd87: return "Cortex-A725";
case 0xd88: return "Cortex-A520AE";
case 0xd89: return "Cortex-A720AE";
case 0xd8e: return "Neoverse-N3";
case 0xd8f: return "Cortex-A320";
default: return NULL;
}
}
@@ -314,6 +319,7 @@ static const char* fujitsuPartId2name(uint32_t partId)
switch (partId)
{
case 0x001: return "A64FX";
case 0x003: return "MONAKA";
default: return NULL;
}
}
+36 -23
View File
@@ -1,5 +1,6 @@
#include "cpu.h"
#include "common/sysctl.h"
#include "util/stringUtils.h"
#include <sys/param.h>
#if __has_include(<sys/cpuset.h>)
@@ -34,36 +35,30 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if (ffSysctlGetString("hw.model", &cpu->name) != NULL)
return "sysctlbyname(hw.model) failed";
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresLogical = cpu->coresPhysical;
cpu->coresLogical = (uint16_t) ffSysctlGetInt("hw.ncpu", 1);
cpu->coresPhysical = (uint16_t) ffSysctlGetInt("kern.smp.cores", 0);
cpu->coresOnline = (uint16_t) ffSysctlGetInt("kern.smp.cpus", cpu->coresLogical);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
if (ffSysctlGetString("kern.sched.topology_spec", &buffer) == NULL && buffer.length > 0)
{
// <groups>
// <group level="1" cache-level="3">
// <cpu count="4" mask="f,0,0,0">0, 1, 2, 3</cpu>
// <children>
// <group level="2" cache-level="2">
// <cpu count="2" mask="3,0,0,0">0, 1</cpu>
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
// </group>
// <group level="2" cache-level="2">
// <cpu count="2" mask="c,0,0,0">2, 3</cpu>
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
// </group>
// </children>
// </group>
// <group level="1" cache-level="3">
// <cpu count="4" mask="f,0,0,0">0, 1, 2, 3</cpu>
// <children>
// <group level="2" cache-level="2">
// <cpu count="2" mask="3,0,0,0">0, 1</cpu>
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
// </group>
// <group level="2" cache-level="2">
// <cpu count="2" mask="c,0,0,0">2, 3</cpu>
// <flags><flag name="THREAD">THREAD group</flag><flag name="SMT">SMT group</flag></flags>
// </group>
// </children>
// </group>
// </groups>
uint32_t i = 0;
while (true)
{
i = ffStrbufNextIndexS(&buffer, i, "<flag name=\"THREAD\">THREAD group</flag>"); // Find physical core with hyper-threading enabled
if (i >= buffer.length) break;
cpu->coresPhysical--;
i += (uint32_t) strlen("<flag name=\"THREAD\">THREAD group</flag>");
}
for (char* p = buffer.chars; (p = strstr(p, "\n </group>\n")); ++p)
cpu->packages++;
}
#if FF_HAVE_CPUSET && (__x86_64__ || __i386__)
@@ -79,6 +74,24 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
uint32_t clockrate = (uint32_t) ffSysctlGetInt("hw.clockrate", 0);
if (clockrate > cpu->frequencyBase) cpu->frequencyBase = clockrate;
for (uint16_t i = 0; i < cpu->coresLogical; ++i)
{
ffStrbufClear(&buffer);
char key[32];
snprintf(key, sizeof(key), "dev.cpu.%u.freq_levels", i);
if (ffSysctlGetString(key, &buffer) == NULL)
{
if (buffer.length == 0) continue;
// MHz/Watts pairs like: 2501/32000 2187/27125 2000/24000
uint32_t fmax = (uint32_t) strtoul(buffer.chars, NULL, 10);
if (cpu->frequencyMax < fmax) cpu->frequencyMax = fmax;
}
else
break;
}
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp)
+85 -7
View File
@@ -9,6 +9,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#define FF_CPUINFO_PATH "/proc/cpuinfo"
@@ -432,11 +433,11 @@ FF_MAYBE_UNUSED static uint16_t getPackageCount(FFstrbuf* cpuinfo)
{
p += strlen("\nphysical id\t:");
char* pend;
unsigned long id = strtoul(p, &pend, 10);
unsigned long long id = strtoul(p, &pend, 10);
if (__builtin_expect(id > 64, false)) // Do 129-socket boards exist?
high |= 1 << (id - 64);
high |= 1ULL << (id - 64);
else
low |= 1 << id;
low |= 1ULL << id;
p = pend;
}
@@ -458,9 +459,7 @@ FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFC
cpu->coresOnline = (uint16_t) get_nprocs();
cpu->packages = getPackageCount(&cpuinfo);
cpu->coresPhysical = (uint16_t) ffStrbufToUInt(&physicalCoresBuffer, 0); // physical cores in single package
if (cpu->coresPhysical == 0)
cpu->coresPhysical = cpu->coresLogical;
else if (cpu->packages > 1)
if (cpu->coresPhysical > 0 && cpu->packages > 1)
cpu->coresPhysical *= cpu->packages;
// Ref https://github.com/fastfetch-cli/fastfetch/issues/1194#issuecomment-2295058252
@@ -473,6 +472,82 @@ FF_MAYBE_UNUSED static const char* detectCPUX86(const FFCPUOptions* options, FFC
#else
static const char* detectPhysicalCores(FFCPUResult* cpu)
{
int dfd = open("/sys/devices/system/cpu/", O_RDONLY | O_DIRECTORY);
if (dfd < 0) return "open(\"/sys/devices/system/cpu/\") failed";
FF_AUTO_CLOSE_DIR DIR* dir = fdopendir(dfd);
if (!dir) return "fdopendir(dfd) failed";
uint64_t pkgLow = 0, pkgHigh = 0;
struct dirent* entry;
FF_LIST_AUTO_DESTROY cpuList = ffListCreate(sizeof(uint32_t));
while ((entry = readdir(dir)) != NULL)
{
if (entry->d_type != DT_DIR || !ffStrStartsWith(entry->d_name, "cpu") || !ffCharIsDigit(entry->d_name[strlen("cpu")]))
continue;
FF_AUTO_CLOSE_FD int cpuxfd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_DIRECTORY);
if (cpuxfd < 0)
continue;
char buf[128];
// Check if the directory contains a file named "topology/physical_package_id"
// that lists the physical package id of the CPU.
ssize_t len = ffReadFileDataRelative(cpuxfd, "topology/physical_package_id", sizeof(buf) - 1, buf);
if (len > 0)
{
buf[len] = '\0';
unsigned long long id = strtoul(buf, NULL, 10);
if (__builtin_expect(id > 64, false)) // Do 129-socket boards exist?
pkgHigh |= 1ULL << (id - 64);
else
pkgLow |= 1ULL << id;
}
// Check if the directory contains a file named "topology/core_cpus_list"
// that lists the physical cores in the package.
len = ffReadFileDataRelative(cpuxfd, "topology/core_cpus_list", sizeof(buf) - 1, buf);
if (len > 0)
{
buf[len] = '\0'; // low-high or low
for (const char* p = buf; *p;)
{
char* pend;
uint32_t coreId = (uint32_t) strtoul(p, &pend, 10);
if (pend == p) break;
bool found = false;
FF_LIST_FOR_EACH(uint32_t, id, cpuList)
{
if (*id == coreId)
{
// This core is already counted
found = true;
break;
}
}
if (!found)
*(uint32_t*) ffListAdd(&cpuList) = coreId;
p = strchr(pend, ',');
if (!p) break;
++p;
}
}
}
cpu->coresPhysical = (uint16_t) cpuList.length;
cpu->packages = (uint16_t) (__builtin_popcountll(pkgLow) + __builtin_popcountll(pkgHigh));
return NULL;
}
FF_MAYBE_UNUSED static void parseIsa(FFstrbuf* cpuIsa)
{
// Always use the last part of the ISA string. Ref: #590 #1204
@@ -601,7 +676,7 @@ FF_MAYBE_UNUSED static uint16_t getLoongarchPropCount(FFstrbuf* cpuinfo, const c
FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options, FFCPUResult* cpu)
{
cpu->coresPhysical = cpu->coresLogical = (uint16_t) get_nprocs_conf();
cpu->coresLogical = (uint16_t) get_nprocs_conf();
cpu->coresOnline = (uint16_t) get_nprocs();
#if __ANDROID__
@@ -663,6 +738,9 @@ FF_MAYBE_UNUSED static const char* detectCPUOthers(const FFCPUOptions* options,
#endif
}
if (cpu->coresPhysical == 0)
detectPhysicalCores(cpu);
return NULL;
}
#endif
+1
View File
@@ -67,6 +67,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
uint32_t freq = (uint32_t) ffSysctlGetInt("machdep.cpu.frequency.target", 0);
if (freq == 0) freq = (uint32_t) (ffSysctlGetInt64("hw.cpu0.clock_frequency", 0) / 1000000);
if (freq == 0) freq = (uint32_t) ffSysctlGetInt("machdep.dmi.processor-frequency", 0);
if (freq > cpu->frequencyBase) cpu->frequencyBase = freq;
cpu->temperature = FF_CPU_TEMP_UNSET;
+45 -8
View File
@@ -1,10 +1,53 @@
#include "cpu.h"
#include "common/sysctl.h"
#include "util/stringUtils.h"
#include <errno.h>
#include <sys/time.h>
#include <sys/sensors.h>
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
static const char* detectCPUTemp(FFCPUResult* cpu)
{
int mib[5] = {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0};
for (mib[2] = 0; mib[2] < 1024; mib[2]++)
{
struct sensordev sensordev;
size_t sdlen = sizeof(struct sensordev);
if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) < 0)
{
if (errno == ENOENT)
break;
if (errno == ENXIO)
continue;
return "sysctl(sensordev) failed";
}
if (!ffStrStartsWith(sensordev.xname, "cpu"))
continue;
for (mib[4] = 0; mib[4] < sensordev.maxnumt[SENSOR_TEMP]; mib[4]++)
{
struct sensor sensor;
size_t slen = sizeof(struct sensor);
if (sysctl(mib, 5, &sensor, &slen, NULL, 0) < 0)
{
if (errno != ENOENT)
return "sysctl(sensor) failed";
continue;
}
if (sensor.flags & SENSOR_FINVALID)
continue;
cpu->temperature = (double)(sensor.value - 273150000) / 1E6;
return NULL;
}
}
return "No sensor for CPU temp found";
}
const char *ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
if (ffSysctlGetString(CTL_HW, HW_MODEL, &cpu->name))
return "sysctl(hw.model) failed";
@@ -19,13 +62,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
if (cpuspeed > cpu->frequencyBase) cpu->frequencyBase = cpuspeed;
cpu->temperature = FF_CPU_TEMP_UNSET;
if (options->temp)
{
struct sensor sensors;
size_t size = sizeof(sensors);
if (sysctl((int[]) {CTL_HW, HW_SENSORS, 0, SENSOR_TEMP, 0}, 5, &sensors, &size, NULL, 0) == 0)
cpu->temperature = (double) (sensors.value - 273150000) / 1E6;
}
if (options->temp) detectCPUTemp(cpu);
return NULL;
}
+104 -2
View File
@@ -1,6 +1,60 @@
#include "cpu.h"
#include "common/processing.h"
#include "util/stringUtils.h"
#include <kstat.h>
static const char* detectCPUTempByKstat(kstat_ctl_t* kc, FFCPUResult* cpu)
{
const char* possibleModules[] = {"temperature", "cpu_temp", "acpi_thermal", NULL};
for (int i = 0; possibleModules[i] != NULL; i++) {
kstat_t* ks = kstat_lookup(kc, possibleModules[i], -1, NULL);
if (ks && kstat_read(kc, ks, NULL) >= 0) {
kstat_named_t* kn = kstat_data_lookup(ks, "temperature");
if (kn) {
switch (kn->data_type) {
case KSTAT_DATA_INT32:
cpu->temperature = (float)kn->value.i32;
return NULL;
case KSTAT_DATA_UINT32:
cpu->temperature = (float)kn->value.ui32;
return NULL;
case KSTAT_DATA_FLOAT:
cpu->temperature = kn->value.f;
return NULL;
}
}
}
}
return "Failed to find CPU temperature using kstat";
}
static const char* detectCPUTempByIpmiTool(FFCPUResult* cpu)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]){
"ipmitool",
"-c",
"sdr",
"list",
NULL
});
if (error)
return error;
char* line = NULL;
size_t len = 0;
while (ffStrbufGetline(&line, &len, &buffer))
{
if (sscanf(line, "CPU%*d Temp,%lf,degrees C,ok", &cpu->temperature) == 1)
return NULL;
}
return "ipmitool sdr list failed to find CPU temperature";
}
static inline void kstatFreeWrap(kstat_ctl_t** pkc)
{
assert(pkc);
@@ -8,7 +62,46 @@ static inline void kstatFreeWrap(kstat_ctl_t** pkc)
kstat_close(*pkc);
}
const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPUResult* cpu)
static inline uint16_t countTypeId(kstat_ctl_t* kc, const char* type)
{
uint64_t low = 0, high = 0;
for (kstat_t* ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
{
if (ffStrStartsWith(ksp->ks_module, "cpu_info"))
{
if (kstat_read(kc, ksp, NULL) < 0)
continue;
kstat_named_t* stat = kstat_data_lookup(ksp, type);
if (!stat)
continue;
uint32_t id = 0;
switch (stat->data_type)
{
#ifdef _INT64_TYPE
case KSTAT_DATA_INT64:
case KSTAT_DATA_UINT64:
id = (uint32_t) stat->value.ui64;
break;
#endif
case KSTAT_DATA_INT32:
case KSTAT_DATA_UINT32:
id = stat->value.ui32;
break;
default:
continue;
}
if (__builtin_expect(id > 64, false))
high |= 1ULL << (id - 64);
else
low |= 1ULL << id;
}
}
return (uint16_t) (__builtin_popcountll(low) + __builtin_popcountll(high));
}
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
__attribute__((__cleanup__(kstatFreeWrap))) kstat_ctl_t* kc = kstat_open();
if (!kc)
@@ -40,7 +133,16 @@ const char* ffDetectCPUImpl(FF_MAYBE_UNUSED const FFCPUOptions* options, FFCPURe
if (ks && kstat_read(kc, ks, NULL) >= 0)
{
kstat_named_t* kn = kstat_data_lookup(ks, "ncpus");
if (kn) cpu->coresLogical = cpu->coresPhysical = cpu->coresOnline = (uint16_t) kn->value.ui32;
if (kn) cpu->coresLogical = cpu->coresOnline = (uint16_t) kn->value.ui32;
}
cpu->packages = countTypeId(kc, "chip_id");
cpu->coresPhysical = countTypeId(kc, "core_id");
if (options->temp)
{
if (detectCPUTempByKstat(kc, cpu) != NULL)
detectCPUTempByIpmiTool(cpu);
}
return NULL;
+41 -3
View File
@@ -4,6 +4,46 @@
#include "util/mallocHelper.h"
#include "util/smbiosHelper.h"
#include <pdh.h>
static void ffPdhOpenCloseQuery(HQUERY* query)
{
assert(query);
if (*query)
{
PdhCloseQuery(*query);
*query = NULL;
}
}
static const char* detectThermalTemp(double* result)
{
// typeperf.exe -sc 1 "\Thermal Zone Information(*)\Temperature"
__attribute__((__cleanup__(ffPdhOpenCloseQuery))) HQUERY query = NULL;
if (PdhOpenQueryW(NULL, 0, &query) != ERROR_SUCCESS)
return "Failed to open PDH query";
HCOUNTER counter = NULL;
if (PdhAddEnglishCounterW(query,
L"\\Thermal Zone Information(*)\\Temperature",
0,
&counter) != ERROR_SUCCESS)
return "Failed to add TZI temperature counter";
if (PdhCollectQueryData(query) != ERROR_SUCCESS)
return "Failed to collect query data";
PDH_FMT_COUNTERVALUE value;
if (PdhGetFormattedCounterValue(counter, PDH_FMT_DOUBLE, NULL, &value) != ERROR_SUCCESS)
return "Failed to format counter value";
*result = value.doubleValue - 273;
return NULL;
}
// 7.5
typedef struct FFSmbiosProcessorInfo
{
@@ -165,8 +205,6 @@ static const char* detectCoreTypes(FFCPUResult* cpu)
return NULL;
}
const char* detectThermalTemp(double* current, double* critical);
const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
{
detectNCores(cpu);
@@ -182,7 +220,7 @@ const char* ffDetectCPUImpl(const FFCPUOptions* options, FFCPUResult* cpu)
detectMaxSpeedBySmbios(cpu);
if(options->temp)
detectThermalTemp(&cpu->temperature, NULL);
detectThermalTemp(&cpu->temperature);
return NULL;
}
-34
View File
@@ -1,34 +0,0 @@
#include "util/windows/wmi.hpp"
extern "C"
const char* detectThermalTemp(double* current, double* critical)
{
// Requires Administrator privileges
// https://wutils.com/wmi/root/wmi/msacpi_thermalzonetemperature/#properties
FFWmiQuery query(L"SELECT CurrentTemperature, CriticalTripPoint FROM MSAcpi_ThermalZoneTemperature WHERE Active = TRUE", nullptr, FFWmiNamespace::WMI);
if(!query)
return "Query WMI service failed";
if(FFWmiRecord record = query.next())
{
if (current)
{
if(auto vtCurrent = record.get(L"CurrentTemperature"))
*current = vtCurrent.get<int32_t>() / 10 - 273.15; // In tenth of degrees Kelvin
else
*current = 0.0/0.0;
}
if (critical)
{
if(auto vtCritical = record.get(L"CriticalTripPoint"))
*critical = vtCritical.get<int32_t>() / 10 - 273.15; // In tenth of degrees Kelvin
else
*critical = 0.0/0.0;
}
return NULL;
}
return "No WMI result returned";
}
+3 -3
View File
@@ -240,9 +240,9 @@ static void detectStats(FFDisk* disk)
if(statvfs(disk->mountpoint.chars, &fs) != 0)
memset(&fs, 0, sizeof(fs)); //Set all values to 0, so our values get initialized to 0 too
disk->bytesTotal = fs.f_blocks * fs.f_frsize;
disk->bytesFree = fs.f_bfree * fs.f_frsize;
disk->bytesAvailable = fs.f_bavail * fs.f_frsize;
disk->bytesTotal = fs.f_blocks * (uint64_t) fs.f_frsize;
disk->bytesFree = fs.f_bfree * (uint64_t) fs.f_frsize;
disk->bytesAvailable = fs.f_bavail * (uint64_t) fs.f_frsize;
disk->bytesUsed = 0; // To be filled in ./disk.c
if (fs.f_files >= fs.f_ffree)
+5 -1
View File
@@ -335,6 +335,7 @@ const char* ffdsConnectXcbRandr(FFDisplayServerResult* result)
{
FF_LIBRARY_LOAD(xcbRandr, "dlopen libxcb-randr failed", "libxcb-randr" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcbRandr, xcb_connect)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcbRandr, xcb_connection_has_error)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcbRandr, xcb_get_setup)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcbRandr, xcb_setup_roots_iterator)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcbRandr, xcb_screen_next)
@@ -368,8 +369,11 @@ const char* ffdsConnectXcbRandr(FFDisplayServerResult* result)
data.connection = ffxcb_connect(NULL, NULL);
if(data.connection == NULL)
if(ffxcb_connection_has_error(data.connection) > 0)
{
ffxcb_disconnect(data.connection);
return "xcb_connect() failed";
}
data.result = result;
-3
View File
@@ -20,9 +20,6 @@ extern int ADL2_Adapter_Graphic_Core_Info_Get(ADL_CONTEXT_HANDLE context, int iA
// Function to retrieve memory information from the adapter. Version 2
extern int ADL2_Adapter_MemoryInfo2_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, ADLMemoryInfo2* lpMemoryInfo2);
// This function retrieves the VRAM usage of given adapter.
extern int ADL2_Adapter_VRAMUsage_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iVRAMUsageInMB);
// This function retrieves the Dedicated VRAM usage of given adapter.
extern int ADL2_Adapter_DedicatedVRAMUsage_Get(ADL_CONTEXT_HANDLE context, int iAdapterIndex, int* iVRAMUsageInMB);
File diff suppressed because it is too large Load Diff
+1 -20
View File
@@ -49,7 +49,6 @@ struct FFAdlData {
FF_LIBRARY_SYMBOL(ADL2_Adapter_Graphic_Core_Info_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_MemoryInfo2_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_DedicatedVRAMUsage_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_VRAMUsage_Get)
FF_LIBRARY_SYMBOL(ADL2_Adapter_ASICFamilyType_Get)
FF_LIBRARY_SYMBOL(ADL2_Overdrive_Caps)
FF_LIBRARY_SYMBOL(ADL2_OverdriveN_CapabilitiesX2_Get)
@@ -91,7 +90,6 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_Graphic_Core_Info_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_MemoryInfo2_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_DedicatedVRAMUsage_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_VRAMUsage_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Adapter_ASICFamilyType_Get)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_Overdrive_Caps)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(atiadl, adlData, ADL2_OverdriveN_CapabilitiesX2_Get)
@@ -188,29 +186,12 @@ const char* ffDetectAmdGpuInfo(const FFGpuDriverCondition* cond, FFGpuDriverResu
FF_DEBUG("ADL2_Adapter_DedicatedVRAMUsage_Get returned %s (%d), usage: %d MB",
ffAdlStatusToString(status), status, vramUsage);
if (status == ADL_OK) {
if (status == ADL_OK && vramUsage >= 0) {
result.memory->used = (uint64_t) vramUsage * 1024 * 1024;
FF_DEBUG("Dedicated VRAM usage: %llu bytes (%d MB)", result.memory->used, vramUsage);
} else {
FF_DEBUG("Failed to get dedicated VRAM usage");
}
if (result.sharedMemory)
{
vramUsage = 0;
status = adlData.ffADL2_Adapter_VRAMUsage_Get(adlData.apiHandle, device->iAdapterIndex, &vramUsage);
FF_DEBUG("ADL2_Adapter_VRAMUsage_Get returned %s (%d), usage: %d MB",
ffAdlStatusToString(status), status, vramUsage);
if (status == ADL_OK) {
uint64_t totalUsage = (uint64_t) vramUsage * 1024 * 1024;
result.sharedMemory->used = totalUsage - result.memory->used;
FF_DEBUG("Total VRAM usage: %llu bytes, Shared VRAM usage: %llu bytes (%llu MB)",
totalUsage, result.sharedMemory->used, result.sharedMemory->used / (1024 * 1024));
} else {
FF_DEBUG("Failed to get total VRAM usage");
}
}
}
if (result.memoryType)
-91
View File
@@ -1,91 +0,0 @@
#if __aarch64__ && FF_HAVE_DRM
#include <drm.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#if __has_include(<drm/asahi_drm.h>)
#include <drm/asahi_drm.h>
#else
// https://github.com/AsahiLinux/linux/blob/asahi/include/uapi/drm/asahi_drm.h
/* SPDX-License-Identifier: MIT */
/* Copyright (C) The Asahi Linux Contributors */
#define DRM_ASAHI_UNSTABLE_UABI_VERSION 10011
#define DRM_ASAHI_GET_PARAMS 0x00
#define DRM_ASAHI_MAX_CLUSTERS 32
struct drm_asahi_params_global
{
__u32 unstable_uabi_version;
__u32 pad0;
__u64 feat_compat;
__u64 feat_incompat;
__u32 gpu_generation;
__u32 gpu_variant;
__u32 gpu_revision;
__u32 chip_id;
__u32 num_dies;
__u32 num_clusters_total;
__u32 num_cores_per_cluster;
__u32 num_frags_per_cluster;
__u32 num_gps_per_cluster;
__u32 num_cores_total_active;
__u64 core_masks[DRM_ASAHI_MAX_CLUSTERS];
__u32 vm_page_size;
__u32 pad1;
__u64 vm_user_start;
__u64 vm_user_end;
__u64 vm_usc_start;
__u64 vm_usc_end;
__u64 vm_kernel_min_size;
__u32 max_syncs_per_submission;
__u32 max_commands_per_submission;
__u32 max_commands_in_flight;
__u32 max_attachments;
__u32 timer_frequency_hz;
__u32 min_frequency_khz;
__u32 max_frequency_khz;
__u32 max_power_mw;
__u32 result_render_size;
__u32 result_compute_size;
__u32 firmware_version[4];
};
struct drm_asahi_get_params
{
/** @extensions: Pointer to the first extension struct, if any */
__u64 extensions;
/** @param: Parameter group to fetch (MBZ) */
__u32 param_group;
/** @pad: MBZ */
__u32 pad;
/** @value: User pointer to write parameter struct */
__u64 pointer;
/** @value: Size of user buffer, max size supported on return */
__u64 size;
};
enum
{
DRM_IOCTL_ASAHI_GET_PARAMS = DRM_IOWR(DRM_COMMAND_BASE + DRM_ASAHI_GET_PARAMS, struct drm_asahi_get_params),
};
#endif // __has_include
#endif // FF_HAVE_DRM
+97 -38
View File
@@ -21,10 +21,16 @@
#include <sys/ioctl.h>
#endif
#include "gpu_asahi.h"
#define FF_STR_INDIR(x) #x
#define FF_STR(x) FF_STR_INDIR(x)
#if defined(FF_HAVE_DRM) && defined(__aarch64__)
// https://github.com/alyssarosenzweig/linux/blob/agx-uapi-v7/include/uapi/drm/asahi_drm.h
// Found in kernel-headers-6.14.4-400.asahi.fc42.aarch64
#if __has_include(<drm/asahi_drm.h>)
#include <drm/asahi_drm.h>
#else
#include "asahi_drm.h"
#endif
#define FF_HAVE_DRM_ASAHI 1
#endif
static bool pciDetectDriver(FFstrbuf* result, FFstrbuf* pciDir, FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey)
{
@@ -140,6 +146,26 @@ static const char* drmDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult
gpu->frequency = (uint32_t) (gpuInfo.max_engine_clk / 1000u);
gpu->index = FF_GPU_INDEX_UNSET;
gpu->type = gpuInfo.ids_flags & AMDGPU_IDS_FLAGS_FUSION ? FF_GPU_TYPE_INTEGRATED : FF_GPU_TYPE_DISCRETE;
#define FF_VRAM_CASE(name, value) case value /* AMDGPU_VRAM_TYPE_ ## name */: ffStrbufSetStatic(&gpu->memoryType, #name); break
switch (gpuInfo.vram_type)
{
FF_VRAM_CASE(UNKNOWN, 0);
FF_VRAM_CASE(GDDR1, 1);
FF_VRAM_CASE(DDR2, 2);
FF_VRAM_CASE(GDDR3, 3);
FF_VRAM_CASE(GDDR4, 4);
FF_VRAM_CASE(GDDR5, 5);
FF_VRAM_CASE(HBM, 6);
FF_VRAM_CASE(DDR3, 7);
FF_VRAM_CASE(DDR4, 8);
FF_VRAM_CASE(GDDR6, 9);
FF_VRAM_CASE(DDR5, 10);
FF_VRAM_CASE(LPDDR4, 11);
FF_VRAM_CASE(LPDDR5, 12);
default:
ffStrbufAppendF(&gpu->memoryType, "Unknown (%u)", gpuInfo.vram_type);
break;
}
struct amdgpu_heap_info heapInfo;
if (ffamdgpu_query_heap_info(handle, AMDGPU_GEM_DOMAIN_VRAM, 0, &heapInfo) >= 0)
@@ -225,10 +251,15 @@ static void pciDetectAmdSpecific(const FFGPUOptions* options, FFGPUResult* gpu,
gpu->shared.used = value;
}
}
ffStrbufSubstrBefore(pciDir, pciDirLen);
ffStrbufAppendS(pciDir, "/gpu_busy_percent");
if (ffReadFileBuffer(pciDir->chars, buffer) && (value = ffStrbufToUInt(buffer, 0)))
gpu->coreUsage = (double) value;
}
}
static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey)
static void pciDetectIntelSpecific(const FFGPUOptions* options, FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf* buffer, const char* drmKey)
{
// Works for Intel GPUs
// https://patchwork.kernel.org/project/intel-gfx/patch/1422039866-11572-3-git-send-email-ville.syrjala@linux.intel.com/
@@ -238,12 +269,46 @@ static void pciDetectIntelSpecific(FFGPUResult* gpu, FFstrbuf* pciDir, FFstrbuf*
if (!drmKey) return;
if (ffStrbufEqualS(&gpu->driver, "xe"))
const uint32_t pciDirLen = pciDir->length;
bool isXE = ffStrbufEqualS(&gpu->driver, "xe");
if (isXE)
ffStrbufAppendS(pciDir, "/tile0/gt0/freq0/max_freq");
else
ffStrbufAppendF(pciDir, "/drm/%s/gt_max_freq_mhz", drmKey);
if (ffReadFileBuffer(pciDir->chars, buffer))
gpu->frequency = (uint32_t) ffStrbufToUInt(buffer, 0);
ffStrbufSubstrBefore(pciDir, pciDirLen);
if (options->temp)
{
ffStrbufAppendS(pciDir, "/hwmon/");
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(pciDir->chars);
if (dirp)
{
struct dirent* entry;
while ((entry = readdir(dirp)) != NULL)
{
if (entry->d_name[0] == '.') continue;
ffStrbufSubstrBefore(pciDir, pciDirLen + strlen("/hwmon/"));
ffStrbufAppendS(pciDir, entry->d_name);
// https://github.com/Syllo/nvtop/blob/73291884d926445e499d6b9b71cb7a9bdbc7c393/src/extract_gpuinfo_intel.c#L279-L281
ffStrbufAppendS(pciDir, isXE ? "/temp2_input" : "/temp1_input");
if (ffReadFileBuffer(pciDir->chars, buffer))
{
uint64_t value = ffStrbufToUInt(buffer, 0);
if (value > 0)
{
gpu->temperature = (double) value / 1000;
break;
}
}
}
}
ffStrbufSubstrBefore(pciDir, pciDirLen);
}
}
static inline int popcountBytes(uint8_t* bytes, uint32_t length)
@@ -500,7 +565,7 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
}
else if (gpu->vendor.chars == FF_GPU_VENDOR_NAME_INTEL)
{
pciDetectIntelSpecific(gpu, deviceDir, buffer, drmKey);
pciDetectIntelSpecific(options, gpu, deviceDir, buffer, drmKey);
ffStrbufSubstrBefore(deviceDir, drmDirPathLength);
if (options->driverSpecific && drmKey)
drmDetectIntelSpecific(gpu, drmKey, buffer);
@@ -556,13 +621,13 @@ static const char* detectPci(const FFGPUOptions* options, FFlist* gpus, FFstrbuf
#if __aarch64__
FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, const char* name, FFstrbuf* buffer, const char* drmKey)
FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, const char* name, FF_MAYBE_UNUSED FFstrbuf* buffer, FF_MAYBE_UNUSED const char* drmKey)
{
if (sscanf(name, "agx-t%lu", &gpu->deviceId) == 1)
ffStrbufSetStatic(&gpu->name, ffCPUAppleCodeToName((uint32_t) gpu->deviceId));
ffStrbufSetStatic(&gpu->vendor, FF_GPU_VENDOR_NAME_APPLE);
#if FF_HAVE_DRM
#if FF_HAVE_DRM_ASAHI
ffStrbufSetS(buffer, "/dev/dri/");
ffStrbufAppendS(buffer, drmKey);
FF_AUTO_CLOSE_FD int fd = open(buffer->chars, O_RDONLY);
@@ -575,38 +640,32 @@ FF_MAYBE_UNUSED static const char* drmDetectAsahiSpecific(FFGPUResult* gpu, cons
.size = sizeof(paramsGlobal),
}) >= 0)
{
ffStrbufAppendF(&gpu->driver, " %u", paramsGlobal.unstable_uabi_version);
// They removed `unstable_uabi_version` from the struct. Hopefully they won't introduce new ABI changes.
gpu->coreCount = (int32_t) (paramsGlobal.num_clusters_total * paramsGlobal.num_cores_per_cluster);
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
gpu->deviceId = paramsGlobal.chip_id;
// FIXME: They will introduce ABI breaking changes. Always check the latest version
// https://www.reddit.com/r/AsahiLinux/comments/1ei2qiv/comment/lgm0v5s/
if (paramsGlobal.unstable_uabi_version == DRM_ASAHI_UNSTABLE_UABI_VERSION)
if (!gpu->name.length)
{
gpu->coreCount = (int) paramsGlobal.num_cores_total_active;
gpu->frequency = paramsGlobal.max_frequency_khz / 1000;
gpu->deviceId = paramsGlobal.chip_id;
if (!gpu->name.length)
{
const char* variant = " Unknown";
switch (paramsGlobal.gpu_variant) {
case 'G':
variant = "";
break;
case 'S':
variant = " Pro";
break;
case 'C':
variant = " Max";
break;
case 'D':
variant = " Ultra";
break;
}
ffStrbufSetF(&gpu->name, "Apple M%d%s (G%d%c %02X)",
paramsGlobal.gpu_generation - 12, variant,
paramsGlobal.gpu_generation, paramsGlobal.gpu_variant,
paramsGlobal.gpu_revision + 0xA0);
const char* variant = " Unknown";
switch (paramsGlobal.gpu_variant) {
case 'G':
variant = "";
break;
case 'S':
variant = " Pro";
break;
case 'C':
variant = " Max";
break;
case 'D':
variant = " Ultra";
break;
}
ffStrbufSetF(&gpu->name, "Apple M%d%s (G%d%c %02X)",
paramsGlobal.gpu_generation - 12, variant,
paramsGlobal.gpu_generation, paramsGlobal.gpu_variant,
paramsGlobal.gpu_revision + 0xA0);
}
}
}
+31 -3
View File
@@ -1,8 +1,10 @@
#include "fastfetch.h"
#include "detection/media/media.h"
#include "common/library.h"
#include "common/processing.h"
#include "util/apple/cf_helpers.h"
#include "util/apple/osascript.h"
#include "fastfetch_datatext.h"
#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
@@ -13,7 +15,7 @@ extern CFStringRef MRNowPlayingClientGetBundleIdentifier(id clientObj) __attribu
extern CFStringRef MRNowPlayingClientGetParentAppBundleIdentifier(id clientObj) __attribute__((weak_import));
void MRMediaRemoteGetNowPlayingApplicationIsPlaying(dispatch_queue_t queue, void (^callback)(BOOL playing)) __attribute__((weak_import));
static const char* getMedia(FFMediaResult* result)
static const char* getMediaByMediaRemote(FFMediaResult* result)
{
#define FF_TEST_FN_EXISTANCE(fn) if (!fn) return "MediaRemote function " #fn " is not available"
FF_TEST_FN_EXISTANCE(MRMediaRemoteGetNowPlayingInfo);
@@ -79,8 +81,34 @@ static const char* getMedia(FFMediaResult* result)
return error;
}
static const char* getMediaByOsascript(FFMediaResult* result)
{
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
// The script must be executed by `/usr/bin/osascript`. `ffOsascript` doesn't work here
const char* error = ffProcessAppendStdOut(&buffer, (char* const[]) {
"/usr/bin/osascript",
"-e",
FASTFETCH_DATATEXT_NOWPLAYING,
nil
});
if (error) return error;
if (buffer.length == 0) return "No media found";
// status\ntitle\nartist\nalbum\nbundleName\nappName
FFstrbuf* const varList[] = { &result->status, &result->song, &result->artist, &result->album, &result->playerId, &result->player };
char* line = NULL;
size_t len = 0;
for (uint32_t i = 0; i < ARRAY_SIZE(varList) && ffStrbufGetline(&line, &len, &buffer); ++i)
ffStrbufSetS(varList[i], line);
return NULL;
}
void ffDetectMediaImpl(FFMediaResult* media)
{
const char* error = getMedia(media);
ffStrbufAppendS(&media->error, error);
const char* error;
if (@available(macOS 15.4, *))
error = getMediaByOsascript(media);
else
error = getMediaByMediaRemote(media);
if (error) ffStrbufAppendS(&media->error, error);
}
+1
View File
@@ -142,6 +142,7 @@ static bool getBusProperties(FFDBusData* data, const char* busName, FFMediaResul
ffStrbufClear(&result->artist);
ffStrbufClear(&result->album);
ffStrbufClear(&result->url);
ffStrbufClear(&result->status);
return false;
}
}
+9 -4
View File
@@ -19,11 +19,16 @@ static const char* getMedia(FFMediaResult* media)
}
ffStrbufSetWS(&media->playerId, result.playerId);
ffStrbufSet(&media->player, &media->playerId);
if (ffStrbufEndsWithIgnCaseS(&media->player, ".exe"))
ffStrbufSubstrBefore(&media->player, media->player.length - 4);
if (result.playerName[0])
{
ffStrbufSetWS(&media->player, result.playerName);
}
else
ffStrbufSubstrAfterFirstC(&media->player, '!'); // UWP ID
{
ffStrbufSet(&media->player, &media->playerId);
if (ffStrbufEndsWithIgnCaseS(&media->player, ".exe"))
ffStrbufSubstrBefore(&media->player, media->player.length - 4);
}
ffStrbufSetWS(&media->song, result.song);
ffStrbufSetWS(&media->artist, result.artist);
ffStrbufSetWS(&media->album, result.album);
@@ -1,5 +1,6 @@
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Media.Control.h>
#include <winrt/Windows.ApplicationModel.h>
#include <wchar.h>
extern "C"
@@ -11,6 +12,7 @@ const char* ffWinrtDetectMedia(FFWinrtMediaResult* result)
// C++/WinRT requires Windows 8.1+ and C++ runtime (std::string, exceptions and other stuff)
// Make it a separate dll in order not to break Windows 7 support
using namespace winrt::Windows::Media::Control;
using namespace winrt::Windows::ApplicationModel;
try
{
@@ -48,6 +50,11 @@ const char* ffWinrtDetectMedia(FFWinrtMediaResult* result)
::wcsncpy(result->song, mediaProps.Title().data(), FF_MEDIA_WIN_RESULT_BUFLEN);
::wcsncpy(result->artist, mediaProps.Artist().data(), FF_MEDIA_WIN_RESULT_BUFLEN);
::wcsncpy(result->album, mediaProps.AlbumTitle().data(), FF_MEDIA_WIN_RESULT_BUFLEN);
try
{
// Only works for UWP apps
::wcsncpy(result->playerName, AppInfo::GetFromAppUserModelId(session.SourceAppUserModelId()).DisplayInfo().DisplayName().data(), FF_MEDIA_WIN_RESULT_BUFLEN);
} catch (...) { }
return NULL;
}
+1
View File
@@ -5,6 +5,7 @@
typedef struct FFWinrtMediaResult
{
wchar_t playerId[FF_MEDIA_WIN_RESULT_BUFLEN];
wchar_t playerName[FF_MEDIA_WIN_RESULT_BUFLEN];
wchar_t song[FF_MEDIA_WIN_RESULT_BUFLEN];
wchar_t artist[FF_MEDIA_WIN_RESULT_BUFLEN];
wchar_t album[FF_MEDIA_WIN_RESULT_BUFLEN];
+18 -33
View File
@@ -4,60 +4,46 @@
#include "common/netif/netif.h"
#include "util/stringUtils.h"
#include <fcntl.h>
#include <net/if.h>
static void getData(FFstrbuf* buffer, const char* ifName, bool isDefaultRoute, FFstrbuf* path, FFlist* result)
static void getData(FFstrbuf* buffer, const char* ifName, bool isDefaultRoute, int basefd, FFlist* result)
{
ffStrbufSetF(path, "/sys/class/net/%s/operstate", ifName);
if(!ffReadFileBuffer(path->chars, buffer) || !ffStrbufEqualS(buffer, "up\n"))
FF_AUTO_CLOSE_FD int dfd = openat(basefd, ifName, O_RDONLY | O_DIRECTORY);
if (dfd < 0)
return;
char operstate;
if(!ffReadFileDataRelative(dfd, "operstate", 1, &operstate) || operstate != 'u' /* up or unknown */)
return;
FFNetIOResult* counters = (FFNetIOResult*) ffListAdd(result);
ffStrbufInitS(&counters->name, ifName);
counters->defaultRoute = isDefaultRoute;
ffStrbufSetF(path, "/sys/class/net/%s/statistics/", ifName);
uint32_t statLen = path->length;
ffStrbufAppendS(path, "rx_bytes");
if (ffReadFileBuffer(path->chars, buffer))
if (ffReadFileBufferRelative(dfd, "statistics/rx_bytes", buffer))
counters->rxBytes = ffStrbufToUInt(buffer, 0);
ffStrbufSubstrBefore(path, statLen);
ffStrbufAppendS(path, "tx_bytes");
if (ffReadFileBuffer(path->chars, buffer))
if (ffReadFileBufferRelative(dfd, "statistics/tx_bytes", buffer))
counters->txBytes = ffStrbufToUInt(buffer, 0);
ffStrbufSubstrBefore(path, statLen);
ffStrbufAppendS(path, "rx_packets");
if (ffReadFileBuffer(path->chars, buffer))
if (ffReadFileBufferRelative(dfd, "statistics/rx_packets", buffer))
counters->rxPackets = ffStrbufToUInt(buffer, 0);
ffStrbufSubstrBefore(path, statLen);
ffStrbufAppendS(path, "tx_packets");
if (ffReadFileBuffer(path->chars, buffer))
if (ffReadFileBufferRelative(dfd, "statistics/tx_packets", buffer))
counters->txPackets = ffStrbufToUInt(buffer, 0);
ffStrbufSubstrBefore(path, statLen);
ffStrbufAppendS(path, "rx_errors");
if (ffReadFileBuffer(path->chars, buffer))
if (ffReadFileBufferRelative(dfd, "statistics/rx_errors", buffer))
counters->rxErrors = ffStrbufToUInt(buffer, 0);
ffStrbufSubstrBefore(path, statLen);
ffStrbufAppendS(path, "tx_errors");
if (ffReadFileBuffer(path->chars, buffer))
if (ffReadFileBufferRelative(dfd, "statistics/tx_errors", buffer))
counters->txErrors = ffStrbufToUInt(buffer, 0);
ffStrbufSubstrBefore(path, statLen);
ffStrbufAppendS(path, "rx_dropped");
if (ffReadFileBuffer(path->chars, buffer))
if (ffReadFileBufferRelative(dfd, "statistics/rx_dropped", buffer))
counters->rxDrops = ffStrbufToUInt(buffer, 0);
ffStrbufSubstrBefore(path, statLen);
ffStrbufAppendS(path, "tx_dropped");
if (ffReadFileBuffer(path->chars, buffer))
if (ffReadFileBufferRelative(dfd, "statistics/tx_dropped", buffer))
counters->txDrops = ffStrbufToUInt(buffer, 0);
ffStrbufSubstrBefore(path, statLen);
}
const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
@@ -65,7 +51,6 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
FF_AUTO_CLOSE_DIR DIR* dirp = opendir("/sys/class/net");
if (!dirp) return "opendir(\"/sys/class/net\") == NULL";
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateA(64);
FF_STRBUF_AUTO_DESTROY buffer = ffStrbufCreate();
const char* defaultRouteIfName = ffNetifGetDefaultRouteIfName();
@@ -75,7 +60,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
if (options->namePrefix.length && strncmp(defaultRouteIfName, options->namePrefix.chars, options->namePrefix.length) != 0)
return NULL;
getData(&buffer, defaultRouteIfName, true, &path, result);
getData(&buffer, defaultRouteIfName, true, dirfd(dirp), result);
}
else
{
@@ -89,7 +74,7 @@ const char* ffNetIOGetIoCounters(FFlist* result, FFNetIOOptions* options)
if (options->namePrefix.length && strncmp(ifName, options->namePrefix.chars, options->namePrefix.length) != 0)
continue;
getData(&buffer, ifName, ffStrEquals(ifName, defaultRouteIfName), &path, result);
getData(&buffer, ifName, ffStrEquals(ifName, defaultRouteIfName), dirfd(dirp), result);
}
}
+1
View File
@@ -40,6 +40,7 @@ typedef struct FFPackagesResult
uint32_t rpm;
uint32_t scoop;
uint32_t snap;
uint32_t soar;
uint32_t sorcery;
uint32_t winget;
uint32_t xbps;
+3
View File
@@ -682,4 +682,7 @@ void ffDetectPackagesImpl(FFPackagesResult* result, FFPackagesOptions* options)
if (!(options->disabled & FF_PACKAGES_FLAG_AM_BIT))
result->amUser = getAMUser();
if (!(options->disabled & FF_PACKAGES_FLAG_SOAR_BIT))
result->soar += getSQLite3Int(&baseDir, ".local/share/soar/db/soar.db", "SELECT COUNT(DISTINCT pkg_id || pkg_name) FROM packages WHERE is_installed = true", "soar");
}
@@ -65,6 +65,7 @@ const char* ffDetectPhysicalDisk(FFlist* result, FFPhysicalDiskOptions* options)
FFPhysicalDiskResult* device = (FFPhysicalDiskResult*) ffListAdd(result);
ffStrbufInitF(&device->devPath, "/dev/%s", provider->lg_name);
ffStrbufInitMove(&device->serial, &identifier);
ffStrbufTrim(&device->serial, ' ');
ffStrbufInit(&device->revision);
ffStrbufInit(&device->interconnect);
switch (snapIter->device_type & DEVSTAT_TYPE_IF_MASK)
@@ -78,10 +78,18 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
ffStrbufInitMove(&device->name, &name);
ffStrbufInitF(&device->devPath, "/dev/%s", devName);
bool isVirtual = false;
{
ffStrbufInit(&device->interconnect);
if (ffStrStartsWith(devName, "nvme"))
ffStrbufSetStatic(&device->interconnect, "NVMe");
else if (ffStrStartsWith(devName, "mmcblk"))
ffStrbufSetStatic(&device->interconnect, "MMC");
else if (ffStrStartsWith(devName, "md"))
{
ffStrbufSetStatic(&device->interconnect, "RAID");
isVirtual = true;
}
else
{
char pathSysDeviceLink[64];
@@ -97,6 +105,11 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
ffStrbufSetStatic(&device->interconnect, "SCSI");
else if (strstr(pathSysDeviceReal, "/nvme") != NULL)
ffStrbufSetStatic(&device->interconnect, "NVMe");
else if (strstr(pathSysDeviceReal, "/virtio") != NULL)
{
ffStrbufSetStatic(&device->interconnect, "Virtual");
isVirtual = true;
}
else
{
if (ffAppendFileBufferRelative(devfd, "transport", &device->interconnect))
@@ -106,6 +119,7 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
}
}
if (!isVirtual)
{
char isRotationalChar = '1';
if (ffReadFileDataRelative(dfd, "queue/rotational", 1, &isRotationalChar) > 0)
@@ -139,7 +153,7 @@ static void parsePhysicalDisk(int dfd, const char* devName, FFPhysicalDiskOption
{
ffStrbufInit(&device->serial);
if (ffReadFileBufferRelative(devfd, "serial", &device->serial))
ffStrbufTrimRightSpace(&device->serial);
ffStrbufTrim(&device->serial, ' ');
}
{
+3 -1
View File
@@ -94,7 +94,9 @@ const char* ffDetectSound(FFlist* devices /* List of FFSoundDevice */)
}, 0, NULL, &dataSize, &active) == kAudioHardwareNoError)
device->active = !!active;
if (!muted)
if (muted)
device->volume = 0;
else
{
float volume;
dataSize = sizeof(volume);
@@ -69,6 +69,7 @@ static bool getShellVersionBash(FFstrbuf* exe, FFstrbuf* exePath, FFstrbuf* vers
if (*path == '\0')
path = exe->chars;
ffBinaryExtractStrings(path, extractBashVersion, version, (uint32_t) strlen("@(#)Bash version 0.0.0(0) release GNU"));
if (version->length > 0) return true;
if(!getExeVersionRaw(exe, version))
return false;
+4 -2
View File
@@ -1,11 +1,13 @@
#include "uptime.h"
#include "common/time.h"
#include <sysinfoapi.h>
#include <realtimeapiset.h>
const char* ffDetectUptime(FFUptimeResult* result)
{
result->uptime = GetTickCount64();
// According to MSDN, this function only fails if it's called with NULL
QueryUnbiasedInterruptTime(&result->uptime);
result->uptime /= 10000; // Convert from 100-nanosecond intervals to milliseconds
result->bootTime = ffTimeGetNow() - result->uptime;
return NULL;
}
+14 -16
View File
@@ -2,15 +2,11 @@
#include "common/io/io.h"
#include "util/stringUtils.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_media.h>
#include <net80211/ieee80211_ioctl.h>
#include <unistd.h>
const char* ffDetectWifi(FFlist* result)
{
@@ -21,6 +17,7 @@ const char* ffDetectWifi(FFlist* result)
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0) {
if_freenameindex(infs);
return "socket() failed";
}
@@ -86,22 +83,23 @@ const char* ffDetectWifi(FFlist* result)
item->conn.channel = curchan.ic_ieee;
item->conn.frequency = curchan.ic_freq;
if (IEEE80211_IS_CHAN_FHSS(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
if (IEEE80211_IS_CHAN_A(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
if (IEEE80211_IS_CHAN_B(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
if (IEEE80211_IS_CHAN_ANYG(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
if (IEEE80211_IS_CHAN_HT(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
if (IEEE80211_IS_CHAN_VHT(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
#ifdef IEEE80211_IS_CHAN_HE // for future use
if (IEEE80211_IS_CHAN_HE(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
else
#endif
if (IEEE80211_IS_CHAN_VHT(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
else if (IEEE80211_IS_CHAN_HT(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
else if (IEEE80211_IS_CHAN_ANYG(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
else if (IEEE80211_IS_CHAN_B(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
else if (IEEE80211_IS_CHAN_A(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
else if (IEEE80211_IS_CHAN_FHSS(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
}
union {
+169
View File
@@ -0,0 +1,169 @@
#include "wifi.h"
#include "common/io/io.h"
#include "util/stringUtils.h"
#define COMPAT_FREEBSD_NET80211 1
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/if_media.h>
#include <net80211/ieee80211.h>
#include <net80211/ieee80211_ioctl.h>
// ieee80211 header of NetBSD is full of mess. Add compatibility macros from FreeBSD
#undef IEEE80211_IS_CHAN_ANYG
#define IEEE80211_IS_CHAN_ANYG(x) (IEEE80211_IS_CHAN_PUREG(x) || IEEE80211_IS_CHAN_G(x))
#undef IEEE80211_IS_CHAN_HT
#define IEEE80211_IS_CHAN_HT(x) (((x)->ic_flags & IEEE80211_CHAN_HT) != 0)
#undef IEEE80211_IS_CHAN_VHT
#define IEEE80211_IS_CHAN_VHT(x) (((x)->ic_flags & IEEE80211_CHAN_VHT) != 0)
const char* ffDetectWifi(FFlist* result)
{
struct if_nameindex* infs = if_nameindex();
if(!infs) {
return "if_nameindex() failed";
}
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0) {
if_freenameindex(infs);
return "socket() failed";
}
for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i)
{
if (!ffStrStartsWith(i->if_name, "iwm")) {
continue;
}
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
ffStrbufInitS(&item->inf.description, i->if_name);
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
item->conn.channel = 0;
item->conn.frequency = 0;
char ssid[IEEE80211_NWID_LEN + 1] = {};
struct ieee80211req ireq = {};
strlcpy(ireq.i_name, i->if_name, sizeof(ireq.i_name));
ireq.i_type = IEEE80211_IOC_SSID;
ireq.i_data = ssid;
ireq.i_len = sizeof(ssid) - 1;
if (ioctl(sock, SIOCG80211, &ireq) < 0 || ireq.i_len == 0) {
struct ifreq ifr;
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
ffStrbufSetStatic(&item->inf.status, "Unknown");
} else {
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
}
ffStrbufAppendS(&item->conn.status, "Not associated");
continue;
}
ffStrbufSetStatic(&item->inf.status, "Up");
ffStrbufSetStatic(&item->conn.status, "Associated");
ffStrbufAppendNS(&item->conn.ssid, ireq.i_len, ssid);
uint8_t bssid[IEEE80211_ADDR_LEN] = {};
ireq.i_type = IEEE80211_IOC_BSSID;
ireq.i_data = bssid;
ireq.i_len = sizeof(bssid);
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
}
struct ieee80211_channel curchan = {};
ireq.i_type = IEEE80211_IOC_CHANNEL;
ireq.i_data = &curchan;
ireq.i_len = sizeof(curchan);
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
// item->conn.channel = curchan.ic_ieee; // No ic_ieee in NetBSD
item->conn.channel = ffWifiFreqToChannel(curchan.ic_freq);
item->conn.frequency = curchan.ic_freq;
#ifdef IEEE80211_IS_CHAN_HE // for future use
if (IEEE80211_IS_CHAN_HE(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11ax (Wi-Fi 6)");
else
#endif
if (IEEE80211_IS_CHAN_VHT(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
else if (IEEE80211_IS_CHAN_HT(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
else if (IEEE80211_IS_CHAN_ANYG(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
else if (IEEE80211_IS_CHAN_B(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11b");
else if (IEEE80211_IS_CHAN_A(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
else if (IEEE80211_IS_CHAN_FHSS(&curchan))
ffStrbufSetStatic(&item->conn.protocol, "802.11 (FHSS)");
}
union {
struct ieee80211req_sta_req req;
uint8_t buf[1024];
} stareq = {};
memcpy(stareq.req.is_u.macaddr, bssid, sizeof(bssid));
ireq.i_type = IEEE80211_IOC_STA_INFO;
ireq.i_data = &stareq;
ireq.i_len = sizeof(stareq);
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
struct ieee80211req_sta_info* sta = stareq.req.info;
if (sta->isi_len != 0) {
int8_t rssi = (int8_t) sta->isi_rssi; // Strangely, `sta->isi_rssi` is unsigned
item->conn.signalQuality = (rssi >= -50 ? 100 : rssi <= -100 ? 0 : (rssi + 100) * 2);
if (sta->isi_txrate) {
item->conn.txRate = (double)sta->isi_txrate / 2.0;
}
}
}
ireq.i_type = IEEE80211_IOC_AUTHMODE;
ireq.i_data = NULL;
ireq.i_len = 0;
if (ioctl(sock, SIOCG80211, &ireq) >= 0) {
switch (ireq.i_val) {
case IEEE80211_AUTH_NONE:
ffStrbufSetStatic(&item->conn.security, "Insecure");
break;
case IEEE80211_AUTH_OPEN:
ffStrbufSetStatic(&item->conn.security, "Open");
break;
case IEEE80211_AUTH_SHARED:
ffStrbufSetStatic(&item->conn.security, "Shared");
break;
case IEEE80211_AUTH_8021X:
ffStrbufSetStatic(&item->conn.security, "8021X");
break;
case IEEE80211_AUTH_AUTO:
ffStrbufSetStatic(&item->conn.security, "Auto");
break;
case IEEE80211_AUTH_WPA:
ffStrbufSetStatic(&item->conn.security, "WPA");
break;
default:
ffStrbufSetF(&item->conn.security, "Unknown (%d)", ireq.i_val);
break;
}
}
}
if_freenameindex(infs);
return NULL;
}
+111
View File
@@ -0,0 +1,111 @@
#include "wifi.h"
#include "common/io/io.h"
#include "util/stringUtils.h"
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net80211/ieee80211.h>
#include <net80211/ieee80211_ioctl.h>
#include <unistd.h>
const char* ffDetectWifi(FFlist* result)
{
struct if_nameindex* infs = if_nameindex();
if(!infs) {
return "if_nameindex() failed";
}
FF_AUTO_CLOSE_FD int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0) {
return "socket() failed";
}
for(struct if_nameindex* i = infs; !(i->if_index == 0 && i->if_name == NULL); ++i)
{
if (!ffStrStartsWith(i->if_name, "iwm")) {
continue;
}
FFWifiResult* item = (FFWifiResult*) ffListAdd(result);
ffStrbufInitS(&item->inf.description, i->if_name);
ffStrbufInit(&item->inf.status);
ffStrbufInit(&item->conn.status);
ffStrbufInit(&item->conn.ssid);
ffStrbufInit(&item->conn.bssid);
ffStrbufInit(&item->conn.protocol);
ffStrbufInit(&item->conn.security);
item->conn.signalQuality = 0.0/0.0;
item->conn.rxRate = 0.0/0.0;
item->conn.txRate = 0.0/0.0;
item->conn.channel = 0;
item->conn.frequency = 0;
struct ieee80211_nodereq nr = {};
strlcpy(nr.nr_ifname, i->if_name, sizeof(nr.nr_ifname));
struct ifreq ifr = {};
strlcpy(ifr.ifr_name, i->if_name, sizeof(ifr.ifr_name));
if (ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
ffStrbufSetStatic(&item->inf.status, "Unknown");
} else {
ffStrbufSetStatic(&item->inf.status, ifr.ifr_flags & IFF_UP ? "Up" : "Down");
}
if (ioctl(sock, SIOCG80211NODE, &nr) < 0) {
ffStrbufSetStatic(&item->conn.status, "Not associated");
continue;
}
if (nr.nr_nwid_len > 0) {
ffStrbufSetStatic(&item->conn.status, "Associated");
ffStrbufAppendNS(&item->conn.ssid, nr.nr_nwid_len, (char*)nr.nr_nwid);
} else {
ffStrbufSetStatic(&item->conn.status, "Not associated");
continue;
}
ffStrbufSetF(&item->conn.bssid, "%02X:%02X:%02X:%02X:%02X:%02X",
nr.nr_bssid[0], nr.nr_bssid[1], nr.nr_bssid[2],
nr.nr_bssid[3], nr.nr_bssid[4], nr.nr_bssid[5]);
item->conn.channel = nr.nr_channel;
if (nr.nr_max_rssi) {
item->conn.signalQuality = ((float)nr.nr_rssi / nr.nr_max_rssi) * 100.0;
}
if (nr.nr_flags & IEEE80211_NODEREQ_HT) {
ffStrbufSetStatic(&item->conn.protocol, "802.11n (Wi-Fi 4)");
} else if (nr.nr_flags & IEEE80211_NODEREQ_VHT) {
ffStrbufSetStatic(&item->conn.protocol, "802.11ac (Wi-Fi 5)");
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_5GHZ) {
ffStrbufSetStatic(&item->conn.protocol, "802.11a");
} else if (nr.nr_chan_flags & IEEE80211_CHANINFO_2GHZ) {
ffStrbufSetStatic(&item->conn.protocol, "802.11g");
}
struct ieee80211_wpaparams wpa = {};
strlcpy(wpa.i_name, i->if_name, sizeof(wpa.i_name));
if (ioctl(sock, SIOCG80211WPAPARMS, &wpa) >= 0 && wpa.i_enabled) {
if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA2)
ffStrbufSetStatic(&item->conn.security, "WPA2");
else if (wpa.i_protos & IEEE80211_WPA_PROTO_WPA1)
ffStrbufSetStatic(&item->conn.security, "WPA");
} else {
struct ieee80211_nwkey nwkey = {};
strlcpy(nwkey.i_name, i->if_name, sizeof(nwkey.i_name));
if (ioctl(sock, SIOCG80211NWKEY, &nwkey) >= 0) {
if (nwkey.i_wepon)
ffStrbufSetStatic(&item->conn.security, "WEP");
else
ffStrbufSetStatic(&item->conn.security, "Open");
}
}
}
if_freenameindex(infs);
return NULL;
}
+1
View File
@@ -38,6 +38,7 @@ static const char* getHyprland(FFstrbuf* result)
{
ffStrbufSubstrAfterFirstC(result, '"');
ffStrbufSubstrBeforeFirstC(result, '"');
ffStrbufTrimLeft(result, 'v');
FF_DEBUG("Extracted version from version.h: %s", result->chars);
return NULL;
}
+14 -3
View File
@@ -1,9 +1,11 @@
#include "fastfetch.h"
#include "common/commandoption.h"
#include "common/init.h"
#include "common/io/io.h"
#include "common/jsonconfig.h"
#include "common/printing.h"
#include "detection/version/version.h"
#include "logo/logo.h"
#include "util/stringUtils.h"
#include "util/mallocHelper.h"
#include "fastfetch_datatext.h"
@@ -483,13 +485,22 @@ static void optionParseConfigFile(FFdata* data, const char* key, const char* val
if (instance.state.platform.exePath.length)
{
ffStrbufSet(&absolutePath, &instance.state.platform.exePath);
ffStrbufSubstrBeforeLastC(&absolutePath, '/');
ffStrbufAppendS(&absolutePath, "/");
uint32_t lastSlash = ffStrbufLastIndexC(&instance.state.platform.exePath, '/') + 1;
assert(lastSlash < instance.state.platform.exePath.length);
// Try {exePath}/
ffStrbufSetNS(&absolutePath, lastSlash, instance.state.platform.exePath.chars);
ffStrbufAppendS(&absolutePath, value);
if (needExtension)
ffStrbufAppendS(&absolutePath, ".jsonc");
if (parseJsoncFile(absolutePath.chars, strictJson)) return;
// Try {exePath}/presets/
ffStrbufSubstrBefore(&absolutePath, lastSlash);
ffStrbufAppendS(&absolutePath, "presets/");
ffStrbufAppendS(&absolutePath, value);
if (needExtension)
ffStrbufAppendS(&absolutePath, ".jsonc");
if (parseJsoncFile(absolutePath.chars, strictJson)) return;
}
+3 -25
View File
@@ -26,7 +26,9 @@
#include "options/general.h"
#ifdef __has_builtin
#if __has_builtin(__builtin_types_compatible_p)
#if __has_builtin(__is_array)
#define ARRAY_SIZE(x) ({ static_assert(__is_array(__typeof__(x)), "Must be an array"); (uint32_t) (sizeof(x) / sizeof(*(x))); })
#elif __has_builtin(__builtin_types_compatible_p)
#define ARRAY_SIZE(x) ({ static_assert(!__builtin_types_compatible_p(__typeof__(x), __typeof__(&*(x))), "Must not be a pointer"); (uint32_t) (sizeof(x) / sizeof(*(x))); })
#endif
#endif
@@ -63,27 +65,3 @@ typedef struct FFinstance
} FFinstance;
extern FFinstance instance; // Defined in `common/init.c`
extern FFModuleBaseInfo** ffModuleInfos[];
//////////////////////
// Init functions //
//////////////////////
//common/init.c
void ffInitInstance();
void ffStart();
void ffFinish();
void ffDestroyInstance();
void ffListFeatures();
////////////////////
// Logo functions //
////////////////////
void ffLogoPrint();
void ffLogoPrintRemaining();
void ffLogoPrintLine();
void ffLogoBuiltinPrint();
void ffLogoBuiltinList();
void ffLogoBuiltinListAutocompletion();
+4
View File
@@ -2,3 +2,7 @@
#define FASTFETCH_DATATEXT_JSON_HELP @DATATEXT_JSON_HELP@
#define FASTFETCH_DATATEXT_STRUCTURE @DATATEXT_STRUCTURE@
#ifdef __APPLE__
#define FASTFETCH_DATATEXT_NOWPLAYING @DATATEXT_NOWPLAYING@
#endif
+1
View File
@@ -1,5 +1,6 @@
#include "fastfetch.h"
#include "common/init.h"
#include "modules/modules.h"
int main(void)
+21 -21
View File
@@ -1,21 +1,21 @@
${c1}rrrrrraaaaaaaaaaaayyyy
${c1}xxrrrrrrrraaaaaaaaaaaayyyyyyyyy
${c1}xxxxxrrrrrrrraaaaaaaaaaaayyyyyyy${c3}yyyyy${c2}yyyyyyyyyy
${c1}xxxxxxxrrrrrrrraaaaa ${c2}aaaaayyyyyyyyyyyyyyyyyyy
${c1}xxxxxx${c3}xxx${c1}rrrrrrrraaaa ${c2}aaaaaaayyyyyyyyyyyyyyyyy
${c1}xxxxxx${c3}xxxxxr${c1}rrrrrrraa ${c2}aaaaaaaaay${c3}yyyyyyyyy${c2}yyyy ${c1}yy
${c1}xxxxxxx${c3}xxx${c1}xxrrrrrrrra ${c2}aaaaaaaaa${c3}ayyyyyyyyyyyy${c1}yyyyyy
${c1}xxxxxxxxxxxxrrrrrrrr ${c2}aaaaaaaaaaa${c3}yyyyyyyyyyyy${c1}yyyyyyy
${c1}xxxxxxxxxxxxxrrrrrr ${c2}raaaaaaaaaaaayyy${c3}yyyyyyyy${c1}yyyyyy${c1}yyy
${c1}xxxxxxxxxxxxxrrrrr ${c2}rraaaaaaaaaaaayyyyy${c3}yy${c2}yyyyyy ${c1}yyyyyy
${c1}xxxxxxxx${c3}xxxx${c1}xrrrrr${c2}rr${c3}raaaaaaa${c2}aaaaayyyyyyyyyy ${c1}yyyyyyyyy
${c1}xxxxxxx${c3}xxxx${c1}xxrrrrrrr${c3}raaaaaa${c2}aaaaaayyyyyyy ${c1}yyyyyyyyyyyy
${c1}xxxxxxx${c3}xxx${c1}xxxrrrrrrrr${c3}aaaaaa${c2}aaaaaayyyy ${c1}yyyyyyyyyyyyyy
${c1}xxxxxxxxxxxxrrrrrrrra ${c2}aaaaaaaaaay ${c1}yyyyyyyyyyyyyyyy
${c1}xxxxxxxxxxxrrrrrrr ${c2}aaaaaaaaaaaayyyy${c1}yyyyyyyyyyyyy
${c1}xxxxxxx${c3}xxxrr${c1}rrrr ${c2}raaaaaaaaaaaa ${c1}yyyyyyyyyyyyyyy
${c1}xxxxxxxxrrrr ${c2}rrraaaaaaaaa ${c1}aayyyyyyyyyyyyyy
${c1}xxxxxxrrrrrrr ${c2}aaaaaa ${c1}aaaayyyyyyyyyyyy
${c1}xxxrrrrrr ${c2}raaa ${c1}aaaaaaayyyyyyyyy
${c1}rrrr ${c2}rr ${c1}aaaaaaaaaayyyyyy
${c2}r ${c1}aaaaaaaaaa
$1rrrrrraaaaaaaaaaaayyyy
$1xxrrrrrrrraaaaaaaaaaaayyyyyyyyy
$1xxxxxrrrrrrrraaaaaaaaaaaayyyyyyy$3yyyyy$2yyyyyyyyyy
$1xxxxxxxrrrrrrrraaaaa $2aaaaayyyyyyyyyyyyyyyyyyy
$1xxxxxx$3xxx$1rrrrrrrraaaa $2aaaaaaayyyyyyyyyyyyyyyyy
$1xxxxxx$3xxxxxr$1rrrrrrraa $2aaaaaaaaay$3yyyyyyyyy$2yyyy $1yy
$1xxxxxxx$3xxx$1xxrrrrrrrra $2aaaaaaaaa$3ayyyyyyyyyyyy$1yyyyyy
$1xxxxxxxxxxxxrrrrrrrr $2aaaaaaaaaaa$3yyyyyyyyyyyy$1yyyyyyy
$1xxxxxxxxxxxxxrrrrrr $2raaaaaaaaaaaayyy$3yyyyyyyy$1yyyyyy$1yyy
$1xxxxxxxxxxxxxrrrrr $2rraaaaaaaaaaaayyyyy$3yy$2yyyyyy $1yyyyyy
$1xxxxxxxx$3xxxx$1xrrrrr$2rr$3raaaaaaa$2aaaaayyyyyyyyyy $1yyyyyyyyy
$1xxxxxxx$3xxxx$1xxrrrrrrr$3raaaaaa$2aaaaaayyyyyyy $1yyyyyyyyyyyy
$1xxxxxxx$3xxx$1xxxrrrrrrrr$3aaaaaa$2aaaaaayyyy $1yyyyyyyyyyyyyy
$1xxxxxxxxxxxxrrrrrrrra $2aaaaaaaaaay $1yyyyyyyyyyyyyyyy
$1xxxxxxxxxxxrrrrrrr $2aaaaaaaaaaaayyyy$1yyyyyyyyyyyyy
$1xxxxxxx$3xxxrr$1rrrr $2raaaaaaaaaaaa $1yyyyyyyyyyyyyyy
$1xxxxxxxxrrrr $2rrraaaaaaaaa $1aayyyyyyyyyyyyyy
$1xxxxxxrrrrrrr $2aaaaaa $1aaaayyyyyyyyyyyy
$1xxxrrrrrr $2raaa $1aaaaaaayyyyyyyyy
$1rrrr $2rr $1aaaaaaaaaayyyyyy
$2r $1aaaaaaaaaa
+11 -11
View File
@@ -1,16 +1,16 @@
${c3} ,-^-___
${c3} /\\\///
${c2}refined.${c1} /\\\\//
${c2}reliable.${c1} /\\\///
${c2}ready.${c1} /\\/////\
$3 ,-^-___
$3 /\\\///
$2refined.$1 /\\\\//
$2reliable.$1 /\\\///
$2ready.$1 /\\/////\
__///\\\\/////\
${c3} _//////\\\\\\\////
${c1} ///////${c3}\\\\\\\\\\//
//////${c1}\\\\\/
$3 _//////\\\\\\\////
$1 ///////$3\\\\\\\\\\//
//////$1\\\\\/
/////\\\\\/
/////${c3}\\\\/
/////$3\\\\/
/\\///\\\/
/\\\/${c1}\\/
/\\\/$1\\/
/\\\\//
//////
/// ${c3}\\\\\
/// $3\\\\\
+15 -15
View File
@@ -1,15 +1,15 @@
${c2}.
${c1}. ${c2}.{!
${c1}.L! ${c2}J@||*
${c1}gJJJJL` ${c2}g@FFS"
${c1},@FFFJF`${c2}_g@@LLP`
${c1}_@FFFFF`${c2}_@@@@@P` ${c4}.
${c1}J@@@LLF ${c2}_@@@@@P` ${c4}.J!
${c1}g@@@@@" ${c2}_@@@@@P`${c3}. ${c4}.L|||*
${c1}g@@@@M" ${c2}"VP`${c3}.L! ${c4}<@JJJJ`
${c1}"@N" ${c3}:||||! ${c4}JFFFFS"
${c3}.{JJ||F`${c4}_gFFFF@'
${c3}.@FJJJF`${c4},@LFFFF`
${c3}_@FFFFF ${c4}VLLLP`
${c3}J@@LL@" ${c4}`"
${c3}V@@"
$2.
$1. $2.{!
$1.L! $2J@||*
$1gJJJJL` $2g@FFS"
$1,@FFFJF`$2_g@@LLP`
$1_@FFFFF`$2_@@@@@P` $4.
$1J@@@LLF $2_@@@@@P` $4.J!
$1g@@@@@" $2_@@@@@P`$3. $4.L|||*
$1g@@@@M" $2"VP`$3.L! $4<@JJJJ`
$1"@N" $3:||||! $4JFFFFS"
$3.{JJ||F`$4_gFFFF@'
$3.@FJJJF`$4,@LFFFF`
$3_@FFFFF $4VLLLP`
$3J@@LL@" $4`"
$3V@@"
+16
View File
@@ -0,0 +1,16 @@
.:::::::::::::::::::::.
.:::::::::::::::::::::::.
.:::::::::::::::::::::::::.
.:::::::::::::::::::::::::::.
.:::::::::$2,db,$1::::::::::::::::.
.::::::::$2,d%%%%b,$1::$2,db,$1:::::::::.
.:::::::$2,%%%%P'%%%b,d%%%b,$1::::::::.
.::::::$2,%%%%P,$1:::$2`%%%b'^q%%b,$1:::::::.
'::::$2,%%%%P,d|$1:::::$2`%%%b:'^%%b,$1:::::'
'::$2`%%%'$1:$2'q$|$1:::::::$2'q%%b'`q%%b'$1::'
':::::::::::::::::::::::::::::::'
':::::::::::::::::::::::::::::'
':::::::::::::::::::::::::::'
':::::::::::::::::::::::::'
':::::::::::::::::::::::'
':::::::::::::::::::::'
+5 -5
View File
@@ -1,6 +1,6 @@
${c1} /\ /\
/${c2}/ ${c1}\ \
/${c2}// ${c1}\ \
/${c2}// ${c1}\ \
${c2}// ${c1}\ \
$1 /\ /\
/$2/ $1\ \
/$2// $1\ \
/$2// $1\ \
$2// $1\ \
\
+6
View File
@@ -0,0 +1,6 @@
,db,
,d%%%%b, ,db,
,%%%%P'%%%b,d%%%b,
,%%%%P, `%%%b'^q%%b,
,%%%%P,d| `%%%b '^%%b,
`%%%' 'q$| 'q%%b'`q%%b
+4 -4
View File
@@ -1,9 +1,9 @@
___________
/ \
/ ${c2}______${c1} \
/ ${c2}/ \${c1} \
| ${c2}( )${c1} \
/ ${c2}\______/${c1} |
/ $2______$1 \
/ $2/ \$1 \
| $2( )$1 \
/ $2\______/$1 |
| |
/ \
| |
+28 -28
View File
@@ -1,28 +1,28 @@
${c2}..${c1}
${c2}..${c1}
${c2}:..${c1}
${c2}:+++.${c1}
.:::++${c2}++++${c1}+::.
.:+######${c2}++++${c1}######+:.
.+#########${c2}+++++${c1}##########:.
.+##########${c2}+++++++${c1}##${c2}+${c1}#########+.
+###########${c2}+++++++++${c1}############:
+##########${c2}++++++${c1}#${c2}++++${c1}#${c2}+${c1}###########+
+###########${c2}+++++${c1}###${c2}++++${c1}#${c2}+${c1}###########+
:##########${c2}+${c1}#${c2}++++${c1}####${c2}++++${c1}#${c2}+${c1}############:
###########${c2}+++++${c1}#####${c2}+++++${c1}#${c2}+${c1}###${c2}++${c1}######+
.##########${c2}++++++${c1}#####${c2}++++++++++++${c1}#######.
.##########${c2}+++++++++++++++++++${c1}###########.
#####${c2}++++++++++++++${c1}###${c2}++++++++${c1}#########+
:###${c2}++++++++++${c1}#########${c2}+++++++${c1}#########:
+######${c2}+++++${c1}##########${c2}++++++++${c1}#######+
+####${c2}+++++${c1}###########${c2}+++++++++${c1}#####+
:##${c2}++++++${c1}############${c2}++++++++++${c1}##:
.${c2}++++++${c1}#############${c2}++++++++++${c1}+.
:${c2}++++${c1}###############${c2}+++++++${c1}::
.${c2}++. .:+${c1}##############${c2}+++++++${c1}..
${c2}.:.${c1} ..::++++++::..:${c2}++++${c1}+.
${c2}.${c1} ${c2}.:+++${c1}.
${c2}.:${c1}:
${c2}..${c1}
${c2}..${c1}
$2..$1
$2..$1
$2:..$1
$2:+++.$1
.:::++$2++++$1+::.
.:+######$2++++$1######+:.
.+#########$2+++++$1##########:.
.+##########$2+++++++$1##$2+$1#########+.
+###########$2+++++++++$1############:
+##########$2++++++$1#$2++++$1#$2+$1###########+
+###########$2+++++$1###$2++++$1#$2+$1###########+
:##########$2+$1#$2++++$1####$2++++$1#$2+$1############:
###########$2+++++$1#####$2+++++$1#$2+$1###$2++$1######+
.##########$2++++++$1#####$2++++++++++++$1#######.
.##########$2+++++++++++++++++++$1###########.
#####$2++++++++++++++$1###$2++++++++$1#########+
:###$2++++++++++$1#########$2+++++++$1#########:
+######$2+++++$1##########$2++++++++$1#######+
+####$2+++++$1###########$2+++++++++$1#####+
:##$2++++++$1############$2++++++++++$1##:
.$2++++++$1#############$2++++++++++$1+.
:$2++++$1###############$2+++++++$1::
.$2++. .:+$1##############$2+++++++$1..
$2.:.$1 ..::++++++::..:$2++++$1+.
$2.$1 $2.:+++$1.
$2.:$1:
$2..$1
$2..$1
+19
View File
@@ -0,0 +1,19 @@
$1+++++++++++
+++++++++++++++++++++
+++++++++++++++++++++++++++++++
=+++++++++++++++++++++++++++++++++++++++=
+++++++++++++++++++++++++++++++++++++++++++++
=++++++++++++++++++++++++++++++++++++++++++++
==+++++++++++++++++++++++++++++++++==
+++++++++++++++++++++++++++
$2**** $1++=+++++++++++=++ $2****
********** $1+++++++ $2**********
************** **************
**************** ****************
***********************
****** ************* ******
*********** *** ***********
*************** ***************
*************** ***************
*********************
***********
+12 -12
View File
@@ -1,19 +1,19 @@
${c2} `.-/::/-``
$2 `.-/::/-``
.-/osssssssso/.
:osyysssssssyyys+-
`.+yyyysssssssssyyyyy+.
`/syyyyyssssssssssyyyyys-`
`/yhyyyyysss${c1}++${c2}ssosyyyyhhy/`
.ohhhyyyys${c1}o++/+o${c2}so${c1}+${c2}syy${c1}+${c2}shhhho.
.shhhhys${c1}oo++//+${c2}sss${c1}+++${c2}yyy${c1}+s${c2}hhhhs.
-yhhhhs${c1}+++++++o${c2}ssso${c1}+++${c2}yyy${c1}s+o${c2}hhddy:
-yddhhy${c1}o+++++o${c2}syyss${c1}++++${c2}yyy${c1}yooy${c2}hdddy-
.yddddhs${c1}o++o${c2}syyyyys${c1}+++++${c2}yyhh${c1}sos${c2}hddddy`
`odddddhyosyhyyyyyy${c1}++++++${c2}yhhhyosddddddo
.dmdddddhhhhhhhyyyo${c1}+++++${c2}shhhhhohddddmmh.
ddmmdddddhhhhhhhso${c1}++++++${c2}yhhhhhhdddddmmdy
dmmmdddddddhhhyso${c1}++++++${c2}shhhhhddddddmmmmh
-dmmmdddddddhhys${c1}o++++o${c2}shhhhdddddddmmmmd-
`/yhyyyyysss$1++$2ssosyyyyhhy/`
.ohhhyyyys$1o++/+o$2so$1+$2syy$1+$2shhhho.
.shhhhys$1oo++//+$2sss$1+++$2yyy$1+s$2hhhhs.
-yhhhhs$1+++++++o$2ssso$1+++$2yyy$1s+o$2hhddy:
-yddhhy$1o+++++o$2syyss$1++++$2yyy$1yooy$2hdddy-
.yddddhs$1o++o$2syyyyys$1+++++$2yyhh$1sos$2hddddy`
`odddddhyosyhyyyyyy$1++++++$2yhhhyosddddddo
.dmdddddhhhhhhhyyyo$1+++++$2shhhhhohddddmmh.
ddmmdddddhhhhhhhso$1++++++$2yhhhhhhdddddmmdy
dmmmdddddddhhhyso$1++++++$2shhhhhddddddmmmmh
-dmmmdddddddhhys$1o++++o$2shhhhdddddddmmmmd-
.smmmmddddddddhhhhhhhhhdddddddddmmmms.
`+ydmmmdddddddddddddddddddmmmmdy/.
`.:+ooyyddddddddddddyyso+:.`
+17 -17
View File
@@ -1,17 +1,17 @@
${c2}__
${c2}gpBBBBBBBBBP
${c2}_gBBBBBBBBBRP
${c2}4BBBBBBBBRP ${c4},_____
${c2}`"" ${c4}_g@@@@@@@@@@@@@%g>
${c4}__@@@@@@@@@@@@@@@@P" ${c1}___
${c4}_g@@@@@@@@@@@@@@@N"` ${c1}_gN@@@@@N^
${c4}_w@@@@@@@@@@@@@@@@P" ${c1}_g@@@@@@@P"
${c4}_g@@@@@@@@@@@@@@@N"` ${c1}VMNN@NNNM^`
${c4}^MMM@@@@@@@@@@@MP" ${c3},ggppww__
${c4}`""""" ${c3}_wNNNNNNNNNNNNNNNNNNN
${c3}_gBNNNNNNNNNNNNNNNNNP"
${c3}_wNNNNNNNNNNNNNNNNNNMP`
${c3}_gBNNNNNNNNNNNNNNNNNP"
${c3}_wNNNNNNNNNNNNNNNNNNNM^
${c3}""Y^^MNNNNNNNNNNNNP`
${c3}`"""""""
$2__
$2gpBBBBBBBBBP
$2_gBBBBBBBBBRP
$24BBBBBBBBRP $4,_____
$2`"" $4_g@@@@@@@@@@@@@%g>
$4__@@@@@@@@@@@@@@@@P" $1___
$4_g@@@@@@@@@@@@@@@N"` $1_gN@@@@@N^
$4_w@@@@@@@@@@@@@@@@P" $1_g@@@@@@@P"
$4_g@@@@@@@@@@@@@@@N"` $1VMNN@NNNM^`
$4^MMM@@@@@@@@@@@MP" $3,ggppww__
$4`""""" $3_wNNNNNNNNNNNNNNNNNNN
$3_gBNNNNNNNNNNNNNNNNNP"
$3_wNNNNNNNNNNNNNNNNNNMP`
$3_gBNNNNNNNNNNNNNNNNNP"
$3_wNNNNNNNNNNNNNNNNNNNM^
$3""Y^^MNNNNNNNNNNNNP`
$3`"""""""
+16 -16
View File
@@ -1,18 +1,18 @@
${c2} .........
$2 .........
...................
.....................${c1}################${c2}
.............. ....${c1}################${c2}
.............. ...${c1}################${c2}
............. ..${c1}****************${c2}
............ . .${c1}****************${c2}
........... ... ${c1}................${c2}
.......... ..... ${c1}...............${c2}
.....................$1################$2
.............. ....$1################$2
.............. ...$1################$2
............. ..$1****************$2
............ . .$1****************$2
........... ... $1................$2
.......... ..... $1...............$2
......... ....... ...
.${c3}...... ${c2}.
${c3}..... .....${c2}.... ${c4}...........
${c3}.... ......${c2}. ${c4}...........
${c3}... ....... ${c4}...........
${c3}................ ${c4}***********
${c3}................ ${c4}###########
${c3}****************
${c3}################
.$3...... $2.
$3..... .....$2.... $4...........
$3.... ......$2. $4...........
$3... ....... $4...........
$3................ $4***********
$3................ $4###########
$3****************
$3################
+8 -8
View File
@@ -1,9 +1,9 @@
${c2} _____ ${c1}_____${c2}
-' '-${c1}| |${c2}
/ ___ ${c1}| |${c2}
| / _ \${c1}|_____|${c2}
$2 _____ $1_____$2
-' '-$1| |$2
/ ___ $1| |$2
| / _ \$1|_____|$2
' / /_\ \
\ / _____ \${c4}___
${c3}|${c2}/_/ ${c3}| ${c4}| |
${c3}| | ${c4}|___|
${c3}|_____|
\ / _____ \$4___
$3|$2/_/ $3| $4| |
$3| | $4|___|
$3|_____|
+10 -10
View File
@@ -2,15 +2,15 @@
_=(SDGJT=_
_GTDJHGGFCVS)
,GTDJGGDTDFBGX0
${c1} JDJDIJHRORVFSBSVL${c2}-=+=,_
${c1} IJFDUFHJNXIXCDXDSV,${c2} "DEBL
${c1} [LKDSDJTDU=OUSCSBFLD.${c2} '?ZWX,
${c1} ,LMDSDSWH' `DCBOSI${c2} DRDS],
${c1} SDDFDFH' !YEWD,${c2} )HDROD
${c1} !KMDOCG &GSU|${c2}\_GFHRGO\'
${c1} HKLSGP'${c2} __${c1}\TKM0${c2}\GHRBV)'
${c1}JSNRVW'${c2} __+MNAEC${c1}\IOI,${c2}\BN'
${c1}HELK['${c2} __,=OFFXCBGHC${c1}\FD)
${c1}?KGHE ${c2}\_-#DASDFLSV='${c1} 'EF
$1 JDJDIJHRORVFSBSVL$2-=+=,_
$1 IJFDUFHJNXIXCDXDSV,$2 "DEBL
$1 [LKDSDJTDU=OUSCSBFLD.$2 '?ZWX,
$1 ,LMDSDSWH' `DCBOSI$2 DRDS],
$1 SDDFDFH' !YEWD,$2 )HDROD
$1 !KMDOCG &GSU|$2\_GFHRGO\'
$1 HKLSGP'$2 __$1\TKM0$2\GHRBV)'
$1JSNRVW'$2 __+MNAEC$1\IOI,$2\BN'
$1HELK['$2 __,=OFFXCBGHC$1\FD)
$1?KGHE $2\_-#DASDFLSV='$1 'EF
'EHTI !H
`0F' '!
+20 -20
View File
@@ -1,20 +1,20 @@
${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢰⡆${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢠⣿⣿⡄${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c3}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢀⣾⣿⣿⣿⡀${c3}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c4}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⣼⣿⣿⣿⣿⣷⡀${c4}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c5}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⣼⣿⣿⣿⣿⣿⣿⣷${c5}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c6}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢼⣿⣿⣿⣿⣿⣿⣿⣿⣧${c6}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⣰⣤⣈⠻⢿⣿⣿⣿⣿⣿⣿⣧${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⣰⣿⣿⣿⣿⣮⣿⣿⣿⣿⣿⣿⣿⣧${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c3}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧${c3}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c4}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧${c4}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c5}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧${c5}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
${c6}⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⣼⣿⣿⣿⣿⣿⡿⣿⣿⡟${c6}⠄⠄${c1}⠸⣿⣿⡿⣿⣿⣿⣿⣿⣷⡀${c6}⠄⠄⠄⠄⠄⠄⠄⠄
${c1}⠄⠄⠄⠄⠄⠄⠄⠄${c1}⣼⣿⣿⣿⣿⣿⡏${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⠈⣿⣿⣿⣿⣿⣷⡀${c1}⠄⠄⠄⠄⠄⠄⠄
${c2}⠄⠄⠄⠄⠄⠄${c1}⢀⣼⣿⣿⣿⣿⣿⣿⡗${c2}⠄⠄⠄${c1}⢀⣠⣤⣀⠄⠄⠄${c1}⠸⣿⣿⣿⣿⣿⣿⣷⡀${c2}⠄⠄⠄⠄⠄⠄
${c3}⠄⠄⠄⠄⠄${c1}⢀⣾⣿⣿⣿⣿⣿⡏⠁${c3}⠄⠄⠄${c1}⢠⣿⣿⣿⣿⡇${c3}⠄⠄⠄⠄${c1}⢙⣿⣿⣻⠿⣿⣷⡀${c3}⠄⠄⠄⠄⠄
${c4}⠄⠄⠄⠄${c1}⢀⣾⣿⣿⣿⣿⣿⣿⣷⣤⡀${c4}⠄⠄⠄${c1}⠻⣿⣿⡿⠃${c4}⠄⠄⠄${c1}⢀⣼⣿⣿⣿⣿⣦⣌⠙⠄${c4}⠄⠄⠄⠄
${c5}⠄⠄⠄${c1}⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏${c5}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⢿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀${c5}⠄⠄⠄
${c6}⠄⠄${c1}⢠⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⠁${c6}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⡄${c6}⠄⠄
${c1}⠄${c1}⣠⣿⣿⣿⣿⠿⠛⠋⠁${c1}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⠉⠙⠻⢿⣿⣿⣿⣿⣆${c1}
${c1}⡰⠟⠛⠉⠁${c2}⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄${c1}⠉⠙⠛⠿⢆
$1⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⢰⡆$1⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$2⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⢠⣿⣿⡄$2⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$3⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⢀⣾⣿⣿⣿⡀$3⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$4⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⣼⣿⣿⣿⣿⣷⡀$4⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$5⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⣼⣿⣿⣿⣿⣿⣿⣷$5⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$6⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⢼⣿⣿⣿⣿⣿⣿⣿⣿⣧$6⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$1⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⣰⣤⣈⠻⢿⣿⣿⣿⣿⣿⣿⣧$1⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$2⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⣰⣿⣿⣿⣿⣮⣿⣿⣿⣿⣿⣿⣿⣧$2⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$3⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧$3⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$4⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧$4⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$5⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧$5⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄
$6⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⣼⣿⣿⣿⣿⣿⡿⣿⣿⡟$6⠄⠄$1⠸⣿⣿⡿⣿⣿⣿⣿⣿⣷⡀$6⠄⠄⠄⠄⠄⠄⠄⠄
$1⠄⠄⠄⠄⠄⠄⠄⠄$1⣼⣿⣿⣿⣿⣿⡏$1⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⠈⣿⣿⣿⣿⣿⣷⡀$1⠄⠄⠄⠄⠄⠄⠄
$2⠄⠄⠄⠄⠄⠄$1⢀⣼⣿⣿⣿⣿⣿⣿⡗$2⠄⠄⠄$1⢀⣠⣤⣀⠄⠄⠄$1⠸⣿⣿⣿⣿⣿⣿⣷⡀$2⠄⠄⠄⠄⠄⠄
$3⠄⠄⠄⠄⠄$1⢀⣾⣿⣿⣿⣿⣿⡏⠁$3⠄⠄⠄$1⢠⣿⣿⣿⣿⡇$3⠄⠄⠄⠄$1⢙⣿⣿⣻⠿⣿⣷⡀$3⠄⠄⠄⠄⠄
$4⠄⠄⠄⠄$1⢀⣾⣿⣿⣿⣿⣿⣿⣷⣤⡀$4⠄⠄⠄$1⠻⣿⣿⡿⠃$4⠄⠄⠄$1⢀⣼⣿⣿⣿⣿⣦⣌⠙⠄$4⠄⠄⠄⠄
$5⠄⠄⠄$1⢠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⠏$5⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⢿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀$5⠄⠄⠄
$6⠄⠄$1⢠⣿⣿⣿⣿⣿⣿⣿⡿⠟⠋⠁$6⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⠙⠻⣿⣿⣿⣿⣿⣿⣿⣿⡄$6⠄⠄
$1⠄$1⣠⣿⣿⣿⣿⠿⠛⠋⠁$1⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⠉⠙⠻⢿⣿⣿⣿⣿⣆$1
$1⡰⠟⠛⠉⠁$2⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄$1⠉⠙⠛⠿⢆
+11 -11
View File
@@ -1,17 +1,17 @@
${c1} *
$1 *
**.
****
******
*******
** *******
**** *******
${c1}****${c2}_____${c1}***${c2}/${c1}*
***${c2}/${c1}*******${c2}//${c1}***
**${c2}/${c1}********${c2}///${c1}*${c2}/${c1}**
**${c2}/${c1}*******${c2}////${c1}***${c2}/${c1}**
**${c2}/${c1}****${c2}//////.,${c1}****${c2}/${c1}**
***${c2}/${c1}*****${c2}/////////${c1}**${c2}/${c1}***
****${c2}/${c1}**** ${c2}/////${c1}***${c2}/${c1}****
******${c2}/${c1}*** ${c2}//// ${c1}**${c2}/${c1}******
********${c2}/${c1}* ${c2}/// ${c1}*${c2}/${c1}********
,****** ${c2}// ______ / ${c1}******,
$1****$2_____$1***$2/$1*
***$2/$1*******$2//$1***
**$2/$1********$2///$1*$2/$1**
**$2/$1*******$2////$1***$2/$1**
**$2/$1****$2//////.,$1****$2/$1**
***$2/$1*****$2/////////$1**$2/$1***
****$2/$1**** $2/////$1***$2/$1****
******$2/$1*** $2//// $1**$2/$1******
********$2/$1* $2/// $1*$2/$1********
,****** $2// ______ / $1******,
+3 -3
View File
@@ -6,6 +6,6 @@
ooooo ooooo
ooooo ooooo
ooooo ooooo
ooooo ${c2}<oooooooo>${c1}
ooooo ${c2}<oooooo>${c1}
ooooo ${c2}<oooo>
ooooo $2<oooooooo>$1
ooooo $2<oooooo>$1
ooooo $2<oooo>
+15 -15
View File
@@ -1,15 +1,15 @@
${c1} `oyyy/${c2}-yyyyyy+
${c1} -syyyy/${c2}-yyyyyy+
${c1} .syyyyy/${c2}-yyyyyy+
${c1} :yyyyyy/${c2}-yyyyyy+
${c1} `/ :yyyyyy/${c2}-yyyyyy+
${c1} .+s :yyyyyy/${c2}-yyyyyy+
${c1} .oys :yyyyyy/${c2}-yyyyyy+
${c1} -oyys :yyyyyy/${c2}-yyyyyy+
${c1} :syyys :yyyyyy/${c2}-yyyyyy+
${c1} /syyyys :yyyyyy/${c2}-yyyyyy+
${c1} +yyyyyys :yyyyyy/${c2}-yyyyyy+
${c1} .oyyyyyyo. :yyyyyy/${c2}-yyyyyy+ ---------
${c1} .syyyyyy+` :yyyyyy/${c2}-yyyyy+-+syyyyyyyy
${c1} -syyyyyy/ :yyyyyy/${c2}-yyys:.syyyyyyyyyy
${c1}:syyyyyy/ :yyyyyy/${c2}-yyo.:syyyyyyyyyyy
$1 `oyyy/$2-yyyyyy+
$1 -syyyy/$2-yyyyyy+
$1 .syyyyy/$2-yyyyyy+
$1 :yyyyyy/$2-yyyyyy+
$1 `/ :yyyyyy/$2-yyyyyy+
$1 .+s :yyyyyy/$2-yyyyyy+
$1 .oys :yyyyyy/$2-yyyyyy+
$1 -oyys :yyyyyy/$2-yyyyyy+
$1 :syyys :yyyyyy/$2-yyyyyy+
$1 /syyyys :yyyyyy/$2-yyyyyy+
$1 +yyyyyys :yyyyyy/$2-yyyyyy+
$1 .oyyyyyyo. :yyyyyy/$2-yyyyyy+ ---------
$1 .syyyyyy+` :yyyyyy/$2-yyyyy+-+syyyyyyyy
$1 -syyyyyy/ :yyyyyy/$2-yyys:.syyyyyyyyyy
$1:syyyyyy/ :yyyyyy/$2-yyo.:syyyyyyyyyyy
+17 -17
View File
@@ -1,17 +1,17 @@
${c1} ***
${c1} *****
${c1} **********
${c1} ***************
${c1} *///****////****////.
${c2} (/////// /////// ///////(
${c2} /(((((//* //, //((((((.
${c2} ((((((((((( ((( ((((((((
${c2} *((((((((((((((((((((((( ((((((((
${c3} (((((#(((((((#((((( ((#(((((
${c3} (#(#(#####(#(#, ####(#(#
${c3} ######### ########
${c3} /######## ########
${c4} #######%#######
${c4} (#%%%%%%%#
${c4} %%%%%
${c4} %%%
$1 ***
$1 *****
$1 **********
$1 ***************
$1 *///****////****////.
$2 (/////// /////// ///////(
$2 /(((((//* //, //((((((.
$2 ((((((((((( ((( ((((((((
$2 *((((((((((((((((((((((( ((((((((
$3 (((((#(((((((#((((( ((#(((((
$3 (#(#(#####(#(#, ####(#(#
$3 ######### ########
$3 /######## ########
$4 #######%#######
$4 (#%%%%%%%#
$4 %%%%%
$4 %%%
+20 -20
View File
@@ -1,22 +1,22 @@
AA
AaaA
Aa${c2}/\${c1}aA
${c1} Aa${c2}/${c1}aa${c2}\${c1}aA
${c1} Aa${c2}/${c1}aAAa${c2}\${c1}aA
${c1} aA${c2}/${c1}aaAAaa${c2}\${c1}Aa
${c1} aA${c2}/${c1}aaAAAAaa${c2}\${c1}Aa
${c1} aaaaaaAAAAa${c2}/${c1}aaAAAAAAaa${c2}\${c1}aAAAAaaaaa
${c1}aAAa${c2}-----${c1}aaaaaAAAAAAAAAAaaaaa${c2}-----${c1}aAAa
${c1} aAA${c2}\ ${c1}aAAAAAAAAAAAAAAAAAAAAAAa${c2} /${c1}AAa
${c1} aAa${c2}\${c1}aAAA${c2}\${c1}AAAA${c2}\${c1}AAAA${c2}\${c1}AAA${c2}\${c1}AAa${c2}/${c1}aAa
${c1} aAa${c2}\${c1}aA${c2}\\${c1}AAA${c2}\\${c1}AAA${c2}\\${c1}AA${c2}\\/${c1}aAa
${c1} aAA${c2}\${c1}aA${c2}\\${c1}AAA${c2}\\${c1}AAA${c2}\\${c1}Aa${c2}/${c1}AAa
${c1} aA${c2}\${c1}aA${c2}\\${c1}AAA${c2}\\${c1}AAA${c2}\\/${c1}Aa
${c1} aA${c2}/${c1}AA${c2}\\\${c1}AA${c2}\\\${c1}AA${c2}\\\${c1}Aa
${c1} aA${c2}/\${c1}AAa${c2}\\\${c1}Aa${c2}\\\${c1}Aa${c2}\\\${c1}Aa
${c1} aA${c2}/\\${c1}AAa${c2}\\/\${c1}a${c2}\\\${c1}Aa${c2}\\${c1}Aa
${c1} aA${c2}/${c1}a${c2}\\\${c1}Aa${c2}\/${c1}AA${c2}\\\\\${c1}Aa${c2}\\${c1}Aa
${c1} aA${c2}/${c1}aA${c2}\\/${c1}aAa aAa${c2}\\\${c1}Aa${c2}\${c1}Aa
${c1} aA${c2}/\${c1}A${c2}\/${c1}Aa aA${c2}\\${c1}A${c2}\\${c1}Aa
${c1} A${c2}|/${c1}aaAa aAaa${c2}\|${c1}A
${c1} aAaa aaAa
Aa$2/\$1aA
$1 Aa$2/$1aa$2\$1aA
$1 Aa$2/$1aAAa$2\$1aA
$1 aA$2/$1aaAAaa$2\$1Aa
$1 aA$2/$1aaAAAAaa$2\$1Aa
$1 aaaaaaAAAAa$2/$1aaAAAAAAaa$2\$1aAAAAaaaaa
$1aAAa$2-----$1aaaaaAAAAAAAAAAaaaaa$2-----$1aAAa
$1 aAA$2\ $1aAAAAAAAAAAAAAAAAAAAAAAa$2 /$1AAa
$1 aAa$2\$1aAAA$2\$1AAAA$2\$1AAAA$2\$1AAA$2\$1AAa$2/$1aAa
$1 aAa$2\$1aA$2\\$1AAA$2\\$1AAA$2\\$1AA$2\\/$1aAa
$1 aAA$2\$1aA$2\\$1AAA$2\\$1AAA$2\\$1Aa$2/$1AAa
$1 aA$2\$1aA$2\\$1AAA$2\\$1AAA$2\\/$1Aa
$1 aA$2/$1AA$2\\\$1AA$2\\\$1AA$2\\\$1Aa
$1 aA$2/\$1AAa$2\\\$1Aa$2\\\$1Aa$2\\\$1Aa
$1 aA$2/\\$1AAa$2\\/\$1a$2\\\$1Aa$2\\$1Aa
$1 aA$2/$1a$2\\\$1Aa$2\/$1AA$2\\\\\$1Aa$2\\$1Aa
$1 aA$2/$1aA$2\\/$1aAa aAa$2\\\$1Aa$2\$1Aa
$1 aA$2/\$1A$2\/$1Aa aA$2\\$1A$2\\$1Aa
$1 A$2|/$1aaAa aAaa$2\|$1A
$1 aAaa aaAa
-24
View File
@@ -1,24 +0,0 @@
${c1} . ..
${c1} :####: ####.
${c1} .################
${c1} :##################
${c1}.###################.
${c1}######## #######
${c1}####### ${c2}####${c1} #####
${c1}:#######. ####
${c1} ######### ${c2}#${c1} ## #
${c1} ####### ${c2}##${c1} ####
${c1}######## ${c2}####${c1} #######
${c1}######## ${c2}#####${c1} ########
${c1}######## ${c2}#######${c1} #######
${c1} ####### ${c2}########${c1} #######
${c1} ######## ${c2}#########${c1} ######
${c1} ######## ${c2}#########${c1} #####
${c1} ####### ${c2}#########${c1} ####
${c1} ####### ${c2}#########${c1} ##
${c1} ####### ${c2}########${c1} ##
${c1} ###### ${c2}########${c1} #
${c1} ### ${c2}#######${c1}
${c1} ${c2}######${c1}
${c1} ${c2}####${c1}
${c1} ${c2}##${c1}
+29
View File
@@ -0,0 +1,29 @@
u.
..:Y
.Y..1
..::i::.. .br7S.
.::::...::::. 5dDr:
..:::.. .:i::.. Y7:
..:::::.. ..::::.
...:i:i:i:.. $2... $1:.:..:i:::...
::i:. $2.USL Yr $1..i::.
.:::. $2:K :u. $1.::.
:... $2jB. .:vUi: 77 KB: $1..::
...: $2iBR vP::5X5PgSKXvLjS. iBB $1.::.
:i:: $2BBQr jgDIuj1UuJjXbbi 2BBP $1:::;
'i:: $2sQBg: i2S55121XSSU. YBQZ: $1.:::
r::: $2r:JgBMu. Q :BqEqZEB: Q :qBBK7i: $1:i:i
.rir. $2IBqPDgQBDr P rB :q 1QBRgEqgB $1.::i.
:i:i $2:JsXPDDRQQPBL P qQXBQRDDPIYY $1rir:
:iii $25qvLUDDMgMgBB5 :DBQZRgMDdJ7Ygi $1iir:
iri: $2MBRgdZZggQgRBMIBQQRRggdZdMBBr $1riri
irii $2IBQgdZbDDRRRgQgQQMZDdZdgBB. $1iiri
i7rr $2.BBQZZbEEMQQDBQMEZdDDBBP $1.rir:
:7ir. $27BBQMDMQSbB5ZBggQBBQ. $1ivr7.
:r7r. $27BBBB:rBbQ.1BBBM. $1:r7vi
::rLrr. $2.b:rBQ7QB uU. $1:7vLi.
.BB .iLYv: $1idL B1 $1:r77r.
LBB :vrvvr rvu7r:
ZB. ':7v177Lsvurr:'
.d2 ''::r:''
:'
+24
View File
@@ -0,0 +1,24 @@
. ..
$1 :####: ####.
$1 .################
$1 :##################
$1.###################.
$1######## #######
$1####### $2####$1 #####
$1:#######. ####
$1 ######### $2#$1 ## #
$1 ####### $2##$1 ####
$1######## $2####$1 #######
$1######## $2#####$1 ########
$1######## $2#######$1 #######
$1 ####### $2########$1 #######
$1 ######## $2#########$1 ######
$1 ######## $2#########$1 #####
$1 ####### $2#########$1 ####
$1 ####### $2#########$1 ##
$1 ####### $2########$1 ##
$1 ###### $2########$1 #
$1 ### $2#######$1
$1 $2######$1
$1 $2####$1
$1 $2##$1
+28
View File
@@ -0,0 +1,28 @@
+++++++++
+++++$4+$1++++++$4+$1++
++++++$4+$1+++ +++++++++++
+++++++++++ $2+$1 +++++$4+$1+++++
++++++$4+$1++++ $4+++$1 +++++++++++
++++++++++$4 + +++++ ++ $2+++++$4+$2++++
+++$4+$1++++$4 + + + +++++++ + + $2+++++$4+$2++
++++++$4 $2+$4 +++ +++++++++ +++ $2++++++++
+++$4+$1++$4 + +++++ +++++ +
++++++$4 $2+$4 +++++ +++++ +++++
++$4+$2+++$4 + +++++ ++++++ ++++++++++
++++++$4 +++++ +++++ + +++++++++++++++++++
++++++$4 + +++++ + +++++++++++++++
+++$4++$2+$4 ++++++ +++++++++++++
++++++$4 + ++++++ +++++++++++++ $2+++ $4++
++++++$4 ++++++++++++++++ $2++$4+$2+ $4++ $1+
++++++$4 ++++++++++++++ $3+ $2++++
++++++$4 +++++++++++ + $4+ $3++++++
++$4+$3+++$4 ++++++++++ +++ $3+++++++++++++
+++++ $4+++++++++ + $3+++++++++++++
+++ $4++++++++ $2++$4 + $3++++++++++++++ ++++
++ $4++++++++ $3+ ++++++++++++++ +++++++
$4++++++ $2+ $3+++++++++++++ +++++++$2++
$4++++ $3+++++++++++++ ++++++$2+++
+++++++++++ ++++++$2+++
+++++ ++++++$2+++
++++++$2++
+++++
+17 -17
View File
@@ -1,17 +1,17 @@
${c1} ////. ${c2} (((((
${c1}//////// ${c2} @((((((((
${c1}//////// ${c2} @((((((((
${c1}//////// /////// ${c2} ((((((( @((((((((
${c1}//////// ///////// ${c2} ((((((((( @((((((((
${c1}//////// ///////// ${c2} ((((((((( @((((((((
${c1}//////// ///////// ////// ${c2} (((((( ((((((((( @((((((((
${c1}//////// ///////// //////// ${c2} (((((((( ((((((((( @((((((((
${c1}//////// ///////// //////// ${c2} (((((((( ((((((((( @((((((((
${c1}//////// ///////// //////// ${c2} ((((((( ((((((((( @((((((((
${c1}//////// ///////// /// ${c2} ( ((((((((( @((((((((
${c1}//////// ///////// ${c2} ((((((((( @((((((((
${c1}//////// ///////// ${c2} &(((((((( @((((((((
${c1}//////// ////// ${c2} @(((( @((((((((
${c1}//////// ${c2} @((((((((
${c1}//////// ${c2} @((((((((
${c1} ///// ${c2} (((((
$1 ////. $2 (((((
$1//////// $2 @((((((((
$1//////// $2 @((((((((
$1//////// /////// $2 ((((((( @((((((((
$1//////// ///////// $2 ((((((((( @((((((((
$1//////// ///////// $2 ((((((((( @((((((((
$1//////// ///////// ////// $2 (((((( ((((((((( @((((((((
$1//////// ///////// //////// $2 (((((((( ((((((((( @((((((((
$1//////// ///////// //////// $2 (((((((( ((((((((( @((((((((
$1//////// ///////// //////// $2 ((((((( ((((((((( @((((((((
$1//////// ///////// /// $2 ( ((((((((( @((((((((
$1//////// ///////// $2 ((((((((( @((((((((
$1//////// ///////// $2 &(((((((( @((((((((
$1//////// ////// $2 @(((( @((((((((
$1//////// $2 @((((((((
$1//////// $2 @((((((((
$1 ///// $2 (((((
+2 -2
View File
@@ -5,14 +5,14 @@
: xMMMMMW. kMMMMNc lW.
:x NMMMMMO ,MMMM0. 'l
Xx "lkk" kMMMX .okx,
${c2}.MX .cc;. .xXKx. KMMM: .OMMMMMl
$2.MX .cc;. .xXKx. KMMM: .OMMMMMl
:MM' 'KMMMMWK: 0MMMMk xMMM. lWMMMMMMM'
cMMN:;xMMMMk::MMO oMMMMX .XMM. .KMMMWOOMMMd
'MMMMMMMMN, NMMx OMMMMl .kM0OMMMMk. ;MMd
xMMMMMMd .MMMW :NMMMd .ckKKx' KMc
dWMNd. oMMMN lkNMX, oM.
;. ;MMMMx "MM:. cO
${c3} .X. oMMMMW. l.
$3 .X. oMMMMW. l.
dMk:..;xWMMMMW,
kMMMMMMMMMMX.
:XMMMMMMK:
+20 -20
View File
@@ -1,21 +1,21 @@
${c3} 00
$3 00
11
====${c1}
.${c3}//${c1}
`o${c3}//${c1}:
`+o${c3}//${c1}o:
`+oo${c3}//${c1}oo:
-+oo${c3}//${c1}oo+:
`/:-:+${c3}//${c1}ooo+:
`/+++++${c3}//${c1}+++++:
`/++++++${c3}//${c1}++++++:
`/+++o${c2}ooo${c3}//${c2}ooo${c1}oooo/`
${c2} ${c1}./${c2}ooosssso${c3}//${c2}osssssso${c1}+`
${c2} .oossssso-`${c3}//${c1}`/ossssss+`
-osssssso. ${c3}//${c1} :ssssssso.
:osssssss/ ${c3}//${c1} osssso+++.
/ossssssss/ ${c3}//${c1} +ssssooo/-
`/ossssso+/:- ${c3}//${c1} -:/+osssso+-
`+sso+:-` ${c3}//${c1} `.-/+oso:
`++:. ${c3}//${c1} `-/+/
.` ${c3}/${c1} `/
====$1
.$3//$1
`o$3//$1:
`+o$3//$1o:
`+oo$3//$1oo:
-+oo$3//$1oo+:
`/:-:+$3//$1ooo+:
`/+++++$3//$1+++++:
`/++++++$3//$1++++++:
`/+++o$2ooo$3//$2ooo$1oooo/`
$2 $1./$2ooosssso$3//$2osssssso$1+`
$2 .oossssso-`$3//$1`/ossssss+`
-osssssso. $3//$1 :ssssssso.
:osssssss/ $3//$1 osssso+++.
/ossssssss/ $3//$1 +ssssooo/-
`/ossssso+/:- $3//$1 -:/+osssso+-
`+sso+:-` $3//$1 `.-/+oso:
`++:. $3//$1 `-/+/
.` $3/$1 `/
+2 -2
View File
@@ -1,7 +1,7 @@
${c3} ........
$3 ........
.,»╔╗╗╬▄▄╫█▀▓▄▄╬╗╗g≈,.
,j╗╬╣▓▓███████▌;»╙▀▀▀▀█▄▄╗j,
.≈╗╬▓██▀▀▀▀▀╠╙░░»»;:`${c2}``>${c1}▄ ${c3}▐ ▓╫╗⌂,
.≈╗╬▓██▀▀▀▀▀╠╙░░»»;:`$2``>$1▄ $3▐ ▓╫╗⌂,
.j╬▓█▀▒░░░░░░░░░»»»;:```` ╙▀█▌╬░,
;╗▓█▄▄███████▀░░»»»»;```` ╓▄▄█▄▄φ ██▌Ñ>.
.j╣█████▀▀░░░░░░░░»»╓▄▄¿``▄███████/▄████▓╬U.
+17 -17
View File
@@ -1,17 +1,17 @@
${c2} `./ohdNMMMMNmho+.` ${c1} .+oo:`
${c2} -smMMMMMMMMMMMMMMMMmy-` ${c1}`yyyyy+
${c2} `:dMMMMMMMMMMMMMMMMMMMMMMd/` ${c1}`yyyyys
${c2} .hMMMMMMMNmhso/++symNMMMMMMMh- ${c1}`yyyyys
${c2} -mMMMMMMms-` -omMMMMMMN-${c1}.yyyyys
${c2}.mMMMMMMy. .yMMMMMMm:${c1}yyyyys
${c2}sMMMMMMy `sMMMMMMh${c1}yyyyys
${c2}NMMMMMN: .NMMMMMN${c1}yyyyys
${c2}MMMMMMm. NMMMMMN${c1}yyyyys
${c2}hMMMMMM+ /MMMMMMN${c1}yyyyys
${c2}:NMMMMMN: :mMMMMMM+${c1}yyyyys
${c2} oMMMMMMNs- .sNMMMMMMs.${c1}yyyyys
${c2} +MMMMMMMNho:.` `.:ohNMMMMMMNo ${c1}`yyyyys
${c2} -hMMMMMMMMNNNmmNNNMMMMMMMMh- ${c1}`yyyyys
${c2} :yNMMMMMMMMMMMMMMMMMMNy:` ${c1}`yyyyys
${c2} .:sdNMMMMMMMMMMNds/. ${c1}`yyyyyo
${c2} `.:/++++/:.` ${c1}:oys+.
$2 `./ohdNMMMMNmho+.` $1 .+oo:`
$2 -smMMMMMMMMMMMMMMMMmy-` $1`yyyyy+
$2 `:dMMMMMMMMMMMMMMMMMMMMMMd/` $1`yyyyys
$2 .hMMMMMMMNmhso/++symNMMMMMMMh- $1`yyyyys
$2 -mMMMMMMms-` -omMMMMMMN-$1.yyyyys
$2.mMMMMMMy. .yMMMMMMm:$1yyyyys
$2sMMMMMMy `sMMMMMMh$1yyyyys
$2NMMMMMN: .NMMMMMN$1yyyyys
$2MMMMMMm. NMMMMMN$1yyyyys
$2hMMMMMM+ /MMMMMMN$1yyyyys
$2:NMMMMMN: :mMMMMMM+$1yyyyys
$2 oMMMMMMNs- .sNMMMMMMs.$1yyyyys
$2 +MMMMMMMNho:.` `.:ohNMMMMMMNo $1`yyyyys
$2 -hMMMMMMMMNNNmmNNNMMMMMMMMh- $1`yyyyys
$2 :yNMMMMMMMMMMMMMMMMMMNy:` $1`yyyyys
$2 .:sdNMMMMMMMMMMNds/. $1`yyyyyo
$2 `.:/++++/:.` $1:oys+.
+15 -15
View File
@@ -2,18 +2,18 @@
oMMMMMMMMMMMMMMMMMMMMMMMMM
oMMMMMMMMMMMMMMMMMMMMMMMMM
oMMMMMMMMMMMMMMMMMMMMMMMMM
-+++++++++++++++++++++++mM${c2}
```````````````````````..${c1}dM${c2}
```````````````````````....${c1}dM${c2}
```````````````````````......${c1}dM${c2}
```````````````````````........${c1}dM${c2}
```````````````````````..........${c1}dM${c2}
```````````````````````............${c1}dM${c2}
.::::::::::::::::::::::-..............${c1}dM${c2}
`-+yyyyyyyyyyyyyyyyyyyo............${c1}+mMM${c2}
-+yyyyyyyyyyyyyyyyo..........${c1}+mMMMM${c2}
./syyyyyyyyyyyyo........${c1}+mMMMMMM${c2}
./oyyyyyyyyyo......${c1}+mMMMMMMMM${c2}
omdyyyyyyo....${c1}+mMMMMMMMMMM${c2}
${c1}oMMM${c2}mdhyyo..${c1}+mMMMMMMMMMMMM
oNNNNNNm${c2}dso${c1}mMMMMMMMMMMMMMM
-+++++++++++++++++++++++mM$2
```````````````````````..$1dM$2
```````````````````````....$1dM$2
```````````````````````......$1dM$2
```````````````````````........$1dM$2
```````````````````````..........$1dM$2
```````````````````````............$1dM$2
.::::::::::::::::::::::-..............$1dM$2
`-+yyyyyyyyyyyyyyyyyyyo............$1+mMM$2
-+yyyyyyyyyyyyyyyyo..........$1+mMMMM$2
./syyyyyyyyyyyyo........$1+mMMMMMM$2
./oyyyyyyyyyo......$1+mMMMMMMMM$2
omdyyyyyyo....$1+mMMMMMMMMMM$2
$1oMMM$2mdhyyo..$1+mMMMMMMMMMMMM
oNNNNNNm$2dso$1mMMMMMMMMMMMMMM
+18 -18
View File
@@ -1,18 +1,18 @@
${c1}| ${c2},,mmKKKKKKKKWm,,
${c1}' ${c2},aKKP${c1}LL**********|L*${c2}TKp,
${c1}t ${c2}aKP${c1}L**``` ```**L${c2}*Kp
IX${c1}EL${c3}L,wwww, ${c1}``*||${c2}Kp
,#P${c1}L|${c3}KKKpPP@IPPTKmw, ${c1}`*||${c2}K
,K${c1}LL*${c3}{KKKKKKPPb$KPhpKKPKp ${c1}`||${c2}K
#${c1}PL ${c3}!KKKKKKPhKPPP$KKEhKKKKp ${c1}`||${c2}K
!H${c1}L* ${c3}1KKKKKKKphKbPKKKKKK$KKp ${c1}`|I${c2}W
$$$${c1}bL ${c3}KKKKKKKKBQKhKbKKKKKKKK ${c1}|I${c2}N
$$$${c1}bL ${c3}!KKKKKKKKKKNKKKKKKKPP` ${c1}|I${c2}b
TH${c1}L* ${c3}TKKKKKK##KKKN@KKKK^ ${c1}|I${c2}M
K@${c1}L ${c3}*KKKKKKKKKKKEKE5 ${c1}||${c2}K
`NL${c1}L ${c3}`KKKKKKKKKK"```|L ${c1}||${c2}#P
`K@${c1}LL ${c3}`"**"` ${c1}'. :||${c2}#P
Yp${c1}LL ${c1}' |L${c2}$M`
`Tp${c1}pLL, ,|||${c2}p'L
"Kpp${c1}LL++,., ,,|||$$$${c2}#K* ${c1}'.
${c2}`"MKWpppppppp#KM"` ${c1}`h,
$1| $2,,mmKKKKKKKKWm,,
$1' $2,aKKP$1LL**********|L*$2TKp,
$1t $2aKP$1L**``` ```**L$2*Kp
IX$1EL$3L,wwww, $1``*||$2Kp
,#P$1L|$3KKKpPP@IPPTKmw, $1`*||$2K
,K$1LL*$3{KKKKKKPPb$KPhpKKPKp $1`||$2K
#$1PL $3!KKKKKKPhKPPP$KKEhKKKKp $1`||$2K
!H$1L* $31KKKKKKKphKbPKKKKKK$KKp $1`|I$2W
$$$$1bL $3KKKKKKKKBQKhKbKKKKKKKK $1|I$2N
$$$$1bL $3!KKKKKKKKKKNKKKKKKKPP` $1|I$2b
TH$1L* $3TKKKKKK##KKKN@KKKK^ $1|I$2M
K@$1L $3*KKKKKKKKKKKEKE5 $1||$2K
`NL$1L $3`KKKKKKKKKK"```|L $1||$2#P
`K@$1LL $3`"**"` $1'. :||$2#P
Yp$1LL $1' |L$2$M`
`Tp$1pLL, ,|||$2p'L
"Kpp$1LL++,., ,,|||$$$$2#K* $1'.
$2`"MKWpppppppp#KM"` $1`h,
+12 -12
View File
@@ -1,15 +1,15 @@
${c2} ,####,
${c2}#######, ${c2},#####,
${c2}#####',# ${c2}'######
${c2}''###'${c3}';,,,'${c2}###'
${c3} ,; ''''
${c3} ;;; ${c2},#####,
${c3} ;;;' ,,;${c2};;###
${c3} ';;;;''${c2}'####'
${c3} ;;;
${c3} ,.;;';'',,,
${c3} ' '
${c1} #
$2 ,####,
$2#######, $2,#####,
$2#####',# $2'######
$2''###'$3';,,,'$2###'
$3 ,; ''''
$3 ;;; $2,#####,
$3 ;;;' ,,;$2;;###
$3 ';;;;''$2'####'
$3 ;;;
$3 ,.;;';'',,,
$3 ' '
$1 #
# O
##, ,##,',##, ,## ,#, ,
# # # # #''# #,, # # #
+5 -5
View File
@@ -1,7 +1,7 @@
......
,,+++++++,.
.,,,....,,,${c2}+**+,,.${c1}
............,${c2}++++,,,${c1}
.,,,....,,,$2+**+,,.$1
............,$2++++,,,$1
...............
......,,,........
.....+*#####+,,,*+.
@@ -15,6 +15,6 @@
..... ..+##***#################*.
.,.*#*****##############*.
..,,*********#####****+.
${c2}.,++*****+++${c1}*****************${c2}+++++,.${c1}
${c2},++++++**+++++${c1}***********${c2}+++++++++,${c1}
${c2}.,,,,++++,.. .,,,,,.....,+++,.,,${c1}
$2.,++*****+++$1*****************$2+++++,.$1
$2,++++++**+++++$1***********$2+++++++++,$1
$2.,,,,++++,.. .,,,,,.....,+++,.,,$1
+13 -13
View File
@@ -1,18 +1,18 @@
.-/-.
////////.
////////${c2}y+${c1}//.
////////${c2}mMN${c1}/////.
////////${c2}mMN+${c1}////////.
////////$2y+$1//.
////////$2mMN$1/////.
////////$2mMN+$1////////.
////////////////////////.
/////////+${c2}shhddhyo${c1}+////////.
////////${c2}ymMNmdhhdmNNdo${c1}///////.
///////+${c2}mMms${c1}////////${c2}hNMh${c1}///////.
///////${c2}NMm+${c1}//////////${c2}sMMh${c1}///////
//////${c2}oMMNmmmmmmmmmmmmMMm${c1}///////
//////${c2}+MMmssssssssssssss+${c1}///////
`//////${c2}yMMy${c1}////////////////////
`//////${c2}smMNhso++oydNm${c1}////////
`///////${c2}ohmNMMMNNdy+${c1}///////
`//////////${c2}++${c1}//////////
/////////+$2shhddhyo$1+////////.
////////$2ymMNmdhhdmNNdo$1///////.
///////+$2mMms$1////////$2hNMh$1///////.
///////$2NMm+$1//////////$2sMMh$1///////
//////$2oMMNmmmmmmmmmmmmMMm$1///////
//////$2+MMmssssssssssssss+$1///////
`//////$2yMMy$1////////////////////
`//////$2smMNhso++oydNm$1////////
`///////$2ohmNMMMNNdy+$1///////
`//////////$2++$1//////////
`////////////////.
-////////-
+17 -17
View File
@@ -1,18 +1,18 @@
${c3}ddddddddddddddc ${c1},cc:
${c3}ddddddddddddddc ${c1},cc:
${c3}ddddddddddddddd ${c1},cc:
${c3}ddddddddddddl:' ${c1},cc:
${c3}dddddddddl' ${c1}..;cc:
${c3}dddddddo. ${c1},:cccccc:
${c3}ddddddl ${c1},ccc:'''''
${c3}dddddo. ${c1};ccc. ............
$3ddddddddddddddc $1,cc:
$3ddddddddddddddc $1,cc:
$3ddddddddddddddd $1,cc:
$3ddddddddddddl:' $1,cc:
$3dddddddddl' $1..;cc:
$3dddddddo. $1,:cccccc:
$3ddddddl $1,ccc:'''''
$3dddddo. $1;ccc. ............
.ccc. cccccccccccc
${c2}...... ${c1}.ccc. .ccc'''''''''
${c2}OOOOOk. ${c1};ccc. .ccc; ......
${c2}OOOOOOd ${c1}'ccc:,....,:ccc' ${c4}coooooo
${c2}OOOOOOOx. ${c1}':cccccccc:' ${c4}.looooooo
${c2}OOOOOOOOOd, ${c1}`'''` ${c4}.coooooooo
${c2}OOOOOOOOOOOOdc,. ${c4}..,coooooooooooo
${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo
${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo
${c2}OOOOOOOOOOOOOOOO' ${c4}.oooooooooooooooo
$2...... $1.ccc. .ccc'''''''''
$2OOOOOk. $1;ccc. .ccc; ......
$2OOOOOOd $1'ccc:,....,:ccc' $4coooooo
$2OOOOOOOx. $1':cccccccc:' $4.looooooo
$2OOOOOOOOOd, $1`'''` $4.coooooooo
$2OOOOOOOOOOOOdc,. $4..,coooooooooooo
$2OOOOOOOOOOOOOOOO' $4.oooooooooooooooo
$2OOOOOOOOOOOOOOOO' $4.oooooooooooooooo
$2OOOOOOOOOOOOOOOO' $4.oooooooooooooooo
+15 -15
View File
@@ -1,18 +1,18 @@
${c2} .,:loool:,.
$2 .,:loool:,.
.,coooooooooooooc,.
.,lllllllllllllllllllll,.
;ccccccccccccccccccccccccc;
${c1} '${c2}ccccccccccccccccccccccccccccc.
${c1} ,oo${c2}c::::::::okO${c5}000${c3}0OOkkkkkkkkkkk:
${c1}.ooool${c2};;;;:x${c5}K0${c4}kxxxxxk${c5}0X${c3}K0000000000.
${c1}:oooool${c2};,;O${c5}K${c4}ddddddddddd${c5}KX${c3}000000000d
${c1}lllllool${c2};l${c5}N${c4}dllllllllllld${c5}N${c3}K000000000
${c1}lllllllll${c2}o${c5}M${c4}dccccccccccco${c5}W${c3}K000000000
${c1};cllllllllX${c5}X${c4}c:::::::::c${c5}0X${c3}000000000d
${c1}.ccccllllllO${c5}Nk${c4}c;,,,;cx${c5}KK${c3}0000000000.
${c1} .cccccclllllxOO${c5}OOO${c1}Okx${c3}O0000000000;
${c1} .:ccccccccllllllllo${c3}O0000000OOO,
${c1} ,:ccccccccclllcd${c3}0000OOOOOOl.
${c1} '::ccccccccc${c3}dOOOOOOOkx:.
${c1} ..,::cccc${c3}xOOOkkko;.
${c1} ..,:${c3}dOkxl:.
$1 '$2ccccccccccccccccccccccccccccc.
$1 ,oo$2c::::::::okO$5000$30OOkkkkkkkkkkk:
$1.ooool$2;;;;:x$5K0$4kxxxxxk$50X$3K0000000000.
$1:oooool$2;,;O$5K$4ddddddddddd$5KX$3000000000d
$1lllllool$2;l$5N$4dllllllllllld$5N$3K000000000
$1lllllllll$2o$5M$4dccccccccccco$5W$3K000000000
$1;cllllllllX$5X$4c:::::::::c$50X$3000000000d
$1.ccccllllllO$5Nk$4c;,,,;cx$5KK$30000000000.
$1 .cccccclllllxOO$5OOO$1Okx$3O0000000000;
$1 .:ccccccccllllllllo$3O0000000OOO,
$1 ,:ccccccccclllcd$30000OOOOOOl.
$1 '::ccccccccc$3dOOOOOOOkx:.
$1 ..,::cccc$3xOOOkkko;.
$1 ..,:$3dOkxl:.
+12 -12
View File
@@ -3,18 +3,18 @@
BBBBBBBBBBBBBBB
BBBBBBBBBBBBBBBBBBBB
BBBBBBBBBBB BBB
BBBBBBBB${c2}YYYYY
${c1} BBBBBBBB${c2}YYYYYY
${c1} BBBBBBBB${c2}YYYYYYY
${c1} BBBBBBBBB${c2}YYYYY${c3}W
${c4} GG${c1}BBBBBBBY${c2}YYYY${c3}WWW
${c4} GGG${c1}BBBBBBB${c2}YY${c3}WWWWWWWW
${c4} GGGGGG${c1}BBBBBB${c3}WWWWWWWW
${c4} GGGGGGGG${c1}BBBB${c3}WWWWWWWW
${c4}GGGGGGGGGGG${c1}BBB${c3}WWWWWWW
${c4}GGGGGGGGGGGGG${c1}B${c3}WWWWWW
${c4}GGGGGGGG${c3}WWWWWWWWWWW
${c4}GG${c3}WWWWWWWWWWWWWWWW
BBBBBBBB$2YYYYY
$1 BBBBBBBB$2YYYYYY
$1 BBBBBBBB$2YYYYYYY
$1 BBBBBBBBB$2YYYYY$3W
$4 GG$1BBBBBBBY$2YYYY$3WWW
$4 GGG$1BBBBBBB$2YY$3WWWWWWWW
$4 GGGGGG$1BBBBBB$3WWWWWWWW
$4 GGGGGGGG$1BBBB$3WWWWWWWW
$4GGGGGGGGGGG$1BBB$3WWWWWWW
$4GGGGGGGGGGGGG$1B$3WWWWWW
$4GGGGGGGG$3WWWWWWWWWWW
$4GG$3WWWWWWWWWWWWWWWW
WWWWWWWWWWWWWWWW
WWWWWWWWWW
WWW
+2 -2
View File
@@ -7,8 +7,8 @@
`oNMMMNo` `sNMMMMMMNs` `oNMMMNo`
`oNMMMMMMMNo` `oNMMNs` `oNMMMMMMMNo`
oNMMMMMMMMMMMNo` `sy` `oNMMMMMMMMMMMNo
`sNMMMMMMMMMMMMNo.${c2}oNNs${c1}.oNMMMMMMMMMMMMNs`
`oNMMMMMMMMMMMMNs.${c2}oNNs${c1}.oNMMMMMMMMMMMMNo`
`sNMMMMMMMMMMMMNo.$2oNNs$1.oNMMMMMMMMMMMMNs`
`oNMMMMMMMMMMMMNs.$2oNNs$1.oNMMMMMMMMMMMMNo`
oNMMMMMMMMMMMNs` `sy` `oNMMMMMMMMMMMNo
`oNMMMMMMMNs` `oNMMNo` `oNMMMMMMMNs`
`oNMMMNs` `sNMMMMMMNs` `oNMMMNs`
+14 -14
View File
@@ -1,16 +1,16 @@
${c1} ///
${c1} ,//////////////
${c1} ///////////////////////////////
${c1} ///////////////${c5}***********${c1}//////
////${c5}***********************${c1}/////
/////${c5}***********************${c1}////
//////${c5},,,,,,,,,,,,,,,,,,,,,,${c1}///
//////${c5},,,,,,,,,,,,,,,,,,,,,,,,,${c1}/////
/////${c5},,,,,,,,,,,,,,,,,,,,,,,,,,,,${c1}/////
${c4} *****${c3},,,,,,,,,,,,,,,,,,,,,,,,,,,,,${c4}*****
******${c3},,,,,,,,,,,,,,,,,,,,,,,,,,,,${c4}*****
*******${c3},,,,,,,,,,,,,,,,,,,,,,,,,${c4}******
*******${c3}......................${c4}*******
******${c3}....${c4}***********************
$1 ///
$1 ,//////////////
$1 ///////////////////////////////
$1 ///////////////$5***********$1//////
////$5***********************$1/////
/////$5***********************$1////
//////$5,,,,,,,,,,,,,,,,,,,,,,$1///
//////$5,,,,,,,,,,,,,,,,,,,,,,,,,$1/////
/////$5,,,,,,,,,,,,,,,,,,,,,,,,,,,,$1/////
$4 *****$3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,$4*****
******$3,,,,,,,,,,,,,,,,,,,,,,,,,,,,$4*****
*******$3,,,,,,,,,,,,,,,,,,,,,,,,,$4******
*******$3......................$4*******
******$3....$4***********************
****************************
*****
+12
View File
@@ -0,0 +1,12 @@
^"^"^". `"^"""`
";;;;;:. `;;;;;;.
^;":;:;: .;,,;:;:
.'`",, '":::. ^;'';;;;, .:: ,;;;:
';;;;:":::::' ^;` `;;;;" ::. ,;;;:
";:;:. ^;` ^;;;;^ ,;. ,;;;:
";;;: ^;` ";;;;^ ";' ,;;;:
";;;: ^;` ,;;;;`^;` ,;;;:
";;;: ^;` ,;;;;;^ ,;;;:
";:;: ^;` .:;:;" ,;:;:
,;;;;. ";" .:;, :;;;;.
."""""` ^"^ '" ."""""`

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