Skip to content

Instantly share code, notes, and snippets.

@Langerz82
Last active November 8, 2025 09:34
Show Gist options
  • Select an option

  • Save Langerz82/e4afb12568d3717cdde2d95470e0ea02 to your computer and use it in GitHub Desktop.

Select an option

Save Langerz82/e4afb12568d3717cdde2d95470e0ea02 to your computer and use it in GitHub Desktop.
EmuELEC 4.3 - setres revised.
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert)
# Copyright (C) 2022-present Joshua L (https://github.com/Langerz82)
# 2025-present DiegroSan (https://github.com/Diegrosan)
# Read the video output mode and set it for emuelec to avoid video flicking.
# This file sets the hdmi output and frame buffer to the argument in pixel width.
# Allowed argument example ./setres.sh 1080p60hz <-- For height 1080 pixels.
# set -x #echo on
# Source predefined functions and variables
. /etc/profile
FILE_MODE="/sys/class/display/mode"
PLATFORM=""
#here we look for the best framebuffer; the default is fb0, but on some devices it is fb1. Here we choose the best available,
#thus achieving the best video performance.
max_area=0
max_fb=""
for fb in /sys/class/graphics/fb*/virtual_size; do
if [ -f "$fb" ]; then
fb_num=$(echo "$fb" | grep -o 'fb[0-9]*' | sed 's/fb//')
size=$(cat "$fb")
width=$(echo "$size" | cut -d',' -f1)
height=$(echo "$size" | cut -d',' -f2)
area=$((width * height))
if [ $area -gt $max_area ]; then
max_area=$area
max_fb=$fb_num
fi
fi
done
blank_buffer() {
# Clears screen buffer
# Blank the buffer.
dd if=/dev/zero of=/dev/fb0 bs=256K conv=sync,noerror,notrunc > /dev/null 2>&1
dd if=/dev/zero of=/dev/fb1 bs=256K conv=sync,noerror,notrunc > /dev/null 2>&1
}
switch_resolution()
{
local MODE=${1}
# Here we first clear the primary display buffer of leftover artifacts then set
# the secondary small buffers flag to stop copying across.
echo 1 > /sys/class/graphics/fb${max_fb}/blank
case ${MODE} in
480cvbs|576cvbs|480p*|480i*|576p*|720p*|1080p*|1440p*|2160p*|576i*|720i*|1080i*|1440i*|2160i*|*x*)
echo null > "${FILE_MODE}"
sleep 1
echo ${MODE} > "${FILE_MODE}"
esac
echo 0 > /sys/class/graphics/fb${max_fb}/blank
NEW_MODE=$( cat ${FILE_MODE} )
[[ "${NEW_MODE}" != "${MODE}" ]] && exit 1
}
get_resolution_size()
{
local MODE=${1}
# Here we set the Height and Width of the particular resolution.
# FBW - Frame Buffer Width, PSW - Physical Screen Width.
# FBH - Frame Buffer Height, PSH - Physical Screen Height.
local FBW=${2}
local FBH=${3}
local PSW=0
local PSH=0
case ${MODE} in
480cvbs)
PSW=720
PSH=480
[[ -z "${FBW}" ]] && FBW=1024
[[ -z "${FBH}" ]] && FBH=768
;;
576cvbs)
PSW=720
PSH=576
[[ -z "${FBW}" ]] && FBW=1024
[[ -z "${FBH}" ]] && FBH=768
;;
480p*|480i*|576p*|720p*|1080p*|1440p*|2160p*|576i*|720i*|1080i*|1440i*|2160i*)
# For resolution with 2 width and height resolution numbers extract the Height.
# *p* stand for progressive and *i* stand for interlaced.
case ${MODE} in
*p*) PSH=$(echo ${MODE} | cut -d'p' -f 1) ;;
*i*) PSH=$(echo ${MODE} | cut -d'i' -f 1) ;;
esac
PSW=$(( ${PSH}*16/9 ))
[[ "${MODE}" == "480"* ]] && PSW=640
[[ -z "${FBW}" || ${FBW} == 0 ]] && FBW=${PSW}
[[ -z "${FBH}" || ${FBH} == 0 ]] && FBH=${PSH}
;;
*x*)
PSW=$(echo ${MODE} | cut -d'x' -f 1)
PSH=$(echo ${MODE} | cut -d'x' -f 2 | cut -d'p' -f 1)
[ ! -n "${PSH}" ] && PSH=$(echo ${MODE} | cut -d'x' -f 2 | cut -d'i' -f 1)
[[ -z "${FBW}" || ${FBW} == 0 ]] && FBW=${PSW}
[[ -z "${FBH}" || ${FBH} == 0 ]] && FBH=${PSH}
;;
esac
echo "${FBW} ${FBH} ${PSW} ${PSH}"
}
set_main_framebuffer() {
local FBW=${1}
local FBH=${2}
local BPP=32
if [[ -n "${FBW}" && "${FBW}" > 0 && -n "${FBH}" && "${FBH}" > 0 ]]; then
MFBH=$(( FBH*2 ))
fbset -fb /dev/fb${max_fb} -g ${FBW} ${FBH} ${FBW} ${MFBH} ${BPP}
[[ -f "/sys/class/graphics/fb${max_fb}/free_scale_axis" ]] && echo 0 0 $(( FBW-1 )) $(( FBH-1 )) > /sys/class/graphics/fb${max_fb}/free_scale_axis
[[ -f "/sys/class/graphics/fb${max_fb}/free_scale" ]] && echo 0 > /sys/class/graphics/fb${max_fb}/free_scale
[[ -f "/sys/class/graphics/fb${max_fb}/freescale_mode" ]] && echo 0 > /sys/class/graphics/fb${max_fb}/freescale_mode
fi
}
set_fb_borders() {
local CUSTOM_OFFSETS=( ${1} ${2} ${3} ${4} )
local COUNT_ARGS=${#CUSTOM_OFFSETS[@]}
if [[ "${COUNT_ARGS}" == "4" ]]; then
echo ${CUSTOM_OFFSETS[@]} > /sys/class/graphics/fb${max_fb}/window_axis
echo 1 > /sys/class/graphics/fb${max_fb}/freescale_mode
echo 0x10001 > /sys/class/graphics/fb${max_fb}/free_scale
fi
}
# Here we initialize any arguments and variables to be used in the script.
# The Mode we want the display to change too.
MODE=$( cat ${FILE_MODE} )
BPP=32
ES_MODE=""
if [[ $# == 0 ]]; then
MODE=$(cat /sys/class/display/mode)
ES_MODE="ee_es."
fi
if [[ $# == 1 ]]; then
MODE=${1}
ES_MODE="ee_es."
fi
if [[ $# == 2 ]]; then
MODE=${1}
PLATFORM=${2}
fi
if [[ $# == 3 ]]; then
MODE=${1}
PLATFORM=${2}
ROMNAME=${3}
fi
FBW=0
FBH=0
#if [[ "${EE_DEVICE}" == "Amlogic" ]]; then
# FBW=1920
# FBH=1080
#fi
# The current display mode before it may get changed below.
OLD_MODE=$( cat ${FILE_MODE} )
BORDER_VALS=$(get_ee_setting ee_videowindow)
# Legacy code, we use to set the buffer that is used for small parts of graphics
# like Cursors and Fonts but setting default 32 made ES Fonts dissappear.
BUFF=$(get_ee_setting ee_video_fb1_size)
[[ -z "${BUFF}" ]] && BUFF=32
if [[ -n "${BUFF}" ]] && [[ ${BUFF} > 0 ]]; then
[[ "${max_fb}" == 0 ]] && fbset -fb /dev/fb1 -g ${BUFF} ${BUFF} ${BUFF} ${BUFF} ${BPP}
[[ "${max_fb}" == 1 ]] && fbset -fb /dev/fb0 -g ${BUFF} ${BUFF} ${BUFF} ${BUFF} ${BPP}
fi
# This is needed to reset scaling.
[[ -f "/sys/class/ppmgr/ppscaler" ]] && echo 0 > /sys/class/ppmgr/ppscaler
# Option too Custom set the CVBS Resolution by creating a cvbs_resolution.txt file.
# File contents must just 2 different integers seperated by a space. e.g. 800 600.
CVBS_RES_FILE="/storage/.config/cvbs_resolution.txt"
if [[ "${MODE}" == *"cvbs" ]]; then
if [[ -f "${CVBS_RES_FILE}" ]]; then
declare -a CVBS_RES=($(cat "${CVBS_RES_FILE}"))
if [[ ! -z "${CVBS_RES[@]}" ]]; then
FBW=${CVBS_RES[0]}
FBH=${CVBS_RES[1]}
fi
fi
fi
CUSTOM_RES=$(get_ee_setting ${ES_MODE}framebuffer "${PLATFORM}" "${ROMNAME}")
if [[ ! -z "${CUSTOM_RES}" ]]; then
declare -a RES=($(echo "${CUSTOM_RES}"))
FBW=${RES[0]}
FBH=${RES[1]}
fi
if [[ ${OLD_MODE} != ${MODE} ]]; then
switch_resolution ${MODE}
fi
MODE=$( cat ${FILE_MODE} )
declare -a SIZE=($( get_resolution_size ${MODE} ${FBW} ${FBH}))
FBW=${SIZE[0]}
FBH=${SIZE[1]}
PSW=${SIZE[2]}
PSH=${SIZE[3]}
# Once we know the Width and Height is valid numbers we set the primary display
# buffer, and we multiply the 2nd height by a factor of 2 I assume for interlaced
# support.
CURRENT_SIZE="$( fbset -fb /dev/fb${max_fb} | grep geometry | cut -d' ' -f2-3 )"
NEW_SIZE="${FBW} ${FBH}"
if [[ "${CURRENT_SIZE}" != "${NEW_SIZE}" ]]; then
blank_buffer
echo "SET MAIN FRAME BUFFER"
set_main_framebuffer ${FBW} ${FBH}
fi
# Legacy code - I have no idea about these values but apparently they should
# make cvbs display properly. The values go over the real values which leads me
# to believe that cvbs uses longer pixel ranges because of overscanning.
declare -a CUSTOM_OFFSETS
if [[ -f "/storage/.config/${MODE}_offsets" ]]; then
CUSTOM_OFFSETS=( $( cat "/storage/.config/${MODE}_offsets" ) )
fi
OFFSET_SETTING=$(get_ee_setting ${ES_MODE}framebuffer_border "${PLATFORM}" "${ROMNAME}")
if [[ ! -z "${OFFSET_SETTING}" ]]; then
CUSTOM_OFFSETS=( ${OFFSET_SETTING} )
CUSTOM_OFFSETS[2]=$(( ${PSW} - CUSTOM_OFFSETS[2] - 1 ))
CUSTOM_OFFSETS[3]=$(( ${PSH} - CUSTOM_OFFSETS[3] - 1 ))
fi
# Now that the primary buffer has been acquired we blank it again because the new
# memory allocated, may contain garbage artifact data.
COUNT_ARGS=${#CUSTOM_OFFSETS[@]}
if [[ "${COUNT_ARGS}" == "2" ]]; then
CUSTOM_OFFSETS[2]=$(( ${PSW} - CUSTOM_OFFSETS[0] - 1 ))
CUSTOM_OFFSETS[3]=$(( ${PSH} - CUSTOM_OFFSETS[1] - 1 ))
fi
if [[ -z "${OFFSET_SETTING}" ]] && [[ "${MODE}" == *"cvbs" ]]; then
if [[ "${COUNT_ARGS}" == "0" ]]; then
[[ "${MODE}" == "480cvbs" ]] && CUSTOM_OFFSETS="30 10 669 469"
[[ "${MODE}" == "576cvbs" ]] && CUSTOM_OFFSETS="35 20 680 565"
fi
fi
COUNT_ARGS=${#CUSTOM_OFFSETS[@]}
if [[ "${COUNT_ARGS}" == "0" ]] && [[ ${FBW} != ${PSW} || ${FBH} != ${PSH} ]]; then
CUSTOM_OFFSETS=(0 0 $(( PSW - 1 )) $(( PSH - 1 )))
elif [[ "${COUNT_ARGS}" == "2" ]]; then
TMP="${CUSTOM_OFFSETS[0]}"
CUSTOM_OFFSETS[2]=$(( ${PSW} - ${TMP} - 1 ))
TMP="${CUSTOM_OFFSETS[1]}"
CUSTOM_OFFSETS[3]=$(( ${PSH} - ${TMP} - 1 ))
fi
if [[ "${#CUSTOM_OFFSETS[@]}" == "4" ]]; then
set_fb_borders ${CUSTOM_OFFSETS[@]}
exit 0
fi
# Gets the default X, and Y position offsets for cvbs so the display can fit
# inside the actual analog diplay resolution which is a bit smaller than the
# resolution it's usually transmitted as.
declare -a BORDERS
BORDER_VALS=$(get_ee_setting ee_videowindow)
if [[ ! -z "${BORDER_VALS}" ]]; then
BORDERS=(${BORDER_VALS})
COUNT_ARGS=${#BORDERS[@]}
if [[ ${COUNT_ARGS} != 4 && ${COUNT_ARGS} != 2 ]]; then
exit 0
fi
A1=${BORDERS[0]}
A2=${BORDERS[1]}
A3=${BORDERS[2]}
[[ -z "${A3}" ]] && A3=${PSW}
A4=${BORDERS[3]}
[[ -z "${A4}" ]] && A4=${PSH}
if [[ ! -n "${A1}" || ! -n "${A2}" || ! -n "${A3}" || ! -n "${A4}" ]]; then
exit 0
fi
A3=$(( PSW-A1-1 ))
A4=$(( PSH-A2-1 ))
set_fb_borders ${A1} ${A2} ${A3} ${A4}
fi
# End Legacy code
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment