MCPcopy Create free account
hub / github.com/amcchord/M5Tab-Macintosh

github.com/amcchord/M5Tab-Macintosh @v4.0

Chat with this repo
repository ↗ · DeepWiki ↗ · release v4.0 ↗ · + Follow
4,028 symbols 13,489 edges 246 files 399 documented · 10% updated 2mo agov4.1-beta · 2026-04-25★ 2382 open issues

Browse by type

Functions 3,920 Types & classes 108
What it actually does AI analysis from the code graph — generated when you open this
loading…
README

BasiliskII ESP32 — Classic Macintosh Emulator

A full port of the BasiliskII Macintosh 68k emulator to the ESP32-P4, bringing classic Mac OS (System 7.x through Mac OS 8.1) to portable embedded devices with touchscreen and USB peripheral support.

Two boards are currently supported from the same source tree:

Board Display Mac screen PlatformIO env
M5Stack Tab5 5" 1280x720 640x360 @ 2x esp32p4_pioarduino
Waveshare ESP32-P4-WIFI6-Touch-LCD-10.1 10.1" 800x1280 (rotated to 1280x800 landscape) 640x400 @ 2x waveshare_p4_101

Both variants share the BasiliskII core, video pipeline, USB HID handling, and boot GUI. Per-board drivers live behind a thin HAL in src/board/; see docs/waveshare/README.md for the Waveshare-specific pin map and notes.


Screenshots

Flying Toasters v4.0

Flying Toasters running smoothly with write-time dirty tracking and tile-based rendering — the three-finger on-screen keyboard lives one gesture away

Mac OS 8.1 Desktop Mac OS 8.1 About This Macintosh

Mac OS 8.1 Booting System 7.5.3 About This Macintosh

Browsing the Internet on System 7

Browsing the web on System 7 via the built-in WiFi networking

View Animations


What's New in v4.0

  • Multi-touch on-screen keyboard — three-finger tap anywhere on the Mac screen spawns a full QWERTY overlay with sticky Shift / Ctrl / Option / Command modifiers and an arrow cluster. Typing drives real ADB keystrokes, so it works in any Mac application — Finder, SimpleText, HyperCard, Netscape, the works. Three-finger tap again to dismiss.
  • Gaming overlay — four-finger tap spawns a D-pad plus Esc / Return / Space / Option action cluster for arrow-key games (Glider, Crystal Quest, Marathon, etc.). Four-finger tap dismisses; a three-finger tap while the gaming overlay is up swaps straight over to the keyboard.
  • "Transparent" overlay without alpha math — because every Mac pixel is already pixel-doubled to a 2x2 physical block, the compositor writes only the (even, even) sub-pixel of each block, giving exact 25% coverage so the Mac content shows through the other three sub-pixels for free. Held keys overlay a 50% checker of black for a pressed look; latched modifiers use the opposite checker so you can tell at a glance which Shift state is active.
  • Per-board PlatformIO pinning — the Tab5 and Waveshare now lock to different pioarduino releases because each adjacent release breaks the other board. Tab5 stays on 55.03.35 (IDF 5.5.1) to avoid a MIPI-DSI backlight flicker that hit M5GFX in IDF 5.5.2; Waveshare moves to 55.03.38-1 (IDF 5.5.4) to pick up the newer esp_hosted that no longer panics in sdio_rx_get_buffer under sustained SD I/O.
  • Tab5 USB Disk over USB-A — SD-card-over-USB-MSC now routes through the Tab5's USB-A port (OTG-HS, where TinyUSB actually lands on the ESP32-P4) instead of USB-C. HWCDC stays alive throughout, so the serial console keeps working while the card is mounted on your host. Plug a standard USB-A-to-USB-C cable into the Tab5 USB-A jack and the other end into your computer; Tab5's own 5V output is gated off so the host supplies VBUS.
  • Auto-sized USB Disk dialog — the pre-boot MSC dialog now grows to fit its copy so the Tab5 cable instructions no longer run under the Done button.
  • Carry-forward from the 3.4.x line — 180° Tab5 rotation, single-refresh boot splash, shared folder (ExtFS), baked-in ESP32-C6 WiFi firmware with SDIO hosted OTA, XPRAM write coalescing, and the pre-boot-to-Mac-OS handoff with no gray flash.

On-screen keyboard overlay on the M5Stack Tab5 Gaming D-pad overlay on the M5Stack Tab5

On-screen keyboard overlay on the Waveshare P4 10.1 Pre-boot configuration environment


Overview

This project runs a Motorola 68040 emulator that can boot real Macintosh ROMs and run genuine classic Mac OS software. Performance is comparable to a Macintosh Quadra 610 (25 MHz 68040), achieving 24 FPS video and 2-3 MIPS CPU speed. The emulation includes:

  • CPU: Motorola 68040 emulation with FPU (68881) — 2-3 MIPS
  • RAM: Configurable from 4MB to 16MB (allocated from ESP32-P4's 32MB PSRAM)
  • Display: 640×360 virtual display (2× scaled to 1280×720 physical display), supporting 1/2/4/8-bit color depths at 24 FPS
  • Storage: Hard disk and CD-ROM images loaded from SD card
  • Input: Capacitive touchscreen (as mouse) + USB keyboard/mouse support
  • Audio: Classic Mac sound output via ES8388 codec (toggleable in boot GUI)
  • Networking: WiFi internet access via NAT router (TCP, UDP, ICMP, DHCP)
  • Video: Optimized pipeline with write-time dirty tracking, double-buffered DMA, and tile-based rendering

Hardware

M5Stack Tab5

The Tab5 features a unique dual-chip architecture that makes it ideal for this project:

Chip Role Key Features
ESP32-P4 Main Application Processor 400MHz dual-core RISC-V, 32MB PSRAM, MIPI-DSI display
ESP32-C6 Wireless Co-processor WiFi 6, Bluetooth LE 5.0 — provides internet access to classic Mac OS

Key Specifications

Component Details
Display 5" IPS TFT, 1280×720 (720p), MIPI-DSI interface
Touch Capacitive multi-touch (ST7123 controller)
Memory 32MB PSRAM for emulated Mac RAM + frame buffers
Storage microSD card slot for ROM, disk images, and settings
USB Type-A host port for keyboard/mouse, Type-C for programming
Audio ES8388 DAC/ADC codec — classic Mac sound output
Battery NP-F550 Li-ion (2000mAh) for portable operation

See boardConfig.md for detailed pin mappings and hardware documentation.


Architecture

Dual-Core Design

The emulator leverages the ESP32-P4's dual-core RISC-V architecture for optimal performance:

┌─────────────────────────────────────────────────────────────────┐
│                        ESP32-P4 (400MHz)                        │
├────────────────────────────┬────────────────────────────────────┤
│         CORE 0             │              CORE 1                │
│    (Video & I/O Core)      │       (CPU Emulation Core)         │
├────────────────────────────┼────────────────────────────────────┤
│  • Video rendering task    │  • 68040 CPU interpreter           │
│  • Double-buffered DMA     │  • Fast-path memory access         │
│  • 2×2 pixel scaling       │  • Write-time dirty marking        │
│  • Input task (60Hz)       │  • Batch instruction execution     │
│  • USB HID processing      │  • ROM patching                    │
│  • Audio output (ES8388)   │  • Disk I/O                        │
│  • Network RX polling      │                                    │
│  • Event-driven @ 24 FPS   │                                    │
└────────────────────────────┴────────────────────────────────────┘

Memory Layout

┌──────────────────────────────────────────────────────────────┐
│                    32MB PSRAM Allocation                     │
├──────────────────────────────────────────────────────────────┤
│  Mac RAM (4-16MB)          │  Configurable via Boot GUI      │
├────────────────────────────┼─────────────────────────────────┤
│  Mac ROM (~1MB)            │  Q650.ROM or compatible         │
├────────────────────────────┼─────────────────────────────────┤
│  Mac Frame Buffer (230KB)  │  640×360 @ 8-bit indexed color  │
├────────────────────────────┼─────────────────────────────────┤
│  Display Buffer (1.8MB)    │  1280×720 @ RGB565              │
├────────────────────────────┼─────────────────────────────────┤
│  Free PSRAM                │  Varies based on RAM selection  │
└──────────────────────────────────────────────────────────────┘

┌──────────────────────────────────────────────────────────────┐
│                    Internal SRAM (Priority)                  │
├──────────────────────────────────────────────────────────────┤
│  CPU Function Table        │  cpufunctbl - hot path lookup   │
├────────────────────────────┼─────────────────────────────────┤
│  Memory Bank Pointers      │  256KB - memory banking         │
├────────────────────────────┼─────────────────────────────────┤
│  Palette (512 bytes)       │  256 RGB565 entries             │
├────────────────────────────┼─────────────────────────────────┤
│  Dirty Tile Bitmap         │  144 bits (write-time tracking) │
├────────────────────────────┼─────────────────────────────────┤
│  Tile Render Lock Bitmap   │  144 bits (race prevention)     │
├────────────────────────────┼─────────────────────────────────┤
│  Double-Buffered Tile Bufs │  ~28KB (DMA pipelining)         │
└──────────────────────────────────────────────────────────────┘

Video Pipeline

The video system uses a highly optimized pipeline with write-time dirty tracking to minimize CPU overhead:

┌─────────────────────────────────────────────────────────────────┐
│                    Video Pipeline Architecture                   │
├─────────────────────────────────────────────────────────────────┤
│                                                                  │
│  ┌──────────────┐    marks dirty    ┌─────────────────────────┐ │
│  │  68040 CPU   │ ─────────────────▶│   Dirty Tile Bitmap     │ │
│  │  (Core 1)    │                   │   (16×9 = 144 tiles)    │ │
│  └──────────────┘                   └─────────────────────────┘ │
│         │                                      │                │
│         │ writes                               │ read & clear   │
│         ▼                                      ▼                │
│  ┌──────────────┐                   ┌─────────────────────────┐ │
│  │ Mac Frame    │                   │    Video Task (Core 0)  │ │
│  │   Buffer     │ ─────────────────▶│  • Tile snapshot        │ │
│  │ (640×360)    │   read tiles      │  • Palette lookup       │ │
│  └──────────────┘                   │  • 2×2 scaling          │ │
│                                     └─────────────────────────┘ │
│                                                │                │
│                                                │ push tiles     │
│                                                ▼                │
│                                     ┌─────────────────────────┐ │
│                                     │   MIPI-DSI Display      │ │
│                                     │      (1280×720)         │ │
│                                     └─────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

Key Features

  1. Write-Time Dirty Tracking: When the 68040 CPU writes to the framebuffer, the memory system immediately marks the affected tile(s) as dirty. This eliminates expensive per-frame comparisons.

  2. Tile-Based Rendering: The screen is divided into a 16×9 grid of 40×40 pixel tiles (144 total). Only dirty tiles are re-rendered each frame, typically reducing video CPU time by 60-90%.

  3. Double-Buffered DMA: Render to one buffer while DMA pushes another to the display. Both tile rendering and full-frame streaming use this pipelining for maximum throughput.

  4. Per-Tile Render Locks: Atomic locks prevent race conditions during tile snapshot. If the CPU writes to a tile being rendered, it's automatically re-queued for the next frame—ensuring glitch-free display.

  5. Multi-Depth Support: Supports 1/2/4/8-bit indexed color modes with packed pixel decoding. Mac OS can switch between depths via the Monitors control panel.

  6. Event-Driven Refresh at 24 FPS: Cinema-standard frame rate with task notifications—the video task sleeps until signaled, reducing idle polling overhead.


Emulation Details

BasiliskII Components

This port includes the following BasiliskII subsystems, adapted for ESP32:

Component File(s) Description
UAE CPU uae_cpu/*.cpp Motorola 68040 interpreter
Memory uae_cpu/memory.cpp Memory banking with write-time dirty tracking
ADB adb.cpp Apple Desktop Bus for keyboard/mouse
Video video_esp32.cpp Tile-based display driver with 2× scaling
Disk disk.cpp, sys_esp32.cpp HDD image support via SD card
CD-ROM cdrom.cpp ISO image mounting
XPRAM xpram_esp32.cpp Non-volatile parameter RAM
**Timer

Core symbols most depended-on inside this repo

Shape

Function 3,816
Method 104
Class 100
Enum 8

Languages

C++87%
C12%
Python1%

Modules by API surface

src/basilisk/uae_cpu/generated/cpuemu.cpp2,161 symbols
src/basilisk/extfs.cpp57 symbols
src/basilisk/boot_gui.cpp57 symbols
src/basilisk/uae_cpu/memory.cpp55 symbols
src/basilisk/uae_cpu/newcpu.cpp50 symbols
src/basilisk/jit/rv32_emitter.cpp49 symbols
src/basilisk/driver_stubs.cpp46 symbols
src/basilisk/touch_overlay.cpp44 symbols
src/basilisk/net_router.cpp38 symbols
src/basilisk/video_esp32.cpp36 symbols
src/basilisk/input_esp32.cpp34 symbols
src/basilisk/sys_esp32.cpp33 symbols

For agents

$ claude mcp add M5Tab-Macintosh \
  -- python -m otcore.mcp_server <graph>

⬇ download graph artifact

Ask about this repo answers extend the page