feat: multiple output modes and less logs at boot

This commit is contained in:
2026-11-04 01:04:21 +01:00
parent 3020ce3d7b
commit d0640583a1
20 changed files with 308 additions and 112 deletions
+6 -4
View File
@@ -1,6 +1,8 @@
error.glsl
forge_default_save.txt
*.log
.venv
__pycache__
build
tmp*
debug.png
forge_default_save.txt.bck
error.glsl
forge_default_save.*
tmp*
+7 -64
View File
@@ -4,7 +4,8 @@ PROJECT_DIR ?= $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
BUILD_DIR ?= $(PROJECT_DIR)/build
FORGE_SRC ?= $(PROJECT_DIR)/forge-steel
TARGET ?= forge
RUN_ARGS ?= --project=$(PROJECT_DIR)/project --internal-size=576 -nmr -t=10 --auto-save
SCREEN_HEIGHT ?= 480
RUN_ARGS ?= --project=$(PROJECT_DIR)/project -is=$(SCREEN_HEIGHT) -nmr -t=10 --auto-save
VERSION ?= invar-$(shell grep -Eo '[0-9]+\.[0-9]+\.[0-9]+' $(FORGE_SRC)/configure.ac)
SOURCES ?= $(FORGE_SRC)/src/*.h $(FORGE_SRC)/src/*.c $(FORGE_SRC)/hashmap.c/hashmap.c $(FORGE_SRC)/log.c/src/log.c
CFLAGS ?= -Ofast -Ofast -march=native -flto -funroll-loops -fprefetch-loop-arrays -fno-exceptions -fopenmp -I$(FORGE_SRC)/include -DGLFW_INCLUDE_NONE -DGLFW_NATIVE_INCLUDE_NONE -DLOG_USE_COLOR -DVERSION=\"$(VERSION)\" -DOPENGL_MAJOR_VERSION=3 -DOPENGL_MINOR_VERSION=1
@@ -12,7 +13,7 @@ LDLIBS ?= -lm -lGL -lglfw -lasound
# FILES
$(BUILD_DIR)/$(TARGET): forge-steel/src/main.c forge-steel/hashmap.c/hashmap.c forge-steel/log.c/src/log.c forge-steel/include/linmath.h
$(BUILD_DIR)/$(TARGET):
mkdir -p $(BUILD_DIR)
$(CC) $(SOURCES) $(CFLAGS) $(LDLIBS) -o $(BUILD_DIR)/$(TARGET)
@@ -31,14 +32,6 @@ apt-install:
pip-install:
pip3 install luma.oled --break-system-packages
.PHONY: setup-weston
setup-weston:
ln -fs $(PROJECT_DIR)/system/weston.ini $(HOME)/.config/weston.ini
.PHONY: remove-motd
remove-motd:
sudo rm -rf /etc/motd
.PHONY: disable-cloud-init
disable-cloud-init:
sudo systemctl disable cloud-init.service
@@ -51,12 +44,8 @@ setup-services:
sudo systemctl daemon-reload
sudo systemctl enable getty@tty1.service seatd.service
.PHONY: setup-bashrc
setup-bashrc:
$(PROJECT_DIR)/scripts/line_in_file.sh "make -C $(PROJECT_DIR) --no-print-directory start" "$(HOME)/.bashrc"
.PHONY: install
install: remove-passwd apt-install pip-install setup-weston remove-motd disable-cloud-init setup-services setup-bashrc
install: remove-passwd apt-install pip-install disable-cloud-init setup-services
.PHONY: clean
clean:
@@ -67,61 +56,15 @@ build: $(BUILD_DIR)/$(TARGET)
.PHONY: run
run: $(BUILD_DIR)/$(TARGET)
$(BUILD_DIR)/$(TARGET) $(RUN_ARGS)
@$(BUILD_DIR)/$(TARGET) $(RUN_ARGS) 2>&1 >> $(PROJECT_DIR)/forge.log
.PHONY: start-bg
start-bg:
@python3 $(PROJECT_DIR)/__main__.py &> $(PROJECT_DIR)/python.log &
@python3 $(PROJECT_DIR)/__main__.py 2>&1 >> $(PROJECT_DIR)/python.log 2>&1
.PHONY: start-fg
start-fg:
@echo "on" | sudo tee /sys/class/drm/card1-Composite-1/status || true
@/usr/bin/weston --shell=kiosk-shell.so --xwayland --log=$(PROJECT_DIR)/weston.log -- kitty --hold make --no-print-directory -C $(PROJECT_DIR) run
@/usr/bin/weston --shell=kiosk-shell.so --xwayland --log=$(PROJECT_DIR)/weston.log -- kitty --hold make --silent --no-print-directory -C $(PROJECT_DIR) run 2>&1 > /dev/null
.PHONY: start
start: start-bg start-fg
# HOST ONLY
.PHONY: host-submodule-update
host-submodule-update:
git submodule update --init --recursive
.PHONY: host-chmod-opt
host-chmod-opt:
sudo chmod a+rwx /run/media/$(shell whoami)/rootfs/opt/
.PHONY: host-rsync
host-rsync: host-chmod-opt
rsync -a $(PWD) /run/media/$(shell whoami)/rootfs/opt/
.PHONY: host-setup-custom
host-setup-custom:
cp $(PROJECT_DIR)/system/config.ini /run/media/$(shell whoami)/bootfs/custom.txt
.PHONY: host-reset-config
host-reset-config:
sed -i '/include custom.txt/d' /run/media/$(shell whoami)/bootfs/config.txt
.PHONY: host-setup-config
host-setup-config: host-setup-custom host-reset-config
echo "include custom.txt" >> /run/media/$(shell whoami)/bootfs/config.txt
.PHONY: host-reset-cmdline
host-reset-cmdline:
sed -i '2,$$d' /run/media/$(shell whoami)/bootfs/cmdline.txt
.PHONY: host-setup-cmdline
host-setup-cmdline: host-reset-cmdline
cat $(PROJECT_DIR)/system/cmdline.txt >> /run/media/$(shell whoami)/bootfs/cmdline.txt
.PHONY: host-unmount
host-unmount:
sudo umount -R /run/media/$(shell whoami)/rootfs
sudo umount -R /run/media/$(shell whoami)/bootfs
.PHONY: host-install
host-install: host-submodule-update host-rsync host-setup-config host-setup-cmdline host-unmount
.PHONY: host-install-reset
host-install-reset: host-submodule-update host-rsync host-reset-config host-reset-cmdline host-unmount
+163
View File
@@ -0,0 +1,163 @@
# ENV
ifeq (,$(shell which uv))
ifeq (,$(shell python3 -m uv --help||python3 -m pip install --user uv)) # detect uv install
UV ?= false
endif
UV ?= python3 -m uv
endif
UV ?= uv
RUFF ?= $(UV) run --active ruff
TY ?= $(UV) run --active ty
RASP_USER ?= forge
RASP_BOOTFS ?= /run/media/$(shell whoami)/bootfs
RASP_ROOTFS ?= /run/media/$(shell whoami)/rootfs
RELATIVE_PROJECT_PATH ?= /opt/forge-invar
RASP_PROJECT_PATH ?= $(RASP_ROOTFS)$(RELATIVE_PROJECT_PATH)
# DOCS
.PHONY: help
help: ## show this message
@echo "Usage: $(MAKE) [target1] [target2] ..."
@echo ""
@echo "Commands/Targets:"
@cat $(MAKEFILE_LIST) | grep -E '(^[a-zA-Z0-9_%-]+:.*?##.*$$)|(^##)' | awk 'BEGIN {FS = ":.*?## "}{printf "\033[32m%-20s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/'
@echo ""
@echo "Environment:"
@cat $(MAKEFILE_LIST) | grep -E '^[a-zA-Z0-9_-]+\s*\??=.*$$' | grep -Eo '^[a-zA-Z0-9_-]+' | xargs -I {} $(MAKE) -s print-{} 2> /dev/null
.PHONY: print-%
print-%:
@echo -e '\033[32m$*\033[0m = $($*)'
# FILES
.venv: uv.lock
$(MAKE) -s uv-sync
# ACTIONS
.PHONY: init
init: uv-sync git-submodule-init git-submodule-update ## install project
.PHONY: update
update: uv-upgrade ## update project dependencies
.PHONY: format
format: ruff-fix ruff-format ## format project
.PHONY: lint
lint: ruff ruff-format-check ty ## lint project
.PHONY: rasp-init
rasp-init: rasp-chmod-opt rasp-rsync rasp-unmount ## init raspberry
.PHONY: rasp-install
rasp-install: rasp-install-pal ## setup raspberry
.PHONY: rasp-install-%
rasp-install-%: ## setup raspberry (PAL/NTSC/HDMI)
make git-submodule-update rasp-rsync rasp-setup-config-$* rasp-setup-cmdline-$* rasp-setup-start-$* rasp-unmount
.PHONY: rasp-reset
rasp-reset: rasp-reset-config rasp-reset-cmdline rasp-reset-start rasp-unmount ## reset raspberry to console mode
# TOOLS
.PHONY: uv-sync
uv-sync: ## uv sync
$(UV) sync --active
.PHONY: uv-update
uv-upgrade: ## uv sync upgrade
$(UV) sync --active --upgrade
.PHONY: ruff
ruff: .venv ## ruff check
$(RUFF) check
.PHONY: ruff-fix
ruff-fix: .venv ## ruff check (and fix)
$(RUFF) check --fix --unsafe-fixes
.PHONY: ruff-format
ruff-format: .venv ## ruff format
$(RUFF) format
.PHONY: ruff-format-check
ruff-format-check: .venv ## ruff format (check only)
$(RUFF) format --check
.PHONY: ty
ty: .venv ## ty check
$(TY) check
.PHONY: git-submodule-update
git-submodule-update: ## prepare git submodules
git submodule update --init --recursive
.PHONY: rasp-chmod-opt
rasp-chmod-opt: ## chmod remote project
sudo chmod -R a+rwx $(RASP_ROOTFS)/opt
.PHONY: rasp-remove-motd
rasp-remove-motd: ##
sudo rm -rf $(RASP_ROOTFS)/etc/motd
sudo rm -rf $(RASP_ROOTFS)/etc/issue
sudo rm -rf $(RASP_ROOTFS)/etc/update-motd.d/*
.PHONY: rasp-rsync
rasp-rsync: ## sync remote project
rsync -av --del --exclude='*/.git/*' --exclude-from=.gitignore $(PWD) $(RASP_ROOTFS)/opt
.PHONY: rasp-setup-custom-%
rasp-setup-custom-%: ## setup custom remote config.txt
cp $(PROJECT_DIR)/system/$*/config.ini $(RASP_BOOTFS)/custom.txt
.PHONY: rasp-reset-config
rasp-reset-config: ## remove include in remote config.txt
sed -i '/include custom.txt/d' $(RASP_BOOTFS)/config.txt
.PHONY: rasp-setup-config-%
rasp-setup-config-%: ## setup include in remote config.txt
make rasp-setup-custom-$* rasp-reset-config
echo "include custom.txt" >> $(RASP_BOOTFS)/config.txt
.PHONY: rasp-reset-cmdline
rasp-reset-cmdline: ## remove custom line from remove cmdline.txt
sed -i '2,$$d' $(RASP_BOOTFS)/cmdline.txt
sed -i 's/console=tty3/console=tty1/g' $(RASP_BOOTFS)/cmdline.txt
.PHONY: rasp-setup-cmdline-%
rasp-setup-cmdline-%: rasp-reset-cmdline ## add custom line to remove cmdline.txt
sed -i 's/console=tty1/console=tty3/g' $(RASP_BOOTFS)/cmdline.txt
cat $(PROJECT_DIR)/system/$*/cmdline.txt >> $(RASP_BOOTFS)/cmdline.txt
.PHONY: rasp-reset-start
rasp-reset-start: ## remove custom .bashrc start
rm -f $(RASP_ROOTFS)/home/$(RASP_USER)/.bash_aliases
.PHONY: rasp-setup-start
rasp-setup-start: rasp-reset-start ## install custom .bashrc start
echo "touch $(RELATIVE_PROJECT_PATH)/*" >> $(RASP_ROOTFS)/home/$(RASP_USER)/.bash_aliases
echo "make -C $(RELATIVE_PROJECT_PATH) --silent --no-print-directory start" >> $(RASP_ROOTFS)/home/$(RASP_USER)/.bash_aliases
.PHONY: rasp-setup-start-hmdi
rasp-setup-start-%: rasp-reset-start ## install custom .bashrc start
cp -f $(PROJECT_DIR)/system/$*/start.sh $(RASP_ROOTFS)/home/$(RASP_USER)/.bash_aliases
.PHONY: rasp-unmount
rasp-unmount: ## unmount rootfs/bootfs
sudo umount -R $(RASP_BOOTFS)
sudo umount -R $(RASP_ROOTFS)
.PHONY: rasp-force-rebuild
rasp-force-rebuild: ## rm remote project/build
rm -rf $(RASP_PROJECT_PATH)/build
.PHONY: rasp-import-logs
rasp-import-logs: ## import remote logs
cp -f $(RASP_PROJECT_PATH)/*.log .
+40 -13
View File
@@ -4,17 +4,40 @@
## Install
## 1. Prepare raspberry SD card
Use [raspi-imager](https://www.raspberrypi.com/software/) and select "Raspberry Pi OS Lite" (in other options)
## 2. Add project to rasp
Re-mount SD card (auto unmounted by raspi-imager)
```bash
sudo apt update
sudo apt install -y git
sudo chmod a+rwx /opt
cd /opt
git clone --recursive https://git.klemek.fr/klemek/forge-invar
cd forge-invar
make install build
echo 'make -C /opt/forge-invar start-weston' >> ~/.bashrc
# host
make -f Makefile.dev rasp-init
```
## 3. Install dependencies in raspberry
Boot raspberry
```bash
# raspberry
cd /opt/forge-invar
make install build
```
## 4. Setup PAL output
Re-mount SD card
```bash
# host
make -f Makefile.dev rasp-install
```
## 5. Enjoy
## Links
* https://www.raspberrypi.com/documentation/computers/config_txt.html
@@ -34,20 +57,24 @@ echo 'make -C /opt/forge-invar start-weston' >> ~/.bashrc
* https://electricalflux.com/mcu-raspberry/i2c-oled-display-raspberry-pi-5-wiring-code
* https://www.raspberrypi.com/documentation/computers/configuration.html
* https://int10h.org/oldschool-pc-fonts/fontlist/font?ibm_bios
* https://raspberrypihq.com/use-a-push-button-with-raspberry-pi-gpio/
## TODO
Logical
* [x] Play on start
* [ ] disable services for faster boot
* [x] disable services for faster boot
* [x] remove texts on boot
* [ ] special texts in demo vs classic
* [x] Save while running
* [ ] I2C monitor screen write
* [x] I2C monitor screen write
* [ ] fix logs on machine
Physical
* [ ] PAL/NTSC switch
* [ ] Sync in -> fake keyboard
* [x] I2C screen
* [ ] Sync in
* [ ] buttons input (save/load states, random, reset, demo)
* [ ] rasp compute
* [ ] I2C screen
* [ ] PAL/NTSC switch (hard)
-14
View File
@@ -1,14 +0,0 @@
#!/bin/bash
set -e
LINE=$1
FILE=$2
DETECT=${3:-$LINE}
if [[ -z $(grep "$DETECT" "$FILE") ]]; then
echo "Line not found in $FILE"
echo -n "$LINE" >> "$FILE"
else
echo "Fragment already exists in $FILE"
fi
-14
View File
@@ -1,14 +0,0 @@
#!/bin/bash
set -e
LINE=$1
FILE=$2
DETECT=${3:-$LINE}
if [[ -z $(grep "$DETECT" "$FILE") ]]; then
echo "Line not found in $FILE"
echo "$LINE" >> "$FILE"
else
echo "Line already exists in $FILE"
fi
-1
View File
@@ -1 +0,0 @@
vc4.tv_norm=PAL video=Composite-1:720x576ie,tv_mode=PAL quiet loglevel=0 consoleblank=1
+1 -1
View File
@@ -21,7 +21,7 @@ Before=rescue.service
ConditionPathExists=/dev/tty0
[Service]
ExecStart=-/sbin/agetty --autologin forge --noreset --noclear %I ${TERM}
ExecStart=-/sbin/agetty --autologin forge --noissue --nohints --nohostname --noreset --noclear %I ${TERM}
Type=idle
Restart=always
RestartSec=0
+1
View File
@@ -0,0 +1 @@
quiet loglevel=3 quiet logo.nologo vt.global_cursor_default=0
+22
View File
@@ -0,0 +1,22 @@
[all]
# --- overclocking ---
# ARM core frequency in MHz
arm_freq=3000
# VideoCore VII frequency in MHz
gpu_freq=1000
# Voltage offset in microvolts
over_voltage_delta=50000
# --- opengl ---
# Enable DRM VC4 V3D driver
dtoverlay=vc4-kms-v3d
# Increase the memory reserved for the GPU
gpu_mem=64
# Avoid GPU down-clocking below 500 MHz that slows FPS down
# v3d_freq_min=500
# --- composite ---
enable_tvout=0
# --- I2C ---
dtparam=i2c_arm=on
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
export PROJECT_DIR=/opt/forge-invar
export SCREEN_HEIGHT=576
ln -fs $PROJECT_DIR/system/hdmi/weston.ini $HOME/.config/weston.ini
rm -rf $PROJECT_DIR/*.log
touch $PROJECT_DIR/*
make -C /opt/forge-invar --silent --no-print-directory start
+3
View File
@@ -0,0 +1,3 @@
[core]
idle-time=0
require-input=false
+2
View File
@@ -0,0 +1,2 @@
vc4.tv_norm=NTSC video=Composite-1:720x480ie,tv_mode=NTSC
quiet loglevel=0 quiet logo.nologo vt.global_cursor_default=0
+1 -1
View File
@@ -17,7 +17,7 @@ gpu_mem=64
# --- composite ---
enable_tvout=1
sdtv_mode=2
sdtv_mode=0
sdtv_aspect=1
# --- I2C ---
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
export PROJECT_DIR=/opt/forge-invar
export SCREEN_HEIGHT=480
ln -fs $PROJECT_DIR/system/ntsc/weston.ini $HOME/.config/weston.ini
rm -rf $PROJECT_DIR/*.log
touch $PROJECT_DIR/*
make -C /opt/forge-invar --silent --no-print-directory start
+8
View File
@@ -0,0 +1,8 @@
[core]
idle-time=0
require-input=false
[output]
name=Composite-1
mode=720x480i
force-on=true
+2
View File
@@ -0,0 +1,2 @@
vc4.tv_norm=PAL video=Composite-1:720x576ie,tv_mode=PAL
quiet loglevel=0 quiet logo.nologo vt.global_cursor_default=0
+22
View File
@@ -0,0 +1,22 @@
[all]
# --- overclocking ---
# ARM core frequency in MHz
arm_freq=3000
# VideoCore VII frequency in MHz
gpu_freq=1000
# Voltage offset in microvolts
over_voltage_delta=50000
# --- opengl ---
# Enable DRM VC4 V3D driver
dtoverlay=vc4-kms-v3d,composite
# Increase the memory reserved for the GPU
gpu_mem=64
# Avoid GPU down-clocking below 500 MHz that slows FPS down
# v3d_freq_min=500
# --- composite ---
enable_tvout=1
# --- I2C ---
dtparam=i2c_arm=on
+10
View File
@@ -0,0 +1,10 @@
#!/bin/sh
export PROJECT_DIR=/opt/forge-invar
export SCREEN_HEIGHT=576
ln -fs $PROJECT_DIR/system/pal/weston.ini $HOME/.config/weston.ini
rm -rf $PROJECT_DIR/*.log
touch $PROJECT_DIR/*
make -C /opt/forge-invar --silent --no-print-directory start