Skip to content

Commit

Permalink
Cleanup our code a little (#141)
Browse files Browse the repository at this point in the history
* Cleanup our CLI arguments a little
  * Rename "syscalls" to be -list-syscalls.
  * Rename "ccps" to be "-list-ccp".
  * Add -list-console-drivers.
* Updated the constructor for the CPM package to drop the logger
  *  We can use `slog.SetDefault` to avoid passing the handle around.
* Drop the use of the quiet flag, and cut down on register-logging.
* Fixed bug with writing wrong character to printer.log
  * Added test case for same, which is how I found it.
* 100% test coverage of memory-package
* Added tests for the cpm-package.
  • Loading branch information
skx authored Jun 25, 2024
1 parent 1bf72f7 commit b6a172a
Show file tree
Hide file tree
Showing 14 changed files with 272 additions and 270 deletions.
10 changes: 1 addition & 9 deletions EXTENSIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,7 @@ Demonstrated in [samples/ccp.z80](samples/ccp.z80)

## Function 0x04: Get/Set Quiet Flag

* If C is 0x01 quiet-mode is enabled.
* If C is 0x00 quiet-mode is disabled.
* If C is 0xFF quiet-mode is queried.
* 0x00 means it is disabled.
* 0x01 means it is active.

Quiet mode prevents the display of a banner every time the CCP is restarted.

Demonstrated in [samples/quiet.z80](samples/quiet.z80)
* Removed. Obsolete.



Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ There are several command-line options which are shown in the output of `cpmulat
* All output which CP/M sends to the "printer" will be written to the given file.
* `-quiet`
* Enable quiet-mode, which cuts down on output.
* `-syscalls`
* `-list-syscalls`
* Dump the list of implemented BDOS and BIOS syscalls.
* `-version`
* Show the version number of the emulator, and exit.
Expand Down Expand Up @@ -309,7 +309,7 @@ $ cpmulator -ccp=ccpz -drive-a /tmp -drive-b ~/Repos/github.com/skx/cpm-dist/G/
You can see the list of implemented syscalls, along with a mention of how complete their implementation is, by running:

```
$ cpmulator -syscalls
$ cpmulator -list-syscalls
BDOS
00 P_TERMCPM
01 C_READ
Expand Down
10 changes: 10 additions & 0 deletions consoleout/console_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,13 @@ func TestNull(t *testing.T) {
t.Fatalf("got output, expected none: '%s'", tmp.String())
}
}

func TestList(t *testing.T) {
x, _ := New("foo")

valid := x.GetDrivers()

if len(valid) != 2 {
t.Fatalf("unexpected number of console drivers")
}
}
16 changes: 15 additions & 1 deletion consoleout/consoleout.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type ConsoleDriver interface {
// GetName will return the name of the driver.
GetName() string

// SetWriter will update the writer
// SetWriter will update the writer.
SetWriter(io.Writer)
}

Expand Down Expand Up @@ -87,6 +87,20 @@ func (co *ConsoleOut) GetName() string {
return co.driver.GetName()
}

// GetDrivers returns all available driver-names.
//
// We hide the internal "null" driver.
func (co *ConsoleOut) GetDrivers() []string {
valid := []string{}

for x := range handlers.m {
if x != "null" {
valid = append(valid, x)
}
}
return valid
}

// PutCharacter outputs a character, using our selected driver.
func (co *ConsoleOut) PutCharacter(c byte) {
co.driver.PutCharacter(c)
Expand Down
56 changes: 13 additions & 43 deletions cpm/cpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
"github.com/skx/cpmulator/consoleout"
"github.com/skx/cpmulator/fcb"
"github.com/skx/cpmulator/memory"
cpmver "github.com/skx/cpmulator/version"
)

var (
Expand Down Expand Up @@ -59,7 +58,7 @@ type CPMHandlerType func(cpm *CPM) error

// CPMHandler contains details of a specific call we implement.
//
// While we mostly need a "number to handler", mapping having a name
// While we mostly need a "number to handler", having a name as well
// is useful for the logs we produce, and we mark those functions that
// don't do 100% of what they should as "Fake".
type CPMHandler struct {
Expand Down Expand Up @@ -87,14 +86,14 @@ type CPMHandler struct {
Noisy bool
}

// FileCache is used to cache filehandles, against FCB addresses.
//
// This is primarily done as a speed optimization.
// FileCache is used to cache filehandles on the host-side of the system,
// which have been opened by the CP/M binary/CCP.
type FileCache struct {
// name holds the name file, when it was opened/created.
// name holds the name of the file, when it was opened/created,
// on the host-side.
name string

// handle has the file object.
// handle has the file handle of the opened file.
handle *os.File
}

Expand All @@ -111,9 +110,6 @@ type CPM struct {
// ccp contains the name of the CCP we should load
ccp string

// Should we be quiet?
quiet bool

// files is the cache we use for File handles.
files map[uint16]FileCache

Expand All @@ -126,7 +122,7 @@ type CPM struct {
// This needs to take account of echo/no-echo status.
input *consolein.ConsoleIn

// output is used for writing characters to the conolse
// output is used for writing characters to the console.
output *consoleout.ConsoleOut

// dma contains the address of the DMA area in RAM.
Expand Down Expand Up @@ -188,9 +184,6 @@ type CPM struct {
// to be read next.
findOffset int

// Logger holds a logger which we use for debugging and diagnostics.
Logger *slog.Logger

// simpleDebug is used to just output the name of syscalls made.
//
// For real debugging we expect the caller to use our Logger, via
Expand All @@ -199,7 +192,7 @@ type CPM struct {
}

// New returns a new emulation object
func New(logger *slog.Logger, prn string, condriver string, ccp string) (*CPM, error) {
func New(prn string, condriver string, ccp string) (*CPM, error) {

//
// Create and populate our syscall table for the BDOS syscalls.
Expand Down Expand Up @@ -464,7 +457,6 @@ func New(logger *slog.Logger, prn string, condriver string, ccp string) (*CPM, e
tmp := &CPM{
BDOSSyscalls: bdos,
BIOSSyscalls: bios,
Logger: logger,
ccp: ccp,
dma: 0x0080,
drives: make(map[string]string),
Expand Down Expand Up @@ -492,11 +484,6 @@ func (cpm *CPM) GetCCPName() string {
return cpm.ccp
}

// GetQuiet returns the status of the quiet-flag.
func (cpm *CPM) GetQuiet() bool {
return cpm.quiet
}

// LogNoisy enables logging support for each of the functions which
// would otherwise be disabled
func (cpm *CPM) LogNoisy() {
Expand All @@ -511,11 +498,6 @@ func (cpm *CPM) LogNoisy() {
}
}

// SetQuiet updates the state of the quiet-flag.
func (cpm *CPM) SetQuiet(state bool) {
cpm.quiet = state
}

// LoadBinary loads the given CP/M binary at the default address of 0x0100,
// where it can then be launched by Execute.
func (cpm *CPM) LoadBinary(filename string) error {
Expand Down Expand Up @@ -639,11 +621,6 @@ func (cpm *CPM) fixupRAM() {
// and executed at a higher address than the default of 0x0100.
func (cpm *CPM) LoadCCP() error {

// Show a startup-banner.
if !cpm.GetQuiet() {
fmt.Printf("\ncpmulator %s loaded CCP %s, with %s output driver\n", cpmver.GetVersionString(), cpm.GetCCPName(), cpm.GetOutputDriver())
}

// Create 64K of memory, full of NOPs
if cpm.Memory == nil {
cpm.Memory = new(memory.Memory)
Expand Down Expand Up @@ -694,7 +671,7 @@ func (cpm *CPM) Execute(args []string) error {
//
// This is only required when running the CCP, as there we're persistent.
for fcb, obj := range cpm.files {
cpm.Logger.Debug("Closing handle in FileCache",
slog.Debug("Closing handle in FileCache",
slog.String("path", obj.name),
slog.Int("fcb", int(fcb)))
obj.handle.Close()
Expand Down Expand Up @@ -822,7 +799,7 @@ func (cpm *CPM) Execute(args []string) error {
//
if !exists {

cpm.Logger.Error("Unimplemented BDOS Syscall",
slog.Error("Unimplemented BDOS Syscall",
slog.Int("syscall", int(syscall)),
slog.String("syscallHex",
fmt.Sprintf("0x%02X", syscall)),
Expand All @@ -838,19 +815,12 @@ func (cpm *CPM) Execute(args []string) error {
fmt.Printf("%03d %s\n", syscall, handler.Desc)
}

cpm.Logger.Info("BDOS",
slog.Info("BDOS",
slog.String("name", handler.Desc),
slog.Int("syscall", int(syscall)),
slog.String("syscallHex", fmt.Sprintf("0x%02X", syscall)),
slog.Group("registers",
slog.String("A", fmt.Sprintf("%02X", cpm.CPU.States.AF.Hi)),
slog.String("B", fmt.Sprintf("%02X", cpm.CPU.States.BC.Hi)),
slog.String("C", fmt.Sprintf("%02X", cpm.CPU.States.BC.Lo)),
slog.String("D", fmt.Sprintf("%02X", cpm.CPU.States.DE.Hi)),
slog.String("E", fmt.Sprintf("%02X", cpm.CPU.States.DE.Lo)),
slog.String("F", fmt.Sprintf("%02X", cpm.CPU.States.AF.Lo)),
slog.String("H", fmt.Sprintf("%02X", cpm.CPU.States.HL.Hi)),
slog.String("L", fmt.Sprintf("%02X", cpm.CPU.States.HL.Lo)),
slog.String("AF", fmt.Sprintf("%04X", cpm.CPU.States.AF.U16())),
slog.String("BC", fmt.Sprintf("%04X", cpm.CPU.States.BC.U16())),
slog.String("DE", fmt.Sprintf("%04X", cpm.CPU.States.DE.U16())),
slog.String("HL", fmt.Sprintf("%04X", cpm.CPU.States.HL.U16()))))
Expand Down Expand Up @@ -951,7 +921,7 @@ func (cpm *CPM) SetDrivePath(drive string, path string) {
//
// This is called by our embedded Z80 emulator.
func (cpm *CPM) In(addr uint8) uint8 {
cpm.Logger.Debug("I/O IN",
slog.Debug("I/O IN",
slog.Int("port", int(addr)))

return 0
Expand Down
Loading

0 comments on commit b6a172a

Please sign in to comment.