Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement support for the RunCPM-Specific function F_UPTIME #159

Merged
merged 1 commit into from
Nov 9, 2024
Merged
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 cpm/cpm.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"os"
"path/filepath"
"strings"
"time"

"github.com/koron-go/z80"
"github.com/skx/cpmulator/ccp"
Expand Down Expand Up @@ -189,6 +190,9 @@ type CPM struct {
// For real debugging we expect the caller to use our Logger, via
// the logfile
simpleDebug bool

// launchTime is the time at which the application was launched
launchTime time.Time
}

// ccpoption defines a config-setting option for our constructor.
Expand Down Expand Up @@ -426,6 +430,11 @@ func New(options ...cpmoption) (*CPM, error) {
Handler: BdosSysCallDirectScreenFunctions,
Fake: true,
}
bdos[248] = CPMHandler{ // used by BBC BASIC v5
Desc: "F_UPTIME",
Handler: BdosSysCallUptime,
Fake: true,
}

//
// Create and populate our syscall table for the BIOS syscalls.
Expand Down Expand Up @@ -504,6 +513,7 @@ func New(options ...cpmoption) (*CPM, error) {
output: driver, // default
prnPath: "printer.log", // default
start: 0x0100,
launchTime: time.Now(),
}

// Allow options to override our defaults
Expand Down
20 changes: 20 additions & 0 deletions cpm/cpm_bdos.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"path/filepath"
"sort"
"strings"
"time"

"github.com/skx/cpmulator/consolein"
"github.com/skx/cpmulator/fcb"
Expand Down Expand Up @@ -1675,3 +1676,22 @@ func BdosSysCallTime(cpm *CPM) error {
func BdosSysCallDirectScreenFunctions(cpm *CPM) error {
return nil
}

// BdosSysCallUptime returns the number of "ticks" since the system
// was booted, it is a custom syscall which is implemented by RunCPM
// which we implement for compatibility, notable users include v5
// of BBC BASIC.
func BdosSysCallUptime(cpm *CPM) error {

// Get elapsed time, since startup
elapsed := time.Since(cpm.launchTime)

// In nanoseconds
timer := elapsed.Nanoseconds()

// Set it.
cpm.CPU.States.HL.SetU16(uint16(timer & 0xFFFF))
cpm.CPU.States.DE.SetU16(uint16((timer >> 16) & 0xFFFF))

return nil
}
37 changes: 37 additions & 0 deletions cpm/cpm_bdos_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"os"
"testing"
"time"

"github.com/skx/cpmulator/consolein"
"github.com/skx/cpmulator/fcb"
Expand Down Expand Up @@ -1286,3 +1287,39 @@ func TestRead(t *testing.T) {
}

}

func TestTicks(t *testing.T) {

// Create a new helper
c, err := New()
if err != nil {
t.Fatalf("failed to create CPM")
}

// Ensure we have a launch time that was in the past.
if !c.launchTime.Before(time.Now()) {
t.Fatalf("time travel isn't possible")
}

// Call the function
err = BdosSysCallUptime(c)
if err != nil {
t.Fatalf("unexpected error getting ticks")
}

// Get the before time.
a := c.CPU.States.HL.U16()

// Call the function
err = BdosSysCallUptime(c)
if err != nil {
t.Fatalf("unexpected error getting ticks")
}

// Get the after time.
b := c.CPU.States.HL.U16()

if a == b {
t.Fatalf("no time has passed %d %d", a, b)
}
}
Loading