commit d0a216d22d6382dadc96fdf1c879148e9b358de5 Author: Matteo Benedetto Date: Sun May 11 18:22:51 2025 +0200 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..114e3d9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# DOSBox-X Windows Manager .gitignore + +# Disk images +*.img +*.vhd +*.vdi +*.vmdk +disks/ + +# ISO files +*.iso +iso/ + +# Snapshots +snapshots/ + +# Generated/temporary config files +temp_dosbox.conf +temp_dosbox_win95.conf +temp_config_tune.conf + +# Backup files +*.bak +*~ +*.old +*.backup + +# Log files +*.log +*.log.* + +# Windows system files +win98_drive/ +win95_drive/ + +# Editor specific files +.vscode/ +.idea/ +*.swp +*.swo +.DS_Store + +# Zenity temporary files +.zenity_* diff --git a/README.md b/README.md new file mode 100644 index 0000000..cdf5e10 --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ +# DOSBox-X Windows 9x Manager + +A graphical launcher tool for running Windows 95/98 in DOSBox-X with advanced management features. + +![DOSBox-X Windows Manager](https://example.com/screenshot.png) + +## Overview + +DOSBox-X Windows Manager provides a user-friendly GUI for running Windows 95 and 98 in DOSBox-X. It handles disk image creation, ISO mounting, snapshots, and performance tuning to make retro Windows usage seamless and accessible. + +## Features + +- **Easy Installation**: Boot directly from installation ISO files +- **HDD Image Management**: Create and format hard disk images with customizable sizes +- **Snapshot System**: Save and restore system states with named snapshots +- **CD-ROM Support**: Mount ISO files to install software or games +- **Performance Tuning**: Optimize DOSBox-X settings for Windows 95 (in win95_launcher) +- **User-friendly Interface**: Simple GUI powered by Zenity + +## Requirements + +- DOSBox-X (https://dosbox-x.com/) +- Zenity for GUI dialogs +- Bash shell +- Windows 95/98 installation media (ISO format) + +## Installation + +1. Clone this repository: + ``` + git clone https://github.com/yourusername/dosbox-x-windows-manager.git + cd dosbox-x-windows-manager + ``` + +2. Make the launcher scripts executable: + ``` + chmod +x win98_launcher.sh win95_launcher.sh + ``` + +3. Run the appropriate launcher: + ``` + # For Windows 98: + ./win98_launcher.sh + + # For Windows 95: + ./win95_launcher.sh + ``` + +## Directory Structure + +- `win98_launcher.sh` - Windows 98 launcher script +- `win95_launcher.sh` - Windows 95 launcher script +- `dosbox.conf` - DOSBox-X configuration file +- `win98_drive/` - Directory for Windows 98 files (optional) +- `win95_drive/` - Directory for Windows 95 files (optional) +- `iso/` - Directory for ISO files +- `disks/` - Directory for disk images +- `snapshots/` - Directory for Windows 98 snapshots +- `snapshots_win95/` - Directory for Windows 95 snapshots + +## Usage Guide + +### First-time Setup + +1. Run the launcher for your Windows version +2. Select "Boot from Windows 9x ISO" option +3. Choose your Windows installation ISO +4. Follow the Windows setup process + +### Creating Snapshots + +1. Make changes to your Windows system +2. Exit to the launcher +3. Select "Create snapshot of current disk image" +4. Enter a name for your snapshot + +### Restoring Snapshots + +1. Select "Restore snapshot" from the launcher +2. Choose the snapshot you wish to restore +3. Confirm the restoration + +## Performance Tuning (Windows 95) + +The Windows 95 launcher includes performance tuning options: + +- **Standard**: Balanced settings for most users +- **Fast**: Better performance but less accuracy +- **Accurate**: Slower but more accurate emulation + +## Troubleshooting + +- **Windows fails to install**: Ensure your disk image is large enough +- **Installation errors**: Try the "Format C: drive" option to create a fresh disk image +- **Performance issues**: Use the tuning options in the Windows 95 launcher + +## License + +This project is licensed under the MIT License - see the LICENSE file for details. + +## Credits + +- DOSBox-X team for the amazing emulator +- Contributors to this project + +--- + +Created with ❤️ for DOS/Windows nostalgia enthusiasts diff --git a/win95_launcher.sh b/win95_launcher.sh new file mode 100644 index 0000000..383d8a3 --- /dev/null +++ b/win95_launcher.sh @@ -0,0 +1,383 @@ +#!/bin/bash + +# Win95 DOSBox-X Launcher +# A GUI tool to launch Windows 95 in DOSBox-X with different scenarios + +# Check if zenity is installed +if ! command -v zenity &> /dev/null; then + echo "Zenity is not installed. Please install it using:" + echo "sudo apt-get install zenity" + exit 1 +fi + +# Base directory +BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +DOSBOX_CONF="$BASE_DIR/dosbox.conf" +WIN95_DRIVE="$BASE_DIR/win95_drive" +ISO_DIR="$BASE_DIR/iso" +IMG_DIR="$BASE_DIR/disks" +HDD_IMAGE="$IMG_DIR/win95.img" +SNAPSHOT_DIR="$BASE_DIR/snapshots_win95" +DEFAULT_HDD_SIZE=1000 # Default size in MB for HDD image (smaller for Win95) +MIN_HDD_SIZE=300 # Minimum size in MB (Win95 needs less space) +MAX_HDD_SIZE=2000 # Maximum size in MB + +# Make sure directories exist +mkdir -p "$WIN95_DRIVE" "$ISO_DIR" "$IMG_DIR" "$SNAPSHOT_DIR" + +# Function to create HDD image if it doesn't exist +create_hdd_image() { + if [ ! -f "$HDD_IMAGE" ]; then + # Let user choose the size with slider + HDD_SIZE=$(zenity --scale --title="Select HDD Size" \ + --text="Choose the size of your Windows 95 hard disk (MB):" \ + --min-value=$MIN_HDD_SIZE --max-value=$MAX_HDD_SIZE --value=$DEFAULT_HDD_SIZE \ + --step=100) + + # Check if user cancelled the dialog + if [ $? -ne 0 ]; then + return 1 + fi + + # If no size was selected, use default + if [ -z "$HDD_SIZE" ]; then + HDD_SIZE=$DEFAULT_HDD_SIZE + fi + + zenity --question --text="Create new disk image of ${HDD_SIZE}MB?" --title="Confirm HDD Creation" --ok-label="Yes" --cancel-label="No" + if [ $? -ne 0 ]; then + return 1 + fi + + # Show progress dialog while creating the image + ( + echo "# Creating disk image of ${HDD_SIZE}MB..." + # Create disk image using DOSBox-X's imgmake command + dosbox-x -c "imgmake \"$HDD_IMAGE\" -size ${HDD_SIZE} -fat 16 -t hd" > /dev/null 2>&1 + if [ $? -ne 0 ]; then + zenity --error --text="Failed to create HDD image. Please check your permissions." + return 1 + fi + + echo "100" + echo "# Disk image created successfully!" + ) | zenity --progress --title="Creating HDD Image" --text="Creating disk image..." --percentage=0 --auto-close --no-cancel + + return 0 + fi + return 0 +} + +# Function to create temporary config file based on scenario +create_temp_config() { + local autoexec_content="$1" + local temp_conf="$BASE_DIR/temp_dosbox_win95.conf" + + # Copy the original config file + cp "$DOSBOX_CONF" "$temp_conf" + + # Replace the [autoexec] section + sed -i '/\[autoexec\]/,$ d' "$temp_conf" + echo "[autoexec]" >> "$temp_conf" + echo "$autoexec_content" >> "$temp_conf" + + echo "$temp_conf" +} + +# Function to start Windows 95 if installed +start_win95() { + # Check if HDD image exists + if [ ! -f "$HDD_IMAGE" ]; then + zenity --error --text="HDD image not found. Please create one first." + return + fi + + local autoexec=$(cat << EOF +# Mount the Windows 95 HDD image as drive C +imgmount c "$HDD_IMAGE" -t hdd -fs fat +c: +# Start Windows 95 +win +EOF +) + local temp_conf=$(create_temp_config "$autoexec") + dosbox-x -conf "$temp_conf" + rm "$temp_conf" +} + +# Function to browse and mount an ISO +mount_iso() { + # Check if HDD image exists + if [ ! -f "$HDD_IMAGE" ]; then + if ! create_hdd_image; then + return + fi + fi + + local iso_path=$(zenity --file-selection --title="Select ISO file" --file-filter="ISO files (*.iso) | *.iso" --filename="$ISO_DIR/") + + if [ -z "$iso_path" ]; then + zenity --error --text="No ISO file selected." + return + fi + + local autoexec=$(cat << EOF +# Mount the Windows 95 HDD image as drive C +imgmount c "$HDD_IMAGE" -t hdd -fs fat + +# Mount the ISO as drive D +imgmount d "$iso_path" -t iso + +c: +EOF +) + local temp_conf=$(create_temp_config "$autoexec") + dosbox-x -conf "$temp_conf" + rm "$temp_conf" +} + +# Function to boot from ISO +boot_iso() { + # Check if we should create a new HDD image + if [ ! -f "$HDD_IMAGE" ]; then + if ! create_hdd_image; then + return + fi + fi + + local iso_path=$(zenity --file-selection --title="Select Windows 95 Installation ISO" --file-filter="ISO files (*.iso) | *.iso" --filename="$ISO_DIR/") + + if [ -z "$iso_path" ]; then + zenity --error --text="No ISO file selected." + return + fi + + local autoexec=$(cat << EOF +# Mount the Windows 95 HDD image as drive C +imgmount c "$HDD_IMAGE" -t hdd -fs fat + +# Mount the ISO as drive D +imgmount d "$iso_path" -t iso +# Run the setup program +d: +# Start the Windows 95 setup (might be different paths for different Win95 CDs) +if exist setup.exe setup.exe +if exist win95\setup.exe cd win95 && setup.exe +EOF +) + local temp_conf=$(create_temp_config "$autoexec") + dosbox-x -conf "$temp_conf" + rm "$temp_conf" +} + +# Function to format C drive (the disk image) +format_c() { + # Check if HDD image exists + if [ ! -f "$HDD_IMAGE" ]; then + if ! create_hdd_image; then + return + fi + zenity --info --text="New disk image created. It's already blank and ready to use." + return + fi + + local confirm=$(zenity --question --text="This will delete the existing disk image and create a new blank one.\nAll data will be lost.\nDo you want to continue?" --title="Confirm Format" --ok-label="Yes" --cancel-label="No") + + if [ $? -ne 0 ]; then + return + fi + + # Remove existing image + rm -f "$HDD_IMAGE" + + # Create new image with user-selected size + create_hdd_image + + if [ $? -eq 0 ]; then + zenity --info --text="Format completed. A new blank disk image has been created." + fi +} + +# Function to create a snapshot of the current disk image +create_snapshot() { + # Check if HDD image exists + if [ ! -f "$HDD_IMAGE" ]; then + zenity --error --text="HDD image not found. Cannot create snapshot." + return 1 + fi + + # Get snapshot name from user + local snapshot_name=$(zenity --entry --title="Create Snapshot" \ + --text="Enter a name for this snapshot:" \ + --entry-text="Windows95_Snapshot") + + # Check if user cancelled + if [ $? -ne 0 ] || [ -z "$snapshot_name" ]; then + return 1 + fi + + # Create a valid filename (replace spaces and special chars) + snapshot_name=$(echo "$snapshot_name" | tr ' ' '_' | tr -cd '[:alnum:]_-') + + # Add timestamp to snapshot name to make it unique + local timestamp=$(date "+%Y%m%d_%H%M%S") + local snapshot_file="$SNAPSHOT_DIR/${timestamp}_${snapshot_name}.img" + + # Show progress while copying the image + ( + echo "# Creating snapshot: $snapshot_name..." + cp "$HDD_IMAGE" "$snapshot_file" + if [ $? -ne 0 ]; then + zenity --error --text="Failed to create snapshot. Check disk space and permissions." + return 1 + fi + echo "100" + echo "# Snapshot created successfully!" + ) | zenity --progress --title="Creating Snapshot" --text="Creating snapshot..." --percentage=0 --auto-close --no-cancel + + zenity --info --title="Snapshot Created" --text="Snapshot '$snapshot_name' created successfully.\nLocation: $snapshot_file" + return 0 +} + +# Function to restore a snapshot +restore_snapshot() { + # Check if snapshots directory exists and has at least one snapshot + if [ ! -d "$SNAPSHOT_DIR" ] || [ -z "$(ls -A "$SNAPSHOT_DIR")" ]; then + zenity --error --text="No snapshots found." + return 1 + fi + + # Create a list of available snapshots + local snapshots=() + for snap in "$SNAPSHOT_DIR"/*.img; do + local snap_name=$(basename "$snap") + snapshots+=("$snap" "$snap_name") + done + + # Let user select a snapshot + local selected_snapshot=$(zenity --list --title="Restore Snapshot" \ + --text="Select a snapshot to restore:" \ + --column="Path" --column="Snapshot Name" \ + "${snapshots[@]}" \ + --hide-column=1 --width=500 --height=300) + + # Check if user cancelled + if [ $? -ne 0 ] || [ -z "$selected_snapshot" ]; then + return 1 + fi + + # Confirm before restoring + zenity --question --title="Confirm Restore" \ + --text="This will replace your current disk image with the selected snapshot.\nAll unsaved changes will be lost.\n\nContinue?" \ + --ok-label="Restore" --cancel-label="Cancel" + + if [ $? -ne 0 ]; then + return 1 + fi + + # Show progress while restoring the snapshot + ( + echo "# Restoring snapshot..." + # Create backup of current image first + if [ -f "$HDD_IMAGE" ]; then + mv "$HDD_IMAGE" "${HDD_IMAGE}.bak" + fi + + # Copy the snapshot to the disk image location + cp "$selected_snapshot" "$HDD_IMAGE" + if [ $? -ne 0 ]; then + zenity --error --text="Failed to restore snapshot. Check permissions." + # Try to restore the backup + if [ -f "${HDD_IMAGE}.bak" ]; then + mv "${HDD_IMAGE}.bak" "$HDD_IMAGE" + fi + return 1 + fi + + # Remove backup if restore was successful + rm -f "${HDD_IMAGE}.bak" + + echo "100" + echo "# Snapshot restored successfully!" + ) | zenity --progress --title="Restoring Snapshot" --text="Restoring snapshot..." --percentage=0 --auto-close --no-cancel + + zenity --info --title="Snapshot Restored" --text="Snapshot restored successfully." + return 0 +} + +# Function to tune DOSBox-X settings for optimal Windows 95 performance +tune_settings() { + local choice=$(zenity --list --title="Tune Windows 95 Settings" \ + --text="Select a performance profile:" \ + --column="Profile" --column="Description" \ + 1 "Standard (Balanced settings)" \ + 2 "Fast (Better performance but less accurate)" \ + 3 "Accurate (Slower but more accurate emulation)" \ + --width=500 --height=200) + + if [ -z "$choice" ]; then + return + fi + + local temp_conf="$BASE_DIR/temp_config_tune.conf" + cp "$DOSBOX_CONF" "$temp_conf" + + case "$choice" in + 1) # Standard profile + sed -i 's/^cycles=.*/cycles=max 80% limit 15000/' "$temp_conf" + sed -i 's/^core=.*/core=normal/' "$temp_conf" + ;; + 2) # Fast profile + sed -i 's/^cycles=.*/cycles=max 100% limit 30000/' "$temp_conf" + sed -i 's/^core=.*/core=dynamic/' "$temp_conf" + ;; + 3) # Accurate profile + sed -i 's/^cycles=.*/cycles=max 70% limit 10000/' "$temp_conf" + sed -i 's/^core=.*/core=normal/' "$temp_conf" + ;; + esac + + # Ask if user wants to make the changes permanent + zenity --question --title="Save Changes" \ + --text="Would you like to make these settings permanent?\nIf you select 'No', the changes will only apply to the next session." \ + --ok-label="Yes" --cancel-label="No" + + if [ $? -eq 0 ]; then + cp "$temp_conf" "$DOSBOX_CONF" + zenity --info --title="Settings Saved" --text="Performance settings have been saved." + else + zenity --info --title="Temporary Settings" --text="Settings will be applied for the next session only." + fi +} + +# Main menu function +main_menu() { + while true; do + local choice=$(zenity --list --title="Windows 95 DOSBox-X Launcher" \ + --text="Select an option:" \ + --column="Option" --column="Description" \ + 1 "Start Windows 95 (if installed)" \ + 2 "Mount ISO and start Windows 95" \ + 3 "Boot from Windows 95 ISO (for installation)" \ + 4 "Format C: drive" \ + 5 "Create snapshot of current disk image" \ + 6 "Restore snapshot" \ + 7 "Tune performance settings" \ + 8 "Exit" \ + --width=500 --height=380) + + case "$choice" in + 1) start_win95 ;; + 2) mount_iso ;; + 3) boot_iso ;; + 4) format_c ;; + 5) create_snapshot ;; + 6) restore_snapshot ;; + 7) tune_settings ;; + 8|"") exit 0 ;; + esac + done +} + +# Start the main menu +main_menu diff --git a/win98_launcher.sh b/win98_launcher.sh new file mode 100755 index 0000000..6674b75 --- /dev/null +++ b/win98_launcher.sh @@ -0,0 +1,335 @@ +#!/bin/bash + +# Win98 DOSBox-X Launcher +# A GUI tool to launch Windows 98 in DOSBox-X with different scenarios + +# Check if zenity is installed +if ! command -v zenity &> /dev/null; then + echo "Zenity is not installed. Please install it using:" + echo "sudo apt-get install zenity" + exit 1 +fi + +# Base directory +BASE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +DOSBOX_CONF="$BASE_DIR/dosbox.conf" +WIN98_DRIVE="$BASE_DIR/win98_drive" +ISO_DIR="$BASE_DIR/iso" +IMG_DIR="$BASE_DIR/disks" +HDD_IMAGE="$IMG_DIR/win98.img" +SNAPSHOT_DIR="$BASE_DIR/snapshots" +DEFAULT_HDD_SIZE=2000 # Default size in MB for HDD image +MIN_HDD_SIZE=500 # Minimum size in MB +MAX_HDD_SIZE=4000 # Maximum size in MB + +# Make sure directories exist +mkdir -p "$WIN98_DRIVE" "$ISO_DIR" "$IMG_DIR" "$SNAPSHOT_DIR" + +# Function to create HDD image if it doesn't exist +create_hdd_image() { + if [ ! -f "$HDD_IMAGE" ]; then + # Let user choose the size with slider + HDD_SIZE=$(zenity --scale --title="Select HDD Size" \ + --text="Choose the size of your Windows 98 hard disk (MB):" \ + --min-value=$MIN_HDD_SIZE --max-value=$MAX_HDD_SIZE --value=$DEFAULT_HDD_SIZE \ + --step=100) + + # Check if user cancelled the dialog + if [ $? -ne 0 ]; then + return 1 + fi + + # If no size was selected, use default + if [ -z "$HDD_SIZE" ]; then + HDD_SIZE=$DEFAULT_HDD_SIZE + fi + + zenity --question --text="Create new disk image of ${HDD_SIZE}MB?" --title="Confirm HDD Creation" --ok-label="Yes" --cancel-label="No" + if [ $? -ne 0 ]; then + return 1 + fi + + # Show progress dialog while creating the image + ( + echo "# Creating disk image of ${HDD_SIZE}MB..." + # Create disk image using DOSBox-X's imgmake command + dosbox-x -c "imgmake \"$HDD_IMAGE\" -size ${HDD_SIZE} -fat 32 -t hd" -c "exit" > /dev/null 2>&1 + if [ $? -ne 0 ]; then + zenity --error --text="Failed to create HDD image. Please check your permissions." + return 1 + fi + + echo "100" + echo "# Disk image created successfully!" + ) | zenity --progress --title="Creating HDD Image" --text="Creating disk image..." --percentage=0 --auto-close --no-cancel + + return 0 + fi + return 0 +} + +# Function to create temporary config file based on scenario +create_temp_config() { + local autoexec_content="$1" + local temp_conf="$BASE_DIR/temp_dosbox.conf" + + # Copy the original config file + cp "$DOSBOX_CONF" "$temp_conf" + + # Replace the [autoexec] section + sed -i '/\[autoexec\]/,$ d' "$temp_conf" + echo "[autoexec]" >> "$temp_conf" + echo "$autoexec_content" >> "$temp_conf" + + echo "$temp_conf" +} + +# Function to start Windows 98 if installed +start_win98() { + # Check if HDD image exists + if [ ! -f "$HDD_IMAGE" ]; then + zenity --error --text="HDD image not found. Please create one first." + return + fi + + local autoexec=$(cat << EOF +# Mount the Windows 98 HDD image as drive C +imgmount c "$HDD_IMAGE" -t hdd -fs fatù +# Mount the Windows 98 drive as E +mount e win98_drive +boot c: +EOF +) + local temp_conf=$(create_temp_config "$autoexec") + dosbox-x -conf "$temp_conf" + rm "$temp_conf" +} + +# Function to browse and mount an ISO +mount_iso() { + # Check if HDD image exists + if [ ! -f "$HDD_IMAGE" ]; then + if ! create_hdd_image; then + return + fi + fi + + local iso_path=$(zenity --file-selection --title="Select ISO file" --file-filter="ISO files (*.iso) | *.iso" --filename="$ISO_DIR/") + + if [ -z "$iso_path" ]; then + zenity --error --text="No ISO file selected." + return + fi + + local autoexec=$(cat << EOF +# Mount the Windows 98 HDD image as drive C +imgmount c "$HDD_IMAGE" -t hdd -fs fat + +# Mount the ISO as drive D +imgmount d "$iso_path" -t iso +mount e win98_drive +boot c: +EOF +) + local temp_conf=$(create_temp_config "$autoexec") + dosbox-x -conf "$temp_conf" + rm "$temp_conf" +} + +# Function to boot from ISO +boot_iso() { + # Check if we should create a new HDD image + if [ ! -f "$HDD_IMAGE" ]; then + if ! create_hdd_image; then + return + fi + fi + + local iso_path=$(zenity --file-selection --title="Select Windows 98 Installation ISO" --file-filter="ISO files (*.iso) | *.iso" --filename="$ISO_DIR/") + + if [ -z "$iso_path" ]; then + zenity --error --text="No ISO file selected." + return + fi + + local autoexec=$(cat << EOF +# Mount the Windows 98 HDD image as drive C +imgmount c "$HDD_IMAGE" -t hdd -fs fat + +# Mount the ISO as drive D +imgmount d "$iso_path" -t iso +# Run the setup program +d: +# Start the Windows 98 setup +setup.exe +EOF +) + local temp_conf=$(create_temp_config "$autoexec") + dosbox-x -conf "$temp_conf" + rm "$temp_conf" +} + +# Function to format C drive (the disk image) +format_c() { + # Check if HDD image exists + if [ ! -f "$HDD_IMAGE" ]; then + if ! create_hdd_image; then + return + fi + zenity --info --text="New disk image created. It's already blank and ready to use." + return + fi + + local confirm=$(zenity --question --text="This will delete the existing disk image and create a new blank one.\nAll data will be lost.\nDo you want to continue?" --title="Confirm Format" --ok-label="Yes" --cancel-label="No") + + if [ $? -ne 0 ]; then + return + fi + + # Remove existing image + rm -f "$HDD_IMAGE" + + # Create new image with user-selected size + create_hdd_image + + if [ $? -eq 0 ]; then + zenity --info --text="Format completed. A new blank disk image has been created." + fi +} + +# Function to create a snapshot of the current disk image +create_snapshot() { + # Check if HDD image exists + if [ ! -f "$HDD_IMAGE" ]; then + zenity --error --text="HDD image not found. Cannot create snapshot." + return 1 + fi + + # Get snapshot name from user + local snapshot_name=$(zenity --entry --title="Create Snapshot" \ + --text="Enter a name for this snapshot:" \ + --entry-text="Windows98_Snapshot") + + # Check if user cancelled + if [ $? -ne 0 ] || [ -z "$snapshot_name" ]; then + return 1 + fi + + # Create a valid filename (replace spaces and special chars) + snapshot_name=$(echo "$snapshot_name" | tr ' ' '_' | tr -cd '[:alnum:]_-') + + # Add timestamp to snapshot name to make it unique + local timestamp=$(date "+%Y%m%d_%H%M%S") + local snapshot_file="$SNAPSHOT_DIR/${timestamp}_${snapshot_name}.img" + + # Show progress while copying the image + ( + echo "# Creating snapshot: $snapshot_name..." + cp "$HDD_IMAGE" "$snapshot_file" + if [ $? -ne 0 ]; then + zenity --error --text="Failed to create snapshot. Check disk space and permissions." + return 1 + fi + echo "100" + echo "# Snapshot created successfully!" + ) | zenity --progress --title="Creating Snapshot" --text="Creating snapshot..." --percentage=0 --auto-close --no-cancel + + zenity --info --title="Snapshot Created" --text="Snapshot '$snapshot_name' created successfully.\nLocation: $snapshot_file" + return 0 +} + +# Function to restore a snapshot +restore_snapshot() { + # Check if snapshots directory exists and has at least one snapshot + if [ ! -d "$SNAPSHOT_DIR" ] || [ -z "$(ls -A "$SNAPSHOT_DIR")" ]; then + zenity --error --text="No snapshots found." + return 1 + fi + + # Create a list of available snapshots + local snapshots=() + for snap in "$SNAPSHOT_DIR"/*.img; do + local snap_name=$(basename "$snap") + snapshots+=("$snap" "$snap_name") + done + + # Let user select a snapshot + local selected_snapshot=$(zenity --list --title="Restore Snapshot" \ + --text="Select a snapshot to restore:" \ + --column="Path" --column="Snapshot Name" \ + "${snapshots[@]}" \ + --hide-column=1 --width=500 --height=300) + + # Check if user cancelled + if [ $? -ne 0 ] || [ -z "$selected_snapshot" ]; then + return 1 + fi + + # Confirm before restoring + zenity --question --title="Confirm Restore" \ + --text="This will replace your current disk image with the selected snapshot.\nAll unsaved changes will be lost.\n\nContinue?" \ + --ok-label="Restore" --cancel-label="Cancel" + + if [ $? -ne 0 ]; then + return 1 + fi + + # Show progress while restoring the snapshot + ( + echo "# Restoring snapshot..." + # Create backup of current image first + if [ -f "$HDD_IMAGE" ]; then + mv "$HDD_IMAGE" "${HDD_IMAGE}.bak" + fi + + # Copy the snapshot to the disk image location + cp "$selected_snapshot" "$HDD_IMAGE" + if [ $? -ne 0 ]; then + zenity --error --text="Failed to restore snapshot. Check permissions." + # Try to restore the backup + if [ -f "${HDD_IMAGE}.bak" ]; then + mv "${HDD_IMAGE}.bak" "$HDD_IMAGE" + fi + return 1 + fi + + # Remove backup if restore was successful + rm -f "${HDD_IMAGE}.bak" + + echo "100" + echo "# Snapshot restored successfully!" + ) | zenity --progress --title="Restoring Snapshot" --text="Restoring snapshot..." --percentage=0 --auto-close --no-cancel + + zenity --info --title="Snapshot Restored" --text="Snapshot restored successfully." + return 0 +} + +# Main menu function +main_menu() { + while true; do + local choice=$(zenity --list --title="Windows 98 DOSBox-X Launcher" \ + --text="Select an option:" \ + --column="Option" --column="Description" \ + 1 "Start Windows 98 (if installed)" \ + 2 "Mount ISO and start Windows 98" \ + 3 "Boot from Windows 98 ISO (for installation)" \ + 4 "Format C: drive" \ + 5 "Create snapshot of current disk image" \ + 6 "Restore snapshot" \ + 7 "Exit" \ + --width=500 --height=350) + + case "$choice" in + 1) start_win98 ;; + 2) mount_iso ;; + 3) boot_iso ;; + 4) format_c ;; + 5) create_snapshot ;; + 6) restore_snapshot ;; + 7|"") exit 0 ;; + esac + done +} + +# Start the main menu +main_menu diff --git a/zfast_crt.glsl b/zfast_crt.glsl new file mode 100644 index 0000000..47931ab --- /dev/null +++ b/zfast_crt.glsl @@ -0,0 +1,199 @@ +/* + zfast_crt_standard - A simple, fast CRT shader. + + Copyright (C) 2017 Greg Hogan (SoltanGris42) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + +Notes: This shader does scaling with a weighted linear filter for adjustable + sharpness on the x and y axes based on the algorithm by Inigo Quilez here: + http://http://www.iquilezles.org/www/articles/texture/texture.htm + but modified to be somewhat sharper. Then a scanline effect that varies + based on pixel brighness is applied along with a monochrome aperture mask. + This shader runs at 60fps on the Raspberry Pi 3 hardware at 2mpix/s + resolutions (1920x1080 or 1600x1200). +*/ + +//For testing compilation +//#define FRAGMENT +//#define VERTEX + +//This can't be an option without slowing the shader down +//Comment this out for a coarser 3 pixel mask...which is currently broken +//on SNES Classic Edition due to Mali 400 gpu precision +#define FINEMASK +//Some drivers don't return black with texture coordinates out of bounds +//SNES Classic is too slow to black these areas out when using fullscreen +//overlays. But you can uncomment the below to black them out if necessary +//#define BLACK_OUT_BORDER + +// Parameter lines go here: +#pragma parameter BLURSCALEX "Blur Amount X-Axis" 0.30 0.0 1.0 0.05 +#pragma parameter LOWLUMSCAN "Scanline Darkness - Low" 6.0 0.0 10.0 0.5 +#pragma parameter HILUMSCAN "Scanline Darkness - High" 8.0 0.0 50.0 1.0 +#pragma parameter BRIGHTBOOST "Dark Pixel Brightness Boost" 1.25 0.5 1.5 0.05 +#pragma parameter MASK_DARK "Mask Effect Amount" 0.25 0.0 1.0 0.05 +#pragma parameter MASK_FADE "Mask/Scanline Fade" 0.8 0.0 1.0 0.05 + +#if defined(VERTEX) + +#if __VERSION__ >= 130 +#define COMPAT_VARYING out +#define COMPAT_ATTRIBUTE in +#define COMPAT_TEXTURE texture +#else +#define COMPAT_VARYING varying +#define COMPAT_ATTRIBUTE attribute +#define COMPAT_TEXTURE texture2D +#endif + +#ifdef GL_ES +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif + +COMPAT_ATTRIBUTE vec4 VertexCoord; +COMPAT_ATTRIBUTE vec4 COLOR; +COMPAT_ATTRIBUTE vec4 TexCoord; +COMPAT_VARYING vec4 COL0; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING float maskFade; +COMPAT_VARYING vec2 invDims; + +vec4 _oPosition1; +uniform mat4 MVPMatrix; +uniform COMPAT_PRECISION int FrameDirection; +uniform COMPAT_PRECISION int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; + +// compatibility #defines +#define vTexCoord TEX0.xy +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define OutSize vec4(OutputSize, 1.0 / OutputSize) + +#ifdef PARAMETER_UNIFORM +// All parameter floats need to have COMPAT_PRECISION in front of them +uniform COMPAT_PRECISION float BLURSCALEX; +//uniform COMPAT_PRECISION float BLURSCALEY; +uniform COMPAT_PRECISION float LOWLUMSCAN; +uniform COMPAT_PRECISION float HILUMSCAN; +uniform COMPAT_PRECISION float BRIGHTBOOST; +uniform COMPAT_PRECISION float MASK_DARK; +uniform COMPAT_PRECISION float MASK_FADE; +#else +#define BLURSCALEX 0.45 +//#define BLURSCALEY 0.20 +#define LOWLUMSCAN 5.0 +#define HILUMSCAN 10.0 +#define BRIGHTBOOST 1.25 +#define MASK_DARK 0.25 +#define MASK_FADE 0.8 +#endif + +void main() +{ + gl_Position = MVPMatrix * VertexCoord; + + TEX0.xy = TexCoord.xy*1.0001; + maskFade = 0.3333*MASK_FADE; + invDims = 1.0/TextureSize.xy; +} + +#elif defined(FRAGMENT) + +#ifdef GL_ES +#ifdef GL_FRAGMENT_PRECISION_HIGH +precision highp float; +#else +precision mediump float; +#endif +#define COMPAT_PRECISION mediump +#else +#define COMPAT_PRECISION +#endif + +#if __VERSION__ >= 130 +#define COMPAT_VARYING in +#define COMPAT_TEXTURE texture +out COMPAT_PRECISION vec4 FragColor; +#else +#define COMPAT_VARYING varying +#define FragColor gl_FragColor +#define COMPAT_TEXTURE texture2D +#endif + +uniform COMPAT_PRECISION int FrameDirection; +uniform COMPAT_PRECISION int FrameCount; +uniform COMPAT_PRECISION vec2 OutputSize; +uniform COMPAT_PRECISION vec2 TextureSize; +uniform COMPAT_PRECISION vec2 InputSize; +uniform sampler2D Texture; +COMPAT_VARYING vec4 TEX0; +COMPAT_VARYING float maskFade; +COMPAT_VARYING vec2 invDims; + +// compatibility #defines +#define Source Texture +#define vTexCoord TEX0.xy +#define texture(c, d) COMPAT_TEXTURE(c, d) +#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize +#define OutSize vec4(OutputSize, 1.0 / OutputSize) + +#ifdef PARAMETER_UNIFORM +// All parameter floats need to have COMPAT_PRECISION in front of them +uniform COMPAT_PRECISION float BLURSCALEX; +//uniform COMPAT_PRECISION float BLURSCALEY; +uniform COMPAT_PRECISION float LOWLUMSCAN; +uniform COMPAT_PRECISION float HILUMSCAN; +uniform COMPAT_PRECISION float BRIGHTBOOST; +uniform COMPAT_PRECISION float MASK_DARK; +uniform COMPAT_PRECISION float MASK_FADE; +#else +#define BLURSCALEX 0.45 +//#define BLURSCALEY 0.20 +#define LOWLUMSCAN 5.0 +#define HILUMSCAN 10.0 +#define BRIGHTBOOST 1.25 +#define MASK_DARK 0.25 +#define MASK_FADE 0.8 +#endif + +void main() +{ + + //This is just like "Quilez Scaling" but sharper + COMPAT_PRECISION vec2 p = vTexCoord * TextureSize; + COMPAT_PRECISION vec2 i = floor(p) + 0.50; + COMPAT_PRECISION vec2 f = p - i; + p = (i + 4.0*f*f*f)*invDims; + p.x = mix( p.x , vTexCoord.x, BLURSCALEX); + COMPAT_PRECISION float Y = f.y*f.y; + COMPAT_PRECISION float YY = Y*Y; +#define ratio SourceSize.x/InputSize.x +#if defined(FINEMASK) + COMPAT_PRECISION float whichmask = floor(vTexCoord.x*OutputSize.x*ratio)*-0.5; + COMPAT_PRECISION float mask = 1.0 + float(fract(whichmask) < 0.5) * -MASK_DARK; +#else + COMPAT_PRECISION float whichmask = floor(vTexCoord.x*OutputSize.x*ratio)*-0.3333; + COMPAT_PRECISION float mask = 1.0 + float(fract(whichmask) < 0.3333) * -MASK_DARK; +#endif + COMPAT_PRECISION vec3 colour = COMPAT_TEXTURE(Source, p).rgb; + + COMPAT_PRECISION float scanLineWeight = (BRIGHTBOOST - LOWLUMSCAN*(Y - 2.05*YY)); + COMPAT_PRECISION float scanLineWeightB = 1.0 - HILUMSCAN*(YY-2.8*YY*Y); + +#if defined(BLACK_OUT_BORDER) + colour.rgb*=float(tc.x > 0.0)*float(tc.y > 0.0); //why doesn't the driver do the right thing? +#endif + + FragColor.rgba = vec4(colour.rgb*mix(scanLineWeight*mask, scanLineWeightB, dot(colour.rgb,vec3(maskFade))),1.0); + +} +#endif