Skip to content
This repository was archived by the owner on Sep 10, 2025. It is now read-only.

Commit ee3b715

Browse files
authored
Merge pull request #160 from skx/65-input
Avoid the unnecessary invokation of STTY
2 parents 96fae4b + 21a91f5 commit ee3b715

26 files changed

+861
-364
lines changed

.github/build

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ if [ -d /github/workspace ] ; then
1212
fi
1313

1414
#
15-
# We build on only a single platform/arch.
15+
# We build for many platforms.
1616
#
17-
BUILD_PLATFORMS="linux darwin freebsd openbsd netbsd"
17+
BUILD_PLATFORMS="linux darwin freebsd openbsd netbsd windows"
1818
BUILD_ARCHS="amd64 386"
1919

2020
# For each platform

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
cpmulator
22
cpmulator-*
3+
*.exe

README.md

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Over time this project has become more complete, and I've now implemented enough
1313
* BBC and Microsoft BASIC.
1414
* Wordstar.
1515

16-
As things stand this project is "complete". I'd like to increase the test-coverage for my own reassurance, but I've now reached a point where all the binaries I've tried to execute work as expected. If you find a program that _doesn't_ work please [open an issue](https://github.com/skx/cpmulator/issues), beyond that I think this project is "complete" and future development will be minimal, and sporadic.
16+
As things stand this project is "complete". I'd like to increase the test-coverage for my own reassurance, but I've now reached a point where all the binaries I've tried to execute work as expected. If you find a program that _doesn't_ work please [open an issue](https://github.com/skx/cpmulator/issues), otherwise I suspect ongoing development will be minimal, and sporadic.
1717

1818
> **NOTE** I've not implemented any notion of disk-support. This means that opening, reading/writing, and closing files is absolutely fine, but any API call that refers to tracks, sectors, or disks will fail (with an "unimplemented syscall" error).
1919
@@ -62,22 +62,6 @@ Releases will be made as/when features seem to justify it, but it should be note
6262

6363

6464

65-
# Portability
66-
67-
The CP/M input handlers need to disable echoing when reading (single) characters from STDIN. There isn't a simple and portable solution for this in golang, although the appropriate primitives exist so building such support isn't impossible.
68-
69-
Usage of is demonstrated in the standard library:
70-
71-
* [x/term package](https://pkg.go.dev/golang.org/x/term)
72-
* [ReadPassword](https://pkg.go.dev/golang.org/x/term#ReadPassword) - ReadPassword reads a line of input from a terminal without local echo.
73-
74-
Unfortunately there is no code there for reading only a _single character_, rather than a complete line. In the interest of expediency I resort to executing the `stty` binary, rather than attempting to use the `x/term` package to manage echo/noecho state myself, and this means the code in this repository isn't 100% portable; it will work on Linux and MacOS hosts, but not Windows.
75-
76-
I've got an open bug about fixing the console (input), [#65](https://github.com/skx/cpmulator/issues/65).
77-
78-
79-
80-
8165
# Usage
8266

8367
If you launch `cpmulator` with no arguments then the default CCP ("console command processor") will be launched, dropping you into a familiar shell:
@@ -139,7 +123,7 @@ $ cpmulator /path/to/binary [optional-args]
139123

140124
## Command Line Flags
141125

142-
There are several command-line options which are shown in the output of `cpmulator -help`, but the following summary shows the most important/useful options:
126+
There are many available command-line options, which are shown in the output of `cpmulator -help`, but the following summary shows the most important/useful options:
143127

144128
* `-cd /path/to/directory`
145129
* Change to the given directory before running.
@@ -152,6 +136,7 @@ There are several command-line options which are shown in the output of `cpmulat
152136
* All output which CP/M sends to the "printer" will be written to the given file.
153137
* `-list-syscalls`
154138
* Dump the list of implemented BDOS and BIOS syscalls.
139+
* `-list-input-drivers` and `-list-output-drivers` to see the available I/O driver-names, which may then be selected via the `-input` and `-output` flags.
155140
* `-version`
156141
* Show the version number of the emulator, and exit.
157142

@@ -171,9 +156,9 @@ This allows you to customize the emulator, or perform other "one-time" setup via
171156

172157
## Runtime Behaviour Changes
173158

174-
There are a small number of [extensions](EXTENSIONS.md) added to the BIOS functionality we provide, and these extensions allow changing the behaviour of the emulator at runtime.
159+
There are a small number of [extensions](EXTENSIONS.md) added to the BIOS functionality we provide, and these extensions allow changing some aspects of the emulator at runtime.
175160

176-
The behaviour changing is achieved by having a small number of .COM files invoke the extension functions, and these binaries are embedded within our emulator to improve ease of use, via the [static/](static/) directory in our source-tree - This means no matter what you'll always find some binaries installed on A:, despite not being present in reality.
161+
The behaviour changing is achieved by having a small number of .COM files invoke the extension functions, and these binaries are embedded within our emulator to improve ease of use, via the [static/](static/) directory in our source-tree. This means no matter what you'll always find some binaries installed on A:, despite not being present in reality.
177162

178163
> **NOTE** To avoid naming collisions all our embedded binaries are named with a `!` prefix, except for `#.COM` which is designed to be used as a comment-binary.
179164
@@ -192,12 +177,14 @@ The binary `A:!CTRLC.COM` which lets you change this at runtime. Run `A:!CTRLC
192177

193178
### Console Output
194179

195-
We default to pretending our output device is an ADM-3A terminal, this can be changed via the `-console` command-line flag at startup. Additionally it can be changed at runtime via `A:!CONSOLE.COM`.
180+
We default to pretending our output device is an ADM-3A terminal, this can be changed via the `-output` command-line flag (previously `-console`) at startup. Additionally it can be changed at runtime via `A:!CONSOLE.COM`.
196181

197182
Run `A:!CONSOLE ansi` to disable the output emulation, or `A:!CONSOLE adm-3a` to restore it.
198183

199184
You'll see that the [cpm-dist](https://github.com/skx/cpm-dist) repository contains a version of Wordstar, and that behaves differently depending on the selected output handler. Changing the handler at run-time is a neat bit of behaviour.
200185

186+
You'll note it is **not** possible to change the console _input_ driver at runtime, I think once you know which works best upon your system it doesn't make sense to change this interactively.
187+
201188

202189
### Debug Handling
203190

@@ -207,6 +194,8 @@ runtime.
207194

208195
`A:!DEBUG.COM` will show the state of the flag, and it can be enabled with `A:!DEBUG 1` or disabled with `!DEBUG 0`.
209196

197+
Finally `A:!VERSION.COM` will show you the version of the emulator you're running.
198+
210199

211200

212201

@@ -326,6 +315,22 @@ The implementation of the syscalls is the core of our emulator, and they can be
326315

327316

328317

318+
# Portability
319+
320+
The CP/M input handlers need to disable echoing when reading (single) characters from STDIN. There isn't a simple and portable solution for this in golang, although the appropriate primitives exist so building such support isn't impossible, it just relies upon writing per-environment support, using something like the [ReadPassword](https://pkg.go.dev/golang.org/x/term#ReadPassword) function from the standard-library.
321+
322+
I sidestepped this whole problem initially, just invoking the `stty` binary to enable/disable the echoing of characters on-demand, but that only works on Linux, BSD, and Mac hosts. To be properly portable I had to use the [termbox](https://github.com/nsf/termbox-go) library for all input, but that means we get no scrollback/history so there's a tradeoff to be made.
323+
324+
By default input will be read via `termbox` but you may you specify a different driver via the CLI arguments:
325+
326+
* `cpmulator -input xxx`
327+
* Use the input-driver named `xxx`.
328+
* `cpmulator -list-input-drivers`
329+
* List all available input-drivers.
330+
331+
332+
333+
329334
# Debugging Failures & Tweaking Behaviour
330335

331336
When an unimplemented BIOS call is attempted the program it will abort with a fatal error, for example:

ccp/ccp.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,21 @@ import (
1515

1616
// Flavour contains details about a possible CCP the user might run.
1717
type Flavour struct {
18-
// Name has the name of the CCP.
18+
// Name contains the public-facing name of the CCP.
1919
//
2020
// NOTE: This name is visible to end-users, and will be used in the "-ccp" command-line flag,
21-
// or as the name when changing at run-time via the "CCP.COM" utility.
21+
// or as the name when changing at run-time via the "A:!CCP.COM" binary.
2222
Name string
2323

24-
// Description has the description of the CCP.
24+
// Description contains the description of the CCP.
2525
Description string
2626

2727
// Bytes contains the raw binary content.
2828
Bytes []uint8
2929

30-
// Origin contains the start/load location of the CCP.
30+
// Start specifies the memory-address, within RAM, to which the raw bytes should be loaded and to which control should be passed.
31+
//
32+
// (i.e. This must match the ORG specified in the CCP source code.)
3133
Start uint16
3234
}
3335

0 commit comments

Comments
 (0)