You now have a fully functional CP/M interactive shell! Phase 1 is complete with all requested features:
- File:
CPMTerminalViewController.swift - Full-screen terminal with green-on-black retro styling
- Menlo monospace font for authentic terminal feel
- Custom keyboard toolbar with CP/M control characters (^C, ^Z, ESC)
- Auto-uppercase conversion (CP/M standard)
- Proper character echoing and backspace handling
- Scroll-to-bottom behavior
- Modified:
8080.clines 154-168 - CPU now properly waits for user input without busy-looping
- Sets
waiting_for_inputflag when no input available - Emulator pauses execution until character arrives
- Input is properly echoed back to the user
- Modified:
8080.clines 185-254 - Full line editing with backspace support
- Character-by-character reading with echo
- Waits for Enter key before completing
- Properly handles empty lines
- File:
TextDocumentViewController.swift-loadInteractiveCCP() - Commands Implemented:
DIR- List all files on diskTYPE filename- Display file contentsERA filename- Delete a fileEXIT- Halt the system
- Proper filename parsing (8.3 format)
- Clean error messages
- Infinite command loop with "A>" prompt
- Modified:
8080.c-cpm_create_sample_file() - Three demo files created automatically:
WELCOME.TXT- Welcome messageHELP.TXT- Command referenceREADME.TXT- System information
- Open your app in Xcode
- Click the "Samples" button repeatedly to cycle through programs
- Stop when you see "CP/M Interactive Shell (CCP)"
- Click "Assemble"
Option A: Add a Terminal button to your storyboard
- Open Main.storyboard
- Find the TextDocumentViewController scene
- Add a UIBarButtonItem to the toolbar
- Set its action to
tapTerminal: - Run the app and click the Terminal button
Option B: Call it programmatically (temporary test) Add this to your code somewhere you can trigger it:
tapTerminal(self)Once the terminal opens, you'll see:
CP/M 2.2 Terminal
Ready.
A>_
Try these commands:
A>DIR
WELCOME .TXT HELP .TXT README .TXT
A>TYPE WELCOME.TXT
Welcome to CP/M 2.2!
Type DIR to see files.
A>TYPE HELP.TXT
Available commands:
DIR - List files
TYPE filename - Display file
ERA filename - Delete file
EXIT - Halt system
A>ERA README.TXT
File deleted
A>DIR
WELCOME .TXT HELP .TXT
A>EXIT
Goodbye!
(System halts)
- ^C Button: Send Ctrl-C (interrupt)
- ^Z Button: Send Ctrl-Z (EOF marker)
- ESC Button: Send Escape character
- Done Button: Hide keyboard
- Auto-uppercase: All input automatically converted to uppercase (CP/M standard)
- Backspace: Works correctly to delete characters
Instead of truly blocking (which would freeze the iOS UI), the system uses a "waiting" flag:
-
When BDOS function 1 or 10 is called with no input available:
- Set
cpm_console.waiting_for_input = 1 - Return immediately without advancing PC
- Emulator checks this flag before executing instructions
- Set
-
When user types a character:
- Character goes into input buffer via
cpm_put_char() - Next emulator step detects input available
- BDOS call retries and succeeds
- Clear
waiting_for_inputflag and continue
- Character goes into input buffer via
-
The emulator loop (in CPMTerminalViewController):
func emulatorStep() { if cpm_is_waiting_for_input() != 0 { return // Don't execute, wait for input } codestep() // Execute next instruction }
- Directory: First 2 tracks (64 entries max)
- Data Storage: Tracks 2-76
- Allocation: 1 block = 1 track, 8 records per block
- Record Size: 128 bytes
- EOF Marker: 0x1A (Ctrl-Z)
The CCP uses simple string matching:
- Read command line into buffer (max 40 chars)
- Compare first characters to known commands
- Parse filename from command line (for TYPE, ERA)
- Call appropriate BDOS functions
-
Add REN Command: Implement rename functionality
- Parse two filenames from command line
- Call BDOS function 23
-
Add SAVE Command: Create new files from terminal
- Read content from console
- Write to new file
-
Command History: Use up/down arrows to recall previous commands
-
Tab Completion: Auto-complete filenames
-
More Commands:
STAT- Show disk statisticsTYPEwith wildcardsCOPY- Copy filesFORMAT- Format disk
-
Multiple Disks:
- Switch between A: and B:
- Copy files between disks
-
Load .COM Files:
- Import actual CP/M programs from iOS Files app
- Execute them in the emulator
- Load Real CCP: Use actual CP/M 2.2 CCP binary
- Full BDOS: Complete all 37 BDOS functions
- BIOS: Implement full CP/M BIOS
- Run Classic Software: WordStar, Turbo Pascal, dBase, etc.
- Make sure you assembled the code first
- Check that
tapTerminalaction is connected in storyboard - Look for errors in Xcode console
- Check that
cpm_console.input_echois set to 1 - Verify BDOS function 2 (console output) is working
- Ensure you're typing in UPPERCASE (or let auto-conversion handle it)
- Check spelling exactly: DIR, TYPE, ERA, EXIT
- For TYPE/ERA, include the full filename:
TYPE WELCOME.TXT
- Use DIR to see what files exist
- Remember the 8.3 format: 8 chars max for name, 3 for extension
- Filenames are space-padded in memory
CPMTerminalViewController.swift- Terminal UICPM_INTERACTIVE_SHELL_GUIDE.md- This guide
-
8080.c:- Console I/O state with waiting flags (lines 56-64)
- Blocking BDOS function 1 (lines 154-168)
- Blocking BDOS function 10 with editing (lines 185-254)
- Sample file creation (lines 973-1024)
- Helper functions (lines 1557-1570)
-
Document Browser-Bridging-Header.h:- Exposed new C functions (lines 23-25)
-
TextDocumentViewController.swift:- Interactive CCP assembly program (lines 918-1314)
- Terminal launch action (lines 338-360)
- Updated sample cycling (lines 362-378)
You now have a working CP/M interactive shell! 🎉
You can:
- Type commands interactively
- List files with DIR
- Read files with TYPE
- Delete files with ERA
- Navigate with a real command prompt
This is a huge milestone - you've essentially created a miniature operating system running on an emulated 1970s CPU, all on an iPad!
Have fun exploring your CP/M system!