From 75f91949c6b6ea20e4a8fef1a50731ca0c39bb06 Mon Sep 17 00:00:00 2001 From: Daniel Olczyk Date: Thu, 6 Nov 2025 19:56:30 +0100 Subject: [PATCH] Improve README file --- LICENSE | 7 ++ README.md | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++- img/app.png | Bin 0 -> 30502 bytes 3 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 LICENSE create mode 100644 img/app.png diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..5486480 --- /dev/null +++ b/LICENSE @@ -0,0 +1,7 @@ +COPYRIGHT 2025 Rust Lab PJATK + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 7b4b780..3ae5c4b 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,218 @@ # Hachi -CHIP-8 interpreter written in Rust +[![Rust](https://img.shields.io/badge/rust-1.70%2B-orange.svg)](https://www.rust-lang.org/) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) +[![Platform](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-lightgrey.svg)](https://github.com/Rust-Lab-PJATK/hachi) + +Hachi is a modern, cross-platform CHIP-8 interpreter built with Rust, designed to accurately emulate the classic CHIP-8 virtual machine from the 1970s. The name "Hachi" (八) means "eight" in Japanese, a reference to the 8-bit architecture of the CHIP-8 system. + +This project provides a complete implementation of the CHIP-8 specification, allowing you to run classic games and programs originally developed for CHIP-8 systems. Whether you're interested in retro computing, learning about emulation, or just want to play some classic games, Hachi offers a faithful recreation of the CHIP-8 experience with modern conveniences. + + + +## What is CHIP-8? + +CHIP-8 is an interpreted programming language developed in the mid-1970s by Joseph Weisbecker. It was initially used on the COSMAC VIP and Telmac 1800 8-bit microcomputers to make game programming easier. CHIP-8 programs are run on a virtual machine with: + +- 4KB of memory +- 16 8-bit general-purpose registers (V0-VF) +- A 16-bit index register (I) +- A program counter +- A 64x32 monochrome display +- A 16-key hexadecimal keypad +- Two timer registers (delay and sound) + +## Why Hachi? + +Hachi stands out by combining accurate emulation with modern features: + +- **Written in Rust** - Leverages Rust's safety guarantees and performance characteristics +- **Cross-platform** - Runs seamlessly on macOS, Linux, and Windows +- **User-friendly** - Simple file loading with drag-and-drop support through file dialogs +- **Configurable** - Adjust emulation speed and sound settings to match different ROMs +- **Developer-friendly** - Optional debug menu for inspecting VM state during execution +- **Well-documented** - Clean, readable codebase with comprehensive documentation + +Whether you're a retro computing enthusiast, a student learning about emulation, or a developer interested in systems programming with Rust, Hachi provides an accessible and well-engineered implementation of the CHIP-8 virtual machine. + +## Features + +### Core Emulation + +- **Complete CHIP-8 instruction set** - All 35 original CHIP-8 opcodes implemented +- **Accurate timing** - 60Hz timer system for delay and sound timers +- **Configurable CPU speed** - Adjustable cycles per frame for different ROM requirements +- **Built-in font set** - Hexadecimal sprite support (0-F) + +### Display & Graphics + +- **64x32 monochrome display** - Original CHIP-8 resolution with smooth rendering +- **Sprite drawing** - XOR-based pixel rendering with collision detection +- **Screen clear** - Full display buffer management + +### Input + +- **16-key hexadecimal keypad** - Mapped to keyboard (1-4, Q-R, A-F, Z-V) +- **Key press detection** - Both synchronous and asynchronous key handling +- **Wait for key instruction** - Blocking key input support (FX0A) + +### Audio + +- **Sound timer** - Classic CHIP-8 beep sound effect +- **Volume control** - Adjustable sound volume through configuration + +### User Interface + +- **File loading** - Command-line argument or interactive file dialog support +- **Debug menu** (optional) - Real-time VM state inspection: + - Memory viewer with search functionality + - Register display (V0-VF, I, PC) + - Stack visualization + - Program execution state +- **Configuration window** - Runtime settings adjustment: + - Cycles per frame tuning + - Sound volume control + - Debug mode toggle + +### ROM Management + +- **Dynamic ROM loading** - Load any CHIP-8 ROM file at runtime +- **VM reset** - Clean state reset without restarting the application +- **Pause/Resume** - Control program execution + +### Configuration + +- **Persistent settings** - TOML-based configuration file +- **Default presets** - Sensible defaults for immediate use +- **Cross-platform config** - Platform-specific configuration directory support + +## Technologies Used + +This project is built with the following technologies: + +- **[Rust](https://www.rust-lang.org/)** - Programming language focused on memory safety and performance +- **[Notan](https://github.com/Nazariglez/notan)** - Simple and portable 2D graphics and audio framework + - Audio system for sound effects + - egui integration for debug UI +- **[egui](https://github.com/emilk/egui)** - Immediate mode GUI library for debug interface +- **[rfd](https://github.com/PolyMeilex/rfd)** - Rusty File Dialogs for cross-platform file selection +- **[clap](https://github.com/clap-rs/clap)** - Command-line argument parser +- **[serde](https://serde.rs/)** & **[toml](https://github.com/toml-rs/toml)** - Configuration serialization/deserialization + +## Prerequisites + +Before setting up the project, ensure you have the following installed: + +### All Platforms + +- **Rust toolchain** (1.70.0 or later) + +### Platform-Specific Requirements + +#### macOS + +No additional dependencies required. The project uses native macOS frameworks. + +#### Linux + +Install the following development packages: + +**Debian/Ubuntu:** + +```bash +sudo apt-get update +sudo apt-get install -y build-essential pkg-config libasound2-dev libudev-dev +``` + +**Fedora:** + +```bash +sudo dnf install gcc pkg-config alsa-lib-devel systemd-devel +``` + +**Arch Linux:** + +```bash +sudo pacman -S base-devel alsa-lib systemd +``` + +#### Windows + +- Install [Visual Studio Build Tools](https://visualstudio.microsoft.com/downloads/) or Visual Studio with C++ development tools +- Rust will use the MSVC toolchain by default + +## Setup + +1. **Clone the repository:** + + ```bash + git clone https://github.com/Rust-Lab-PJATK/hachi.git + cd hachi + ``` + +2. **Build the project:** + + ```bash + cargo build --release + ``` + +3. **Verify the build:** + + ```bash + cargo test + ``` + +## How to Run + +### Without provided ROM + +```bash +cargo run --release +``` + +You can then load a ROM file using the file dialog in the application. + +### Running the example ROM + +The project includes an example ROM in the `assets` folder: + +```bash +cargo run --release -- --file assets/ibm.ch8 +``` + +### Command-line Options + +- `-f, --file ` - Path to a CHIP-8 ROM file to load on startup + +## Controls + +The CHIP-8 keypad is mapped to your keyboard as follows: + +### Keypad Mapping + +```text +Original CHIP-8 Keypad: Keyboard Mapping: +┌───┬───┬───┬───┐ ┌───┬───┬───┬───┐ +│ 1 │ 2 │ 3 │ C │ │ 1 │ 2 │ 3 │ 4 │ +├───┼───┼───┼───┤ ├───┼───┼───┼───┤ +│ 4 │ 5 │ 6 │ D │ │ Q │ W │ E │ R │ +├───┼───┼───┼───┤ ├───┼───┼───┼───┤ +│ 7 │ 8 │ 9 │ E │ │ A │ S │ D │ F │ +├───┼───┼───┼───┤ ├───┼───┼───┼───┤ +│ A │ 0 │ B │ F │ │ Z │ X │ C │ V │ +└───┴───┴───┴───┘ └───┴───┴───┴───┘ +``` + +## Project Structure + +```text +hachi/ +├── src/ +│ ├── main.rs # Application entry point +│ ├── config/ # Configuration management +│ ├── ui/ # User interface and rendering +│ └── vm/ # CHIP-8 virtual machine implementation +├── assets/ # ROM files and resources +├── Cargo.toml # Rust dependencies and project metadata +└── README.md +``` diff --git a/img/app.png b/img/app.png new file mode 100644 index 0000000000000000000000000000000000000000..93d4a42d33675f6ca0d90a14dc5dcca3ad56b528 GIT binary patch literal 30502 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 rO