From 487c4f2cbd39775113c8a8e0e70ac3e2dfcef3d7 Mon Sep 17 00:00:00 2001 From: Douglas Teles Date: Wed, 4 Feb 2026 14:09:18 -0300 Subject: [PATCH] Initial commit - Arch R project structure --- .gitignore | 13 ++ README.md | 52 +++++++ build-all.sh | 93 +++++++++++++ build-image.sh | 234 ++++++++++++++++++++++++++++++++ build-kernel.sh | 168 +++++++++++++++++++++++ build-rootfs.sh | 224 ++++++++++++++++++++++++++++++ config/retroarch.cfg | 61 +++++++++ config/udev/99-archr-r36s.rules | 38 ++++++ kernel/dts/gameconsole-r36s.dtb | Bin 0 -> 61649 bytes scripts/first-boot.sh | 101 ++++++++++++++ scripts/wifi-connect.sh | 102 ++++++++++++++ setup-toolchain.sh | 208 ++++++++++++++++++++++++++++ 12 files changed, 1294 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 build-all.sh create mode 100644 build-image.sh create mode 100644 build-kernel.sh create mode 100644 build-rootfs.sh create mode 100644 config/retroarch.cfg create mode 100644 config/udev/99-archr-r36s.rules create mode 100644 kernel/dts/gameconsole-r36s.dtb create mode 100644 scripts/first-boot.sh create mode 100644 scripts/wifi-connect.sh create mode 100644 setup-toolchain.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000..c13fac2c73 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Build output +output/ +rootfs/staging/ +*.log + +# Archives +*.tar.gz +*.xz +*.img + +# Kernel source (will be cloned separately) +kernel/src/ +bootloader/src/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000000..31a0035f63 --- /dev/null +++ b/README.md @@ -0,0 +1,52 @@ +# Arch R + +> Arch Linux-based Gaming Distribution for R36S Handheld + +## About + +Arch R is a custom Linux distribution optimized for the R36S handheld gaming console. +Based on Arch Linux ARM with full support for RetroArch and EmulationStation. + +## Building + +### Prerequisites + +- Ubuntu 22.04+ or WSL2 +- Cross-compilation toolchain for aarch64 +- 10GB+ free disk space + +### Quick Start + +```bash +# Setup build environment (run once) +./setup-toolchain.sh + +# Build everything +./build-all.sh + +# Output will be in output/ directory +``` + +## Project Structure + +``` +arch-r/ +├── bootloader/ # U-Boot configuration +├── kernel/ # Kernel source and DTB +├── rootfs/ # Root filesystem overlay +├── config/ # Configuration files +├── scripts/ # Runtime scripts +└── output/ # Build artifacts +``` + +## Hardware Support + +- **SoC**: Rockchip RK3326 +- **Display**: 640x480 +- **USB OTG**: Host mode with VBUS power +- **Wi-Fi**: AIC8800 USB adapter support +- **Controls**: Full joypad + analog sticks + +## License + +GPL v3 diff --git a/build-all.sh b/build-all.sh new file mode 100644 index 0000000000..30649584a5 --- /dev/null +++ b/build-all.sh @@ -0,0 +1,93 @@ +#!/bin/bash + +#============================================================================== +# Arch R - Master Build Script +#============================================================================== + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Load environment +if [ -f "$SCRIPT_DIR/env.sh" ]; then + source "$SCRIPT_DIR/env.sh" +else + echo "ERROR: env.sh not found. Run setup-toolchain.sh first!" + exit 1 +fi + +echo "==========================================" +echo " Arch R Build System" +echo "==========================================" +echo "" +echo "Device: $ARCHR_DEVICE" +echo "SoC: $ARCHR_SOC" +echo "" + +# Parse arguments +BUILD_KERNEL=0 +BUILD_ROOTFS=0 +BUILD_IMAGE=0 + +if [ $# -eq 0 ]; then + BUILD_KERNEL=1 + BUILD_ROOTFS=1 + BUILD_IMAGE=1 +else + for arg in "$@"; do + case $arg in + kernel) BUILD_KERNEL=1 ;; + rootfs) BUILD_ROOTFS=1 ;; + image) BUILD_IMAGE=1 ;; + all) + BUILD_KERNEL=1 + BUILD_ROOTFS=1 + BUILD_IMAGE=1 + ;; + *) + echo "Unknown option: $arg" + echo "Usage: $0 [kernel|rootfs|image|all]" + exit 1 + ;; + esac + done +fi + +# Build steps +if [ $BUILD_KERNEL -eq 1 ]; then + echo "" + echo "=== Building Kernel ===" + if [ -x "$SCRIPT_DIR/build-kernel.sh" ]; then + "$SCRIPT_DIR/build-kernel.sh" + else + echo "WARNING: build-kernel.sh not found or not executable" + fi +fi + +if [ $BUILD_ROOTFS -eq 1 ]; then + echo "" + echo "=== Building Root Filesystem ===" + if [ -x "$SCRIPT_DIR/build-rootfs.sh" ]; then + "$SCRIPT_DIR/build-rootfs.sh" + else + echo "WARNING: build-rootfs.sh not found or not executable" + fi +fi + +if [ $BUILD_IMAGE -eq 1 ]; then + echo "" + echo "=== Building SD Card Image ===" + if [ -x "$SCRIPT_DIR/build-image.sh" ]; then + "$SCRIPT_DIR/build-image.sh" + else + echo "WARNING: build-image.sh not found or not executable" + fi +fi + +echo "" +echo "==========================================" +echo " Build Complete!" +echo "==========================================" +echo "" +echo "Output files are in: $ARCHR_OUTPUT" +ls -la "$ARCHR_OUTPUT" 2>/dev/null || echo "(empty)" diff --git a/build-image.sh b/build-image.sh new file mode 100644 index 0000000000..1c8786b392 --- /dev/null +++ b/build-image.sh @@ -0,0 +1,234 @@ +#!/bin/bash + +#============================================================================== +# Arch R - SD Card Image Build Script +#============================================================================== +# Creates a bootable SD card image for R36S +#============================================================================== + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Load environment +if [ -f "$SCRIPT_DIR/env.sh" ]; then + source "$SCRIPT_DIR/env.sh" +else + echo "ERROR: env.sh not found!" + exit 1 +fi + +LOG_FILE="$ARCHR_OUTPUT/build-image.log" +IMAGE_FILE="$ARCHR_OUTPUT/archr-r36s.img" +IMAGE_SIZE="4G" # Minimum image size + +log() { + echo "[$(date '+%H:%M:%S')] $1" | tee -a "$LOG_FILE" +} + +log "=== Arch R Image Build ===" + +#------------------------------------------------------------------------------ +# Check root +#------------------------------------------------------------------------------ +if [ "$EUID" -ne 0 ]; then + log "This script needs root for loop device operations." + log "Please run: sudo $0" + exit 1 +fi + +#------------------------------------------------------------------------------ +# Check prerequisites +#------------------------------------------------------------------------------ +log "" +log "Checking prerequisites..." + +BOOT_FILES="$ARCHR_OUTPUT/boot" +ROOTFS_ARCHIVE="$ARCHR_OUTPUT/archr-rootfs.tar.gz" + +if [ ! -d "$BOOT_FILES" ] || [ ! -f "$BOOT_FILES/Image" ]; then + log "ERROR: Kernel not built. Run build-kernel.sh first." + exit 1 +fi + +if [ ! -f "$ROOTFS_ARCHIVE" ]; then + log "ERROR: Rootfs not built. Run build-rootfs.sh first." + exit 1 +fi + +log " Prerequisites OK" + +#------------------------------------------------------------------------------ +# Step 1: Create image file +#------------------------------------------------------------------------------ +log "" +log "Step 1: Creating image file..." + +rm -f "$IMAGE_FILE" +truncate -s "$IMAGE_SIZE" "$IMAGE_FILE" +log " Created: $IMAGE_FILE ($IMAGE_SIZE)" + +#------------------------------------------------------------------------------ +# Step 2: Partition image +#------------------------------------------------------------------------------ +log "" +log "Step 2: Partitioning image..." + +# Partition layout: +# 0MB-1MB: Reserved for bootloader (idbloader, u-boot) +# 1MB-129MB: Boot partition (FAT32) +# 129MB-end: Root partition (ext4) + +parted -s "$IMAGE_FILE" mklabel msdos +parted -s "$IMAGE_FILE" mkpart primary fat32 1MiB 129MiB +parted -s "$IMAGE_FILE" mkpart primary ext4 129MiB 100% +parted -s "$IMAGE_FILE" set 1 boot on + +log " Partitions created" + +#------------------------------------------------------------------------------ +# Step 3: Setup loop device +#------------------------------------------------------------------------------ +log "" +log "Step 3: Setting up loop device..." + +LOOP_DEV=$(losetup --find --show --partscan "$IMAGE_FILE") +log " Loop device: $LOOP_DEV" + +# Wait for partitions to appear +sleep 2 + +BOOT_PART="${LOOP_DEV}p1" +ROOT_PART="${LOOP_DEV}p2" + +#------------------------------------------------------------------------------ +# Step 4: Format partitions +#------------------------------------------------------------------------------ +log "" +log "Step 4: Formatting partitions..." + +mkfs.vfat -F 32 -n BOOT "$BOOT_PART" +log " Formatted: $BOOT_PART (FAT32)" + +mkfs.ext4 -L ROOT "$ROOT_PART" +log " Formatted: $ROOT_PART (ext4)" + +#------------------------------------------------------------------------------ +# Step 5: Mount and populate +#------------------------------------------------------------------------------ +log "" +log "Step 5: Mounting partitions..." + +MOUNT_DIR="$ARCHR_OUTPUT/mnt" +BOOT_MOUNT="$MOUNT_DIR/boot" +ROOT_MOUNT="$MOUNT_DIR/root" + +mkdir -p "$BOOT_MOUNT" "$ROOT_MOUNT" +mount "$BOOT_PART" "$BOOT_MOUNT" +mount "$ROOT_PART" "$ROOT_MOUNT" + +log " Mounted partitions" + +#------------------------------------------------------------------------------ +# Step 6: Copy boot files +#------------------------------------------------------------------------------ +log "" +log "Step 6: Copying boot files..." + +# Copy kernel +cp "$BOOT_FILES/Image" "$BOOT_MOUNT/" +log " Copied: Image" + +# Copy DTB +if [ -f "$BOOT_FILES/rk3326-r36s.dtb" ]; then + cp "$BOOT_FILES/rk3326-r36s.dtb" "$BOOT_MOUNT/" + log " Copied: rk3326-r36s.dtb" +fi + +# Create boot.ini for R36S +cat > "$BOOT_MOUNT/boot.ini" << 'EOF' +# Arch R Boot Configuration for R36S + +setenv bootargs "root=/dev/mmcblk0p2 rootwait rw console=ttyFIQ0 quiet splash loglevel=0" + +setenv loadaddr "0x02000000" +setenv initrd_loadaddr "0x01100000" +setenv dtb_loadaddr "0x01f00000" + +load mmc 1:1 ${loadaddr} Image +load mmc 1:1 ${dtb_loadaddr} rk3326-r36s.dtb + +booti ${loadaddr} - ${dtb_loadaddr} +EOF + +log " Created: boot.ini" + +#------------------------------------------------------------------------------ +# Step 7: Extract rootfs +#------------------------------------------------------------------------------ +log "" +log "Step 7: Extracting rootfs..." + +tar -xzf "$ROOTFS_ARCHIVE" -C "$ROOT_MOUNT/" +log " Rootfs extracted" + +# Create fstab +cat > "$ROOT_MOUNT/etc/fstab" << 'EOF' +# Arch R fstab +/dev/mmcblk0p1 /boot vfat defaults 0 2 +/dev/mmcblk0p2 / ext4 defaults,noatime 0 1 +EOF + +log " Created: /etc/fstab" + +#------------------------------------------------------------------------------ +# Step 8: Install bootloader (if available) +#------------------------------------------------------------------------------ +log "" +log "Step 8: Installing bootloader..." + +UBOOT_DIR="$ARCHR_BOOTLOADER/output" +if [ -f "$UBOOT_DIR/idbloader.img" ] && [ -f "$UBOOT_DIR/u-boot.itb" ]; then + dd if="$UBOOT_DIR/idbloader.img" of="$LOOP_DEV" seek=64 conv=notrunc + dd if="$UBOOT_DIR/u-boot.itb" of="$LOOP_DEV" seek=16384 conv=notrunc + log " Bootloader installed" +else + log " WARNING: U-Boot not found. You may need to install it manually." + log " For now, the image will use the existing bootloader on SD card." +fi + +#------------------------------------------------------------------------------ +# Step 9: Cleanup +#------------------------------------------------------------------------------ +log "" +log "Step 9: Cleanup..." + +sync +umount "$BOOT_MOUNT" +umount "$ROOT_MOUNT" +losetup -d "$LOOP_DEV" + +rmdir "$BOOT_MOUNT" "$ROOT_MOUNT" "$MOUNT_DIR" + +log " Cleanup complete" + +#------------------------------------------------------------------------------ +# Step 10: Compress image +#------------------------------------------------------------------------------ +log "" +log "Step 10: Compressing image..." + +xz -z -k -9 -T 0 "$IMAGE_FILE" 2>&1 | tee -a "$LOG_FILE" +log " Created: ${IMAGE_FILE}.xz" + +#------------------------------------------------------------------------------ +# Complete +#------------------------------------------------------------------------------ +log "" +log "=== Image Build Complete ===" +log "" +log "Output files:" +ls -lh "$IMAGE_FILE"* +log "" +log "To flash to SD card:" +log " xzcat ${IMAGE_FILE}.xz | sudo dd of=/dev/sdX bs=4M status=progress" diff --git a/build-kernel.sh b/build-kernel.sh new file mode 100644 index 0000000000..78db0dc8fe --- /dev/null +++ b/build-kernel.sh @@ -0,0 +1,168 @@ +#!/bin/bash + +#============================================================================== +# Arch R - Kernel Build Script +#============================================================================== +# Builds the Linux kernel with R36S Device Tree +#============================================================================== + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Load environment +if [ -f "$SCRIPT_DIR/env.sh" ]; then + source "$SCRIPT_DIR/env.sh" +else + echo "ERROR: env.sh not found!" + exit 1 +fi + +LOG_FILE="$ARCHR_OUTPUT/build-kernel.log" + +log() { + echo "[$(date '+%H:%M:%S')] $1" | tee -a "$LOG_FILE" +} + +log "=== Arch R Kernel Build ===" + +#------------------------------------------------------------------------------ +# Configuration +#------------------------------------------------------------------------------ + +# Kernel source - You can use: +# 1. Rockchip BSP kernel (4.4.x) - More hardware support +# 2. Mainline kernel (5.x/6.x) - Newer features but may need more patches + +KERNEL_VERSION="4.4.189" +KERNEL_SRC_DIR="$ARCHR_KERNEL/src/linux-$KERNEL_VERSION" + +# If using dArkOS kernel source +DARKOS_KERNEL_URL="" # Set this to your kernel source repo + +#------------------------------------------------------------------------------ +# Step 1: Check/Download Kernel Source +#------------------------------------------------------------------------------ +log "" +log "Step 1: Checking kernel source..." + +if [ -d "$KERNEL_SRC_DIR" ]; then + log " Kernel source exists at: $KERNEL_SRC_DIR" +else + log " Kernel source not found!" + log "" + log " You need to provide the kernel source. Options:" + log " 1. Copy the dArkOS kernel source to: $KERNEL_SRC_DIR" + log " 2. Clone from a git repository" + log "" + log " Example:" + log " git clone $KERNEL_SRC_DIR" + log "" + exit 1 +fi + +#------------------------------------------------------------------------------ +# Step 2: Apply R36S Device Tree +#------------------------------------------------------------------------------ +log "" +log "Step 2: Checking Device Tree..." + +DTS_FILE="$ARCHR_KERNEL/dts/rk3326-r36s.dts" +if [ ! -f "$DTS_FILE" ]; then + log " R36S DTS not found. Creating from template..." + + # Check if we have the original DTB to decompile + if [ -f "$SCRIPT_DIR/../gameconsole-r36s.dtb" ]; then + log " Found gameconsole-r36s.dtb, decompiling..." + dtc -I dtb -O dts "$SCRIPT_DIR/../gameconsole-r36s.dtb" -o "$DTS_FILE" 2>/dev/null + log " Created: $DTS_FILE" + else + log " ERROR: No DTB or DTS found!" + log " Please place gameconsole-r36s.dtb in the parent directory" + exit 1 + fi +fi + +#------------------------------------------------------------------------------ +# Step 3: Apply kernel config +#------------------------------------------------------------------------------ +log "" +log "Step 3: Configuring kernel..." + +CONFIG_FILE="$ARCHR_KERNEL/configs/r36s_defconfig" +if [ ! -f "$CONFIG_FILE" ]; then + log " No custom config found, using defconfig from kernel..." + + cd "$KERNEL_SRC_DIR" + + # Try to use existing RK3326 config + if [ -f "arch/arm64/configs/rk3326_linux_defconfig" ]; then + make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE rk3326_linux_defconfig + elif [ -f "arch/arm64/configs/rockchip_linux_defconfig" ]; then + make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE rockchip_linux_defconfig + else + log " WARNING: No suitable defconfig found!" + make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE defconfig + fi +else + log " Using custom config: $CONFIG_FILE" + cp "$CONFIG_FILE" "$KERNEL_SRC_DIR/.config" +fi + +#------------------------------------------------------------------------------ +# Step 4: Build kernel +#------------------------------------------------------------------------------ +log "" +log "Step 4: Building kernel... (this may take a while)" + +cd "$KERNEL_SRC_DIR" + +# Disable warnings as errors if needed +sed -i 's/CONFIG_ERROR_ON_WARNING=y/CONFIG_ERROR_ON_WARNING=n/' .config 2>/dev/null || true + +# Build kernel image +log " Building Image..." +make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE Image $MAKEFLAGS 2>&1 | tee -a "$LOG_FILE" + +# Build DTBs +log " Building Device Trees..." +make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE dtbs $MAKEFLAGS 2>&1 | tee -a "$LOG_FILE" + +# Build modules +log " Building modules..." +make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE modules $MAKEFLAGS 2>&1 | tee -a "$LOG_FILE" + +#------------------------------------------------------------------------------ +# Step 5: Install to output directory +#------------------------------------------------------------------------------ +log "" +log "Step 5: Installing kernel artifacts..." + +mkdir -p "$ARCHR_OUTPUT/boot" +mkdir -p "$ARCHR_OUTPUT/modules" + +# Copy kernel image +cp arch/arm64/boot/Image "$ARCHR_OUTPUT/boot/" +log " Copied: Image" + +# Copy DTB +if [ -f "arch/arm64/boot/dts/rockchip/rk3326-r36s.dtb" ]; then + cp "arch/arm64/boot/dts/rockchip/rk3326-r36s.dtb" "$ARCHR_OUTPUT/boot/" + log " Copied: rk3326-r36s.dtb" +fi + +# Install modules +make ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE \ + INSTALL_MOD_PATH="$ARCHR_OUTPUT/modules" \ + modules_install 2>&1 | tee -a "$LOG_FILE" + +log " Modules installed to: $ARCHR_OUTPUT/modules" + +#------------------------------------------------------------------------------ +# Complete +#------------------------------------------------------------------------------ +log "" +log "=== Kernel Build Complete ===" +log "" +log "Artifacts:" +ls -la "$ARCHR_OUTPUT/boot/" diff --git a/build-rootfs.sh b/build-rootfs.sh new file mode 100644 index 0000000000..b2033cf82f --- /dev/null +++ b/build-rootfs.sh @@ -0,0 +1,224 @@ +#!/bin/bash + +#============================================================================== +# Arch R - Root Filesystem Build Script +#============================================================================== +# Creates an Arch Linux ARM root filesystem for R36S +#============================================================================== + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Load environment +if [ -f "$SCRIPT_DIR/env.sh" ]; then + source "$SCRIPT_DIR/env.sh" +else + echo "ERROR: env.sh not found!" + exit 1 +fi + +LOG_FILE="$ARCHR_OUTPUT/build-rootfs.log" +ROOTFS_DIR="$ARCHR_ROOTFS/staging" +ROOTFS_ARCHIVE="$ARCHR_OUTPUT/archr-rootfs.tar.gz" + +log() { + echo "[$(date '+%H:%M:%S')] $1" | tee -a "$LOG_FILE" +} + +log "=== Arch R Root Filesystem Build ===" + +#------------------------------------------------------------------------------ +# Check if running as root (required for chroot) +#------------------------------------------------------------------------------ +if [ "$EUID" -ne 0 ]; then + log "This script needs to run as root for chroot operations." + log "Please run: sudo $0" + exit 1 +fi + +#------------------------------------------------------------------------------ +# Step 1: Download Arch Linux ARM base +#------------------------------------------------------------------------------ +log "" +log "Step 1: Getting Arch Linux ARM base..." + +ALARM_ROOTFS="$ARCHR_ROOTFS/ArchLinuxARM-aarch64-latest.tar.gz" +ALARM_URL="http://os.archlinuxarm.org/os/ArchLinuxARM-aarch64-latest.tar.gz" + +if [ -f "$ALARM_ROOTFS" ]; then + log " Base archive exists: $ALARM_ROOTFS" +else + log " Downloading Arch Linux ARM..." + wget -O "$ALARM_ROOTFS" "$ALARM_URL" 2>&1 | tee -a "$LOG_FILE" +fi + +#------------------------------------------------------------------------------ +# Step 2: Extract rootfs +#------------------------------------------------------------------------------ +log "" +log "Step 2: Extracting rootfs..." + +# Clean staging directory +rm -rf "$ROOTFS_DIR" +mkdir -p "$ROOTFS_DIR" + +bsdtar -xpf "$ALARM_ROOTFS" -C "$ROOTFS_DIR" 2>&1 | tee -a "$LOG_FILE" +log " Extracted to: $ROOTFS_DIR" + +#------------------------------------------------------------------------------ +# Step 3: Setup for chroot +#------------------------------------------------------------------------------ +log "" +log "Step 3: Setting up for chroot..." + +# Copy QEMU static binary for ARM64 emulation +cp /usr/bin/qemu-aarch64-static "$ROOTFS_DIR/usr/bin/" + +# Mount required filesystems +mount -t proc /proc "$ROOTFS_DIR/proc" +mount -t sysfs /sys "$ROOTFS_DIR/sys" +mount -o bind /dev "$ROOTFS_DIR/dev" +mount -o bind /dev/pts "$ROOTFS_DIR/dev/pts" + +# Copy DNS resolution +cp /etc/resolv.conf "$ROOTFS_DIR/etc/resolv.conf" + +log " Chroot environment ready" + +#------------------------------------------------------------------------------ +# Step 4: Configure system in chroot +#------------------------------------------------------------------------------ +log "" +log "Step 4: Configuring system in chroot..." + +cat > "$ROOTFS_DIR/tmp/setup.sh" << 'CHROOT_SCRIPT' +#!/bin/bash + +set -e + +echo "=== Inside chroot ===" + +# Initialize pacman keyring +pacman-key --init +pacman-key --populate archlinuxarm + +# Update system +pacman -Syu --noconfirm + +# Install base packages +pacman -S --noconfirm --needed \ + base \ + linux-firmware \ + networkmanager \ + wpa_supplicant \ + sudo \ + vim \ + htop \ + mesa \ + sdl2 \ + alsa-utils \ + git \ + +# Install gaming packages +pacman -S --noconfirm --needed \ + retroarch \ + retroarch-assets-xmb \ + retroarch-assets-ozone \ + +# Install libretro cores (available in AUR or prebuilt) +# Note: Not all cores are in official repos +pacman -S --noconfirm --needed \ + libretro-mgba \ + libretro-snes9x \ + libretro-nestopia \ + libretro-genesis-plus-gx \ + || echo "Some cores may need to be built separately" + +# Create archr user +useradd -m -G wheel -s /bin/bash archr 2>/dev/null || true +echo "archr:archr" | chpasswd + +# Allow wheel group sudo +echo "%wheel ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/wheel + +# Set hostname +echo "archr" > /etc/hostname + +# Enable services +systemctl enable NetworkManager + +# Set timezone +ln -sf /usr/share/zoneinfo/America/Sao_Paulo /etc/localtime + +# Generate locales +echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen +echo "pt_BR.UTF-8 UTF-8" >> /etc/locale.gen +locale-gen + +# Cleanup +pacman -Scc --noconfirm + +echo "=== Chroot setup complete ===" +CHROOT_SCRIPT + +chmod +x "$ROOTFS_DIR/tmp/setup.sh" +chroot "$ROOTFS_DIR" /tmp/setup.sh 2>&1 | tee -a "$LOG_FILE" + +#------------------------------------------------------------------------------ +# Step 5: Apply overlay +#------------------------------------------------------------------------------ +log "" +log "Step 5: Applying overlay..." + +if [ -d "$ARCHR_ROOTFS/overlay" ]; then + cp -a "$ARCHR_ROOTFS/overlay/"* "$ROOTFS_DIR/" 2>/dev/null || true + log " Overlay applied" +fi + +#------------------------------------------------------------------------------ +# Step 6: Install kernel modules +#------------------------------------------------------------------------------ +log "" +log "Step 6: Installing kernel modules..." + +if [ -d "$ARCHR_OUTPUT/modules/lib/modules" ]; then + cp -a "$ARCHR_OUTPUT/modules/lib/modules/"* "$ROOTFS_DIR/lib/modules/" 2>/dev/null || true + log " Modules installed" +else + log " WARNING: No kernel modules found. Run build-kernel.sh first." +fi + +#------------------------------------------------------------------------------ +# Step 7: Cleanup and unmount +#------------------------------------------------------------------------------ +log "" +log "Step 7: Cleanup..." + +# Remove QEMU binary +rm -f "$ROOTFS_DIR/usr/bin/qemu-aarch64-static" +rm -f "$ROOTFS_DIR/tmp/setup.sh" + +# Unmount in reverse order +umount "$ROOTFS_DIR/dev/pts" +umount "$ROOTFS_DIR/dev" +umount "$ROOTFS_DIR/sys" +umount "$ROOTFS_DIR/proc" + +#------------------------------------------------------------------------------ +# Step 8: Create archive +#------------------------------------------------------------------------------ +log "" +log "Step 8: Creating rootfs archive..." + +cd "$ROOTFS_DIR" +tar -czf "$ROOTFS_ARCHIVE" . + +log " Created: $ROOTFS_ARCHIVE" +log " Size: $(du -h "$ROOTFS_ARCHIVE" | cut -f1)" + +#------------------------------------------------------------------------------ +# Complete +#------------------------------------------------------------------------------ +log "" +log "=== Root Filesystem Build Complete ===" diff --git a/config/retroarch.cfg b/config/retroarch.cfg new file mode 100644 index 0000000000..3ea7d55e7c --- /dev/null +++ b/config/retroarch.cfg @@ -0,0 +1,61 @@ +# Arch R - RetroArch Configuration for R36S +# Optimized for 640x480 display + +# Video Settings +video_driver = "gl" +video_fullscreen = "true" +video_windowed_fullscreen = "false" +video_vsync = "true" +video_smooth = "false" +video_scale_integer = "true" +video_rotation = "0" +video_aspect_ratio_auto = "true" + +# R36S has 640x480 display (rotated to 480x640 in some configs) +video_fullscreen_x = "640" +video_fullscreen_y = "480" + +# Audio Settings +audio_driver = "alsa" +audio_device = "default" +audio_latency = "64" +audio_sync = "true" + +# Input Settings +input_autodetect_enable = "true" +input_joypad_driver = "udev" +input_max_users = "1" + +# Menu Settings +menu_driver = "ozone" +menu_show_core_updater = "true" +menu_show_online_updater = "true" +quick_menu_show_save_core_overrides = "true" +quick_menu_show_save_game_overrides = "true" + +# Directories +savefile_directory = "~/.config/retroarch/saves" +savestate_directory = "~/.config/retroarch/states" +libretro_directory = "/usr/lib/libretro" +libretro_info_path = "/usr/share/libretro/info" +assets_directory = "/usr/share/retroarch/assets" +system_directory = "~/roms/bios" + +# Performance +video_threaded = "true" +video_frame_delay = "0" + +# Power Saving (important for handheld) +suspend_screensaver_enable = "false" +pause_nonactive = "true" + +# Hotkeys (adapt these for R36S button layout) +input_enable_hotkey = "nul" +input_menu_toggle_gamepad_combo = "4" +input_exit_emulator = "escape" +input_save_state = "f2" +input_load_state = "f4" +input_state_slot_increase = "f7" +input_state_slot_decrease = "f6" +input_toggle_fast_forward = "space" +input_fps_toggle = "f3" diff --git a/config/udev/99-archr-r36s.rules b/config/udev/99-archr-r36s.rules new file mode 100644 index 0000000000..e3fa845f93 --- /dev/null +++ b/config/udev/99-archr-r36s.rules @@ -0,0 +1,38 @@ +# Arch R - R36S udev Rules for USB OTG and Wi-Fi + +#--------------------------------------------------------------------------- +# AIC8800 Wi-Fi USB Modeswitch +# The adapter appears first as a CD-ROM/storage device (a69c:5721) +# and needs to be ejected to switch to Wi-Fi mode (a69c:8801) +#--------------------------------------------------------------------------- + +# Primary CD-ROM mode - trigger eject to switch to Wi-Fi +SUBSYSTEM=="block", ATTRS{idVendor}=="a69c", ATTRS{idProduct}=="5721", RUN+="/usr/bin/eject %k" +SUBSYSTEM=="usb", ATTR{idVendor}=="a69c", ATTR{idProduct}=="5721", RUN+="/usr/bin/eject /dev/%k" + +# Alternative VIDs that might appear +SUBSYSTEM=="block", ATTRS{idVendor}=="2604", ATTRS{idProduct}=="0012", RUN+="/usr/bin/eject %k" +SUBSYSTEM=="block", ATTRS{idVendor}=="2604", ATTRS{idProduct}=="0013", RUN+="/usr/bin/eject %k" + +#--------------------------------------------------------------------------- +# AIC8800 Wi-Fi Mode (after modeswitch) +# These are the IDs when the device is in Wi-Fi mode +#--------------------------------------------------------------------------- + +# Set permissions for Wi-Fi device +SUBSYSTEM=="usb", ATTR{idVendor}=="a69c", ATTR{idProduct}=="8801", MODE="0666" +SUBSYSTEM=="usb", ATTR{idVendor}=="2604", ATTR{idProduct}=="0013", MODE="0666" + +#--------------------------------------------------------------------------- +# R36S Controller/Joystick +#--------------------------------------------------------------------------- + +# ADC-based analog sticks +SUBSYSTEM=="input", ATTRS{name}=="adc-joystick", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# GPIO buttons (D-pad, face buttons) +SUBSYSTEM=="input", ATTRS{name}=="gpio-keys", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" + +# R36S specific controller names +SUBSYSTEM=="input", ATTRS{name}=="*OdroidGoa*", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" +SUBSYSTEM=="input", ATTRS{name}=="*R36S*", MODE="0666", ENV{ID_INPUT_JOYSTICK}="1" diff --git a/kernel/dts/gameconsole-r36s.dtb b/kernel/dts/gameconsole-r36s.dtb new file mode 100644 index 0000000000000000000000000000000000000000..d30641c91730eb156244f5f5a7e70621885f506f GIT binary patch literal 61649 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 RWNCpeep$E?WvN9a3;=*$OQrw- literal 0 HcmV?d00001 diff --git a/scripts/first-boot.sh b/scripts/first-boot.sh new file mode 100644 index 0000000000..fcc6e85568 --- /dev/null +++ b/scripts/first-boot.sh @@ -0,0 +1,101 @@ +#!/bin/bash + +#============================================================================== +# Arch R - First Boot Setup Script +#============================================================================== +# Runs on first boot to configure the system +#============================================================================== + +FIRST_BOOT_FLAG="/var/lib/archr/.first-boot-done" + +# Check if already ran +if [ -f "$FIRST_BOOT_FLAG" ]; then + exit 0 +fi + +echo "=== Arch R First Boot Setup ===" + +#------------------------------------------------------------------------------ +# Resize partition to fill SD card +#------------------------------------------------------------------------------ +echo "Resizing root partition..." + +ROOT_DEV="/dev/mmcblk0p2" +ROOT_DISK="/dev/mmcblk0" + +# Get current end and max available +PART_INFO=$(parted -m "$ROOT_DISK" unit s print 2>/dev/null | grep "^2:") +CURRENT_END=$(echo "$PART_INFO" | cut -d: -f3 | tr -d 's') + +DISK_SIZE=$(parted -m "$ROOT_DISK" unit s print 2>/dev/null | grep "^$ROOT_DISK" | cut -d: -f2 | tr -d 's') +MAX_END=$((DISK_SIZE - 34)) # Leave space for GPT backup + +if [ "$CURRENT_END" -lt "$MAX_END" ]; then + echo " Expanding partition..." + parted -s "$ROOT_DISK" resizepart 2 100% + resize2fs "$ROOT_DEV" + echo " Partition expanded!" +else + echo " Partition already at maximum size" +fi + +#------------------------------------------------------------------------------ +# Generate SSH host keys +#------------------------------------------------------------------------------ +echo "Generating SSH host keys..." +ssh-keygen -A 2>/dev/null || true + +#------------------------------------------------------------------------------ +# Set random machine-id +#------------------------------------------------------------------------------ +echo "Generating machine ID..." +rm -f /etc/machine-id +systemd-machine-id-setup + +#------------------------------------------------------------------------------ +# Enable services +#------------------------------------------------------------------------------ +echo "Enabling services..." +systemctl enable NetworkManager 2>/dev/null || true +systemctl enable bluetooth 2>/dev/null || true + +#------------------------------------------------------------------------------ +# Configure RetroArch +#------------------------------------------------------------------------------ +echo "Configuring RetroArch..." + +RA_CONFIG="/home/archr/.config/retroarch/retroarch.cfg" +mkdir -p "$(dirname "$RA_CONFIG")" + +if [ ! -f "$RA_CONFIG" ]; then + cp /etc/archr/retroarch.cfg "$RA_CONFIG" 2>/dev/null || true +fi + +chown -R archr:archr /home/archr/.config 2>/dev/null || true + +#------------------------------------------------------------------------------ +# Create ROM directories +#------------------------------------------------------------------------------ +echo "Creating ROM directories..." + +ROM_BASE="/home/archr/roms" +SYSTEMS=( + "gb" "gbc" "gba" "nes" "snes" "megadrive" "psx" + "n64" "psp" "dreamcast" "arcade" "mame" +) + +for sys in "${SYSTEMS[@]}"; do + mkdir -p "$ROM_BASE/$sys" +done + +chown -R archr:archr "$ROM_BASE" + +#------------------------------------------------------------------------------ +# Mark first boot complete +#------------------------------------------------------------------------------ +mkdir -p "$(dirname "$FIRST_BOOT_FLAG")" +touch "$FIRST_BOOT_FLAG" + +echo "=== First Boot Setup Complete ===" +echo "" +echo "System will continue booting..." diff --git a/scripts/wifi-connect.sh b/scripts/wifi-connect.sh new file mode 100644 index 0000000000..930255d8b4 --- /dev/null +++ b/scripts/wifi-connect.sh @@ -0,0 +1,102 @@ +#!/bin/bash + +#============================================================================== +# Arch R - Wi-Fi Connection Script +#============================================================================== + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${GREEN}=== Arch R Wi-Fi Setup ===${NC}" +echo "" + +#------------------------------------------------------------------------------ +# Check for Wi-Fi interface +#------------------------------------------------------------------------------ +echo "Checking for Wi-Fi interface..." + +IFACE="" +for iface in wlan0 wlan1 wlp1s0; do + if [ -d "/sys/class/net/$iface" ]; then + IFACE="$iface" + break + fi +done + +if [ -z "$IFACE" ]; then + echo -e "${RED}No Wi-Fi interface found!${NC}" + echo "" + echo "Troubleshooting:" + echo " 1. Make sure Wi-Fi adapter is connected" + echo " 2. Check if driver is loaded: lsmod | grep aic" + echo " 3. Check dmesg for errors: dmesg | grep -i wifi" + exit 1 +fi + +echo -e "${GREEN}Found interface: $IFACE${NC}" +echo "" + +#------------------------------------------------------------------------------ +# Check NetworkManager +#------------------------------------------------------------------------------ +if command -v nmcli &> /dev/null; then + # Use NetworkManager + echo "Scanning for networks..." + echo "" + + nmcli device wifi rescan 2>/dev/null + sleep 2 + + echo "Available networks:" + nmcli device wifi list + echo "" + + read -p "Enter network name (SSID): " SSID + read -sp "Enter password: " PASSWORD + echo "" + + echo "Connecting to $SSID..." + nmcli device wifi connect "$SSID" password "$PASSWORD" + + if [ $? -eq 0 ]; then + echo -e "${GREEN}Connected successfully!${NC}" + echo "" + echo "IP Address:" + ip -4 addr show "$IFACE" | grep inet + else + echo -e "${RED}Connection failed!${NC}" + exit 1 + fi + +else + # Fallback to wpa_supplicant + echo "NetworkManager not available, using wpa_supplicant..." + + read -p "Enter network name (SSID): " SSID + read -sp "Enter password: " PASSWORD + echo "" + + # Create wpa_supplicant config + WPA_CONF="/tmp/wpa_temp.conf" + wpa_passphrase "$SSID" "$PASSWORD" > "$WPA_CONF" + + # Stop any existing wpa_supplicant + killall wpa_supplicant 2>/dev/null + + # Start wpa_supplicant + wpa_supplicant -B -i "$IFACE" -c "$WPA_CONF" + sleep 2 + + # Get IP via DHCP + dhcpcd "$IFACE" + + echo -e "${GREEN}Connection attempted!${NC}" + echo "" + echo "IP Address:" + ip -4 addr show "$IFACE" | grep inet +fi diff --git a/setup-toolchain.sh b/setup-toolchain.sh new file mode 100644 index 0000000000..f337e1da71 --- /dev/null +++ b/setup-toolchain.sh @@ -0,0 +1,208 @@ +#!/bin/bash + +#============================================================================== +# Arch R - Toolchain Setup Script +#============================================================================== +# Sets up the cross-compilation environment for building Arch R +#============================================================================== + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +LOG_FILE="$SCRIPT_DIR/setup-toolchain.log" + +log() { + echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE" +} + +log "=== Arch R Toolchain Setup ===" +log "Script directory: $SCRIPT_DIR" + +# Check if running as root +if [ "$EUID" -eq 0 ]; then + log "Warning: Running as root. Some operations may require sudo anyway." +fi + +#------------------------------------------------------------------------------ +# Step 1: Install required packages +#------------------------------------------------------------------------------ +log "" +log "Step 1: Installing required packages..." + +PACKAGES=( + # Cross-compilation toolchain + gcc-aarch64-linux-gnu + g++-aarch64-linux-gnu + binutils-aarch64-linux-gnu + + # Build tools + make + cmake + ninja-build + bc + bison + flex + + # Device tree compiler + device-tree-compiler + + # U-Boot tools + u-boot-tools + + # For rootfs manipulation + binfmt-support + qemu-user-static + debootstrap + + # Archive tools + bsdtar + xz-utils + zstd + + # Misc + git + wget + curl + python3 + python3-pip + libssl-dev + libncurses5-dev + + # For image creation + parted + dosfstools + e2fsprogs + mtools +) + +log "Updating package list..." +sudo apt update 2>&1 | tee -a "$LOG_FILE" + +log "Installing packages..." +sudo apt install -y "${PACKAGES[@]}" 2>&1 | tee -a "$LOG_FILE" + +#------------------------------------------------------------------------------ +# Step 2: Create directory structure +#------------------------------------------------------------------------------ +log "" +log "Step 2: Creating directory structure..." + +DIRS=( + "$SCRIPT_DIR/bootloader/configs" + "$SCRIPT_DIR/bootloader/src" + "$SCRIPT_DIR/kernel/configs" + "$SCRIPT_DIR/kernel/dts" + "$SCRIPT_DIR/kernel/patches" + "$SCRIPT_DIR/kernel/src" + "$SCRIPT_DIR/rootfs/overlay/etc" + "$SCRIPT_DIR/rootfs/overlay/usr/local/bin" + "$SCRIPT_DIR/rootfs/staging" + "$SCRIPT_DIR/config/emulationstation" + "$SCRIPT_DIR/config/retroarch" + "$SCRIPT_DIR/config/udev" + "$SCRIPT_DIR/scripts" + "$SCRIPT_DIR/output" +) + +for dir in "${DIRS[@]}"; do + mkdir -p "$dir" + log " Created: $dir" +done + +#------------------------------------------------------------------------------ +# Step 3: Verify toolchain +#------------------------------------------------------------------------------ +log "" +log "Step 3: Verifying toolchain..." + +if command -v aarch64-linux-gnu-gcc &> /dev/null; then + GCC_VERSION=$(aarch64-linux-gnu-gcc --version | head -1) + log " GCC: $GCC_VERSION" +else + log "ERROR: aarch64-linux-gnu-gcc not found!" + exit 1 +fi + +if command -v dtc &> /dev/null; then + DTC_VERSION=$(dtc --version | head -1) + log " DTC: $DTC_VERSION" +else + log "ERROR: dtc not found!" + exit 1 +fi + +if command -v mkimage &> /dev/null; then + log " mkimage: Available" +else + log "WARNING: mkimage not found. U-Boot builds may fail." +fi + +#------------------------------------------------------------------------------ +# Step 4: Setup QEMU for ARM64 emulation +#------------------------------------------------------------------------------ +log "" +log "Step 4: Setting up QEMU for ARM64..." + +if command -v qemu-aarch64-static &> /dev/null; then + log " QEMU AArch64 static: Available" + + # Register binfmt if not already done + if [ -f /proc/sys/fs/binfmt_misc/qemu-aarch64 ]; then + log " binfmt: Already registered" + else + log " Registering binfmt..." + sudo systemctl restart binfmt-support 2>/dev/null || true + fi +else + log "WARNING: qemu-aarch64-static not found. Chroot operations will fail." +fi + +#------------------------------------------------------------------------------ +# Step 5: Create environment file +#------------------------------------------------------------------------------ +log "" +log "Step 5: Creating environment configuration..." + +cat > "$SCRIPT_DIR/env.sh" << 'EOF' +#!/bin/bash +# Arch R Build Environment Configuration + +export ARCH=arm64 +export CROSS_COMPILE=aarch64-linux-gnu- + +# Paths +export ARCHR_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +export ARCHR_BOOTLOADER="$ARCHR_ROOT/bootloader" +export ARCHR_KERNEL="$ARCHR_ROOT/kernel" +export ARCHR_ROOTFS="$ARCHR_ROOT/rootfs" +export ARCHR_CONFIG="$ARCHR_ROOT/config" +export ARCHR_OUTPUT="$ARCHR_ROOT/output" + +# Build options +export MAKEFLAGS="-j$(nproc)" + +# Device-specific +export ARCHR_DEVICE="r36s" +export ARCHR_SOC="rk3326" + +echo "Arch R build environment loaded." +echo " ARCH: $ARCH" +echo " CROSS_COMPILE: $CROSS_COMPILE" +echo " Device: $ARCHR_DEVICE" +EOF + +log " Created: $SCRIPT_DIR/env.sh" + +#------------------------------------------------------------------------------ +# Complete +#------------------------------------------------------------------------------ +log "" +log "=== Setup Complete! ===" +log "" +log "To start building, source the environment:" +log " source env.sh" +log "" +log "Then run the build scripts:" +log " ./build-kernel.sh" +log " ./build-rootfs.sh" +log " ./build-image.sh"