From 6de2fbadbbe5bce1e82af8fa6e3a8cd003778830 Mon Sep 17 00:00:00 2001 From: jbSdev Date: Fri, 2 Jan 2026 03:36:35 +0100 Subject: [PATCH 1/3] Add support for reMarkable2 firmware 3.24+ with new framebuffer format - Detect firmware version from /etc/os-release - Handle ABGR32 pixel format for firmware 3.24+ - Handle new framebuffer and offset for 3.24+ --- reSnap.sh | 52 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/reSnap.sh b/reSnap.sh index 38e7d0c..d742732 100755 --- a/reSnap.sh +++ b/reSnap.sh @@ -1,6 +1,6 @@ #!/bin/sh -version="v2.5.2" +version="v2.5.3" # create temporary directory tmp_dir="/tmp/reSnap" @@ -64,6 +64,7 @@ while [ $# -gt 0 ]; do ;; -i | --invert-colors) invert_colors="true" + shift ;; -v | --version) echo "$0 version $version" @@ -78,12 +79,12 @@ while [ $# -gt 0 ]; do echo " $0 -o snapshot.png # saves the snapshot in the current directory" echo " $0 -d # display the file" echo " $0 -n # don't display the file" - echo " $0 -c # no color correction (reMarkable2)" + echo " $0 -c # no color correction (reMarkable2) - enables highlighter on 3.24+" echo " $0 -x # Copy snapshot to clipboard also" echo " $0 -f # Remove white background" echo " $0 -p # no pixel format correction (reMarkable2 version < 3.6)" echo " $0 -v # displays version" - echo " $0 --sketch # Construct sketc" + echo " $0 --sketch # Construct sketch" echo " $0 -i # Invert colors" echo " $0 -h # displays help information (this)" exit 2 @@ -132,18 +133,47 @@ if [ "$rm_version" = "reMarkable 1.0" ]; then elif [ "$rm_version" = "reMarkable 2.0" ]; then + fw_version="$(ssh_cmd grep 'VERSION_ID' /etc/os-release | cut -d '=' -f2 | tr -d '\"')" + fw_major=$(echo "$fw_version" | cut -d '.' -f1) + fw_minor=$(echo "$fw_version" | cut -d '.' -f2) + # calculate how much bytes the window is width=1872 height=1404 + # pixel format - if [ "$byte_correction" = "true" ]; then - bytes_per_pixel=2 - pixel_format="gray16" - filters="$filters,transpose=3" # 90° clockwise and vertical flip + if [ "$fw_major" -gt 3 ] || ([ "$fw_major" -eq 3 ] && [ "$fw_minor" -ge 24 ]); then + # Firmware 3.24+ uses ABGR32 format + bytes_per_pixel=4 + pixel_format="bgra" + + # Framebuffer is stored rotated, swap dimensions + fb_width=$width + fb_height=$height + width=$fb_height + height=$fb_width + + # Offset the beginning of mmap memory by + # 468 full lines and 336 pixels + # (468 * 1404 + 336) * 4 = 2629636 + # Not yet known why. Discovered by davisremmel and showed in + # https://github.com/owulveryck/goMarkableStream/issues/140 + skip_offset=2629632 + + # No transpose is needed, as dimensions are already correct + else - bytes_per_pixel=1 - pixel_format="gray8" - filters="$filters,transpose=2" # 90° counter-clockwise + # Firmware < 3.24 uses gray8/16 format + if [ "$byte_correction" = "true" ]; then + bytes_per_pixel=2 + pixel_format="gray16" + filters="$filters,transpose=3" # 90° clockwise and vertical flip + else + bytes_per_pixel=1 + pixel_format="gray8" + filters="$filters,transpose=2" # 90° counter-clockwise + fi + skip_offset=7 fi window_bytes="$((width * height * bytes_per_pixel))" @@ -161,7 +191,7 @@ elif [ "$rm_version" = "reMarkable 2.0" ]; then # it is actually the map allocated _after_ the fb0 mmap read_address="grep -C1 '/dev/fb0' /proc/$pid/maps | tail -n1 | sed 's/-.*$//'" skip_bytes_hex="$(ssh_cmd "$read_address")" - skip_bytes="$((0x$skip_bytes_hex + 7))" + skip_bytes="$((0x$skip_bytes_hex + $skip_offset))" # remarkable's dd does not have iflag=skip_bytes, so cut the command in two: # one to seek the exact amount and the second to copy in a large chunk From ceca9e8b30f31f19a730af8ed3c714aaaf5eb01e Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 2 Jan 2026 20:12:55 +0100 Subject: [PATCH 2/3] fix shellcheck --- .reSnap.sh.swp | Bin 0 -> 20480 bytes reSnap.sh | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 .reSnap.sh.swp diff --git a/.reSnap.sh.swp b/.reSnap.sh.swp new file mode 100644 index 0000000000000000000000000000000000000000..5e0f55b0ad2573c99af998eeb0cadcf3da2b878b GIT binary patch literal 20480 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 VqDYxPe#JUTa&&q2zrnQJ{{mTcil_hp literal 0 HcmV?d00001 diff --git a/reSnap.sh b/reSnap.sh index d742732..fdf35e9 100755 --- a/reSnap.sh +++ b/reSnap.sh @@ -142,7 +142,7 @@ elif [ "$rm_version" = "reMarkable 2.0" ]; then height=1404 # pixel format - if [ "$fw_major" -gt 3 ] || ([ "$fw_major" -eq 3 ] && [ "$fw_minor" -ge 24 ]); then + if [ "$fw_major" -gt 3 ] || { [ "$fw_major" -eq 3 ] && [ "$fw_minor" -ge 24 ]; }; then # Firmware 3.24+ uses ABGR32 format bytes_per_pixel=4 pixel_format="bgra" @@ -191,7 +191,7 @@ elif [ "$rm_version" = "reMarkable 2.0" ]; then # it is actually the map allocated _after_ the fb0 mmap read_address="grep -C1 '/dev/fb0' /proc/$pid/maps | tail -n1 | sed 's/-.*$//'" skip_bytes_hex="$(ssh_cmd "$read_address")" - skip_bytes="$((0x$skip_bytes_hex + $skip_offset))" + skip_bytes="$((0x$skip_bytes_hex + skip_offset))" # remarkable's dd does not have iflag=skip_bytes, so cut the command in two: # one to seek the exact amount and the second to copy in a large chunk From 0fe10a8749fdfb3bf8841b3983ba656a77f01a62 Mon Sep 17 00:00:00 2001 From: Fabian Weik Date: Fri, 2 Jan 2026 20:25:43 +0100 Subject: [PATCH 3/3] skip color correction for newer version --- reSnap.sh | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/reSnap.sh b/reSnap.sh index fdf35e9..ef5f7ac 100755 --- a/reSnap.sh +++ b/reSnap.sh @@ -147,21 +147,18 @@ elif [ "$rm_version" = "reMarkable 2.0" ]; then bytes_per_pixel=4 pixel_format="bgra" - # Framebuffer is stored rotated, swap dimensions - fb_width=$width - fb_height=$height - width=$fb_height - height=$fb_width - # Offset the beginning of mmap memory by # 468 full lines and 336 pixels # (468 * 1404 + 336) * 4 = 2629636 - # Not yet known why. Discovered by davisremmel and showed in + # Discovered by davisremmel and showed in # https://github.com/owulveryck/goMarkableStream/issues/140 skip_offset=2629632 # No transpose is needed, as dimensions are already correct - + # But swap dimensions + tmp=$height + height=$width + width=$tmp else # Firmware < 3.24 uses gray8/16 format if [ "$byte_correction" = "true" ]; then @@ -173,7 +170,13 @@ elif [ "$rm_version" = "reMarkable 2.0" ]; then pixel_format="gray8" filters="$filters,transpose=2" # 90° counter-clockwise fi + skip_offset=7 + + # color correction + if [ "$color_correction" = "true" ]; then + filters="$filters,curves=all=0.045/0 0.06/1" + fi fi window_bytes="$((width * height * bytes_per_pixel))" @@ -198,11 +201,6 @@ elif [ "$rm_version" = "reMarkable 2.0" ]; then # bytes are located in, and then we trim the resulting data with what we need. head_fb0="{ dd bs=1 skip=$skip_bytes count=0 && dd bs=$window_bytes count=1; } < /proc/$pid/mem 2>/dev/null" - # color correction - if [ "$color_correction" = "true" ]; then - filters="$filters,curves=all=0.045/0 0.06/1" - fi - else if [ "$rm_version" = "reMarkable Ferrari" ]; then