Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[build]
target = "m68k-unknown-none-elf"

[target.m68k-unknown-none-elf]
rustflags = ["-C", "link-arg=-Tkernel.ld"]

# Note: This target requires nightly and build-std.
# If you are on stable, you must override the target or use a custom JSON target spec (not included).
# [unstable]
# build-std = ["core", "alloc"]
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ Binaries/
disks.rar
Analysis/
Binaries/
/target
/rust_src/target
35 changes: 35 additions & 0 deletions BUILD_RUST.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Building the Rust OS

The operating system has been converted to a Rust workspace structure.

## Structure
- `rust_src/mac_types`: Common Macintosh types (OSErr, Rect, etc.) rewritten in Rust.
- `rust_src/os`: Core OS subsystems (MemoryMgr, StartMgr, etc.).
- `rust_src/kernel`: The kernel entry point and main loop (MiniFinder equivalent).

## Prerequisites
- **Rust Nightly** is **REQUIRED** to build for the `m68k-unknown-none-elf` target because the standard library (`core`) is not pre-compiled for this target.
- `rust-src` component.

## Building for Macintosh SE/30 (m68k)

1. Install the nightly toolchain and the rust-src component:
```bash
rustup toolchain install nightly
rustup component add rust-src --toolchain nightly
```

2. Build using cargo with the nightly toolchain and `build-std`:
```bash
cargo +nightly build --release -Z build-std=core,alloc
```

*Note: The `.cargo/config.toml` sets the default target to `m68k-unknown-none-elf`. You can uncomment the `[unstable]` section in that file if you are always using nightly.*

## Verifying on x86_64 Host (Syntax Check)

If you do not have the nightly toolchain or just want to check the syntax:

```bash
cargo check --target x86_64-unknown-linux-gnu
```
22 changes: 22 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[workspace]
members = [
"rust_src/mac_types",
"rust_src/kernel",
"rust_src/os",
]
resolver = "2"

[profile.release]
lto = true
opt-level = "s"
panic = "abort"

[profile.dev]
panic = "abort"
8 changes: 8 additions & 0 deletions kernel.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ENTRY(_start)

SECTIONS {
. = 0x1000;
.text : { *(.text) }
.data : { *(.data) }
.bss : { *(.bss) }
}
File renamed without changes.
11 changes: 11 additions & 0 deletions rust_src/kernel/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "kernel"
version = "0.1.0"
edition = "2021"

[dependencies]
mac_types = { path = "../mac_types" }
os = { path = "../os" }

[profile.release]
panic = "abort"
135 changes: 135 additions & 0 deletions rust_src/kernel/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#![no_std]
#![no_main]

use core::panic::PanicInfo;
use mac_types::{EventRecord, Rect, Point, Str255, EVERY_EVENT, NULL_EVENT, MOUSE_DOWN, KEY_DOWN};
use os::memory_mgr::{init_zone, new_handle, dispose_handle};

// Mock External Functions (Toolbox)
// In a real implementation, these would be linked to the actual C/Asm implementation
// or rewritten in Rust. For now, we stub them.

extern "C" {
fn InitGraf(ptr: *mut u8);
fn InitFonts();
fn InitWindows();
fn InitMenus();
fn TEInit();
fn InitDialogs(ptr: *mut u8);
fn InitCursor();
fn MaxApplZone();
}

#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "C" fn FillRect(_rect: *const Rect, _pattern: *const u8) {
// Hardware specific implementation
}

#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "C" fn SetRect(rect: *mut Rect, left: i16, top: i16, right: i16, bottom: i16) {
if rect.is_null() { return; }
(*rect).left = left;
(*rect).top = top;
(*rect).right = right;
(*rect).bottom = bottom;
}

#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "C" fn NewWindow(_w_storage: *mut u8, _bounds_rect: *const Rect, _title: *const Str255, _visible: u8, _proc_id: i16, _behind: *mut u8, _go_away_flag: u8, _ref_con: i32) -> *mut u8 {
// Return a dummy pointer
0xDEADBEEF as *mut u8
}

#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "C" fn WaitNextEvent(_event_mask: u16, the_event: *mut EventRecord, _sleep: u32, _mouse_rgn: *mut u8) -> u8 {
// Simulation: just return false for now, or true with a null event
if !the_event.is_null() {
(*the_event).what = NULL_EVENT;
}
0
}

#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "C" fn ExitToShell() -> ! {
loop {}
}

#[no_mangle]
pub extern "C" fn _start() -> ! {
main();
loop {}
}

fn main() {
let mut _my_event = EventRecord {
what: 0,
message: 0,
when: 0,
where_: Point { v: 0, h: 0 },
modifiers: 0,
};
let mut bounds = Rect::default();

// Initialize Memory Manager (Stubbed)
unsafe {
// Assume some memory range 0x10000 to 0x20000 is available for the heap
let heap_start = 0x10000 as *mut u8;
let heap_end = 0x20000 as *mut u8;
let _ = init_zone(heap_start, heap_end);

let _h = new_handle(1024);
dispose_handle(_h);
}

// In a real pure Rust OS, we would initialize our own subsystems here.
// For now, we stub the calls to show where they would go.

// unsafe {
// InitGraf(core::ptr::null_mut()); // Stub
// InitFonts();
// InitWindows();
// InitMenus();
// TEInit();
// InitDialogs(core::ptr::null_mut());
// InitCursor();
// MaxApplZone();
// }

unsafe {
// Draw Desktop
FillRect(&bounds, core::ptr::null()); // Mock

// Create a dummy window to show it's alive
SetRect(&mut bounds, 50, 50, 400, 200);
let title = Str255::from_str("System 7.1 Rust");
NewWindow(core::ptr::null_mut(), &bounds, &title, 1, 0, core::ptr::null_mut(), 1, 0);

// Main Event Loop
loop {
if WaitNextEvent(EVERY_EVENT, &mut _my_event, 60, core::ptr::null_mut()) != 0 {
match _my_event.what {
MOUSE_DOWN => {
// Handle clicks
}
KEY_DOWN => {
// Handle keys
// if (_my_event.message & 0xFF) == 'q' as u32 {
// ExitToShell();
// }
}
_ => {}
}
}
}
}
}

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
loop {}
}
6 changes: 6 additions & 0 deletions rust_src/mac_types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[package]
name = "mac_types"
version = "0.1.0"
edition = "2021"

[dependencies]
11 changes: 11 additions & 0 deletions rust_src/mac_types/src/gestalt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

use crate::{OSType};

pub type SelectorFunctionProcPtr = *mut u8; // pascal OSErr (*)(OSType, long*)

#[repr(C)]
#[derive(Clone, Copy, Debug)]
pub struct GestaltEntry {
pub selector: OSType,
pub handler: SelectorFunctionProcPtr,
}
77 changes: 77 additions & 0 deletions rust_src/mac_types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#![no_std]

pub type OSErr = i16;
pub type OSType = u32;
pub type ResType = OSType;
pub type Boolean = u8;
pub type Size = u32;
pub type Ptr = *mut u8;
pub type Handle = *mut Ptr;
pub type ProcPtr = *mut u8;
pub type GrowZoneProcPtr = *mut u8;

pub mod start;
pub mod gestalt;
pub mod timer;

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct Point {
pub v: i16,
pub h: i16,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct Rect {
pub top: i16,
pub left: i16,
pub bottom: i16,
pub right: i16,
}

impl Rect {
pub fn new(top: i16, left: i16, bottom: i16, right: i16) -> Self {
Rect { top, left, bottom, right }
}
}

#[repr(C)]
pub struct EventRecord {
pub what: u16,
pub message: u32,
pub when: u32,
pub where_: Point,
pub modifiers: u16,
}

pub const NULL_EVENT: u16 = 0;
pub const MOUSE_DOWN: u16 = 1;
pub const MOUSE_UP: u16 = 2;
pub const KEY_DOWN: u16 = 3;
pub const KEY_UP: u16 = 4;
pub const AUTO_KEY: u16 = 5;
pub const UPDATE_EVT: u16 = 6;
pub const DISK_EVT: u16 = 7;
pub const ACTIVATE_EVT: u16 = 8;
pub const OS_EVT: u16 = 15;

pub const EVERY_EVENT: u16 = 0xFFFF;

#[repr(C, packed)]
pub struct Str255 {
pub len: u8,
pub data: [u8; 255],
}

impl Str255 {
pub fn from_str(s: &str) -> Self {
let mut data = [0u8; 255];
let len = s.len().min(255);
data[..len].copy_from_slice(&s.as_bytes()[..len]);
Str255 {
len: len as u8,
data,
}
}
}
49 changes: 49 additions & 0 deletions rust_src/mac_types/src/start.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct SlotDev {
pub sd_ext_dev_id: u8,
pub sd_partition: u8,
pub sd_slot_num: u8,
pub sd_s_rsrc_id: u8,
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct SCSIDev {
pub sd_reserved1: u8,
pub sd_reserved2: u8,
pub sd_ref_num: i16,
}

#[repr(C)]
#[derive(Clone, Copy)]
pub union DefStartRec {
pub slot_dev: SlotDev,
pub scsi_dev: SCSIDev,
}

impl Default for DefStartRec {
fn default() -> Self {
DefStartRec { slot_dev: SlotDev::default() }
}
}

pub type DefStartPtr = *mut DefStartRec;

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct DefVideoRec {
pub sd_slot: u8,
pub sds_resource: u8,
}

pub type DefVideoPtr = *mut DefVideoRec;

#[repr(C)]
#[derive(Clone, Copy, Debug, Default)]
pub struct DefOSRec {
pub sd_reserved: u8,
pub sd_os_type: u8,
}

pub type DefOSPtr = *mut DefOSRec;
Loading