From 71ea4bd733c5174c0e517ce0a2870066eabbdc9a Mon Sep 17 00:00:00 2001 From: Ivan Izaguirre Date: Fri, 1 Nov 2024 21:35:20 +0100 Subject: [PATCH] Show speed on screen --- apple2.go | 7 +++- apple2Run.go | 5 ++- command.go | 2 +- frontend/a2ebiten/ebitenKeyboard.go | 15 +++++--- frontend/a2ebiten/ebitenSpeaker.go | 5 --- frontend/a2ebiten/main.go | 53 ++++++++++++++++++++++++----- go.mod | 1 + go.sum | 2 ++ 8 files changed, 68 insertions(+), 22 deletions(-) diff --git a/apple2.go b/apple2.go index 358be2c..73cef32 100644 --- a/apple2.go +++ b/apple2.go @@ -34,11 +34,12 @@ type Apple2 struct { cycleBreakpoint uint64 breakPoint bool profile bool - showSpeed bool paused bool cpuTrace bool forceCaps bool removableMediaDrives []drive + + currentFreqMHz float64 } // GetCards returns the array of inserted cards @@ -75,6 +76,10 @@ func (a *Apple2) GetCycles() uint64 { return a.cycles } +func (a *Apple2) GetCurrentFreqMHz() float64 { + return a.currentFreqMHz +} + // SetCycleBreakpoint sets a cycle number to pause the emulator. 0 to disable func (a *Apple2) SetCycleBreakpoint(cycle uint64) { a.cycleBreakpoint = cycle diff --git a/apple2Run.go b/apple2Run.go index 0c676dd..e7c7190 100644 --- a/apple2Run.go +++ b/apple2Run.go @@ -116,12 +116,11 @@ func (a *Apple2) Start(paused bool) { } } - if a.showSpeed && a.cycles-speedReferenceCycles > 1000000 { + if a.cycles-speedReferenceCycles > 1000000 { // Calculate speed in MHz every million cycles newTime := time.Now() elapsedCycles := float64(a.cycles - speedReferenceCycles) - freq := 1000.0 * elapsedCycles / float64(newTime.Sub(speedReferenceTime).Nanoseconds()) - fmt.Printf("Freq: %f Mhz\n", freq) + a.currentFreqMHz = 1000.0 * elapsedCycles / float64(newTime.Sub(speedReferenceTime).Nanoseconds()) speedReferenceTime = newTime speedReferenceCycles = a.cycles } diff --git a/command.go b/command.go index 05252e1..96f2edb 100644 --- a/command.go +++ b/command.go @@ -77,7 +77,7 @@ func (a *Apple2) executeCommand(command command) { a.cycleDurationNs = 0 } case CommandShowSpeed: - a.showSpeed = !a.showSpeed + fmt.Printf("Freq: %f Mhz\n", a.currentFreqMHz) case CommandDumpDebugInfo: a.dumpDebugInfo() case CommandNextCharGenPage: diff --git a/frontend/a2ebiten/ebitenKeyboard.go b/frontend/a2ebiten/ebitenKeyboard.go index e698d16..9c2873c 100644 --- a/frontend/a2ebiten/ebitenKeyboard.go +++ b/frontend/a2ebiten/ebitenKeyboard.go @@ -18,7 +18,10 @@ type ebitenKeyboard struct { showPages bool showCharGen bool showAltText bool + showFreq bool screenMode int + + debug bool } func newEbitenKeyBoard(a *izapple2.Apple2) *ebitenKeyboard { @@ -33,14 +36,18 @@ func newEbitenKeyBoard(a *izapple2.Apple2) *ebitenKeyboard { func (k *ebitenKeyboard) update() { runes := ebiten.AppendInputChars(nil) if len(runes) > 0 { - fmt.Println("Runes: ", string(runes)) + if k.debug { + fmt.Println("Runes: ", string(runes)) + } k.putText(string(runes)) } keys := inpututil.AppendJustPressedKeys(nil) for _, key := range keys { - s := key.String() - fmt.Println("Key pressed: ", s) + if k.debug { + s := key.String() + fmt.Println("Key pressed: ", s) + } k.putKey(key) } } @@ -115,7 +122,7 @@ func (k *ebitenKeyboard) putKey(key ebiten.Key) { k.a.SendCommand(izapple2.CommandToggleCPUTrace) case ebiten.KeyF5: if ctrl { - k.a.SendCommand(izapple2.CommandShowSpeed) + k.showFreq = !k.showFreq } else { k.a.SendCommand(izapple2.CommandToggleSpeed) } diff --git a/frontend/a2ebiten/ebitenSpeaker.go b/frontend/a2ebiten/ebitenSpeaker.go index 17f52b9..34bd9cd 100644 --- a/frontend/a2ebiten/ebitenSpeaker.go +++ b/frontend/a2ebiten/ebitenSpeaker.go @@ -84,11 +84,7 @@ func (s *ebitenSpeaker) Read(buf []byte) (n int, err error) { // Build wave const bytesPerSample = 8 // Two floats32, 4 bytes each, one for each channel samples := len(buf) / bytesPerSample - //fmt.Printf("smples: %v\n", smples) - if len(s.pendingClicks) > 0 { - fmt.Printf("pendingClicks: %v\n", len(s.pendingClicks)) - } var i, r int level := s.lastLevel for p := 0; p < len(s.pendingClicks); p++ { @@ -125,7 +121,6 @@ func (s *ebitenSpeaker) Read(buf []byte) (n int, err error) { // If the buffer is empty lets stop the signal if i == 0 && level != 0.0 { level = 0.0 - fmt.Printf("Speaker buffer empty, to zero.\n") } // Complete the buffer if needed diff --git a/frontend/a2ebiten/main.go b/frontend/a2ebiten/main.go index d305156..55df461 100644 --- a/frontend/a2ebiten/main.go +++ b/frontend/a2ebiten/main.go @@ -1,31 +1,42 @@ package main import ( + "bytes" "fmt" "image" + "image/color" "github.com/ivanizag/izapple2" a_screen "github.com/ivanizag/izapple2/screen" "github.com/hajimehoshi/ebiten/v2" + "github.com/hajimehoshi/ebiten/v2/examples/resources/fonts" + "github.com/hajimehoshi/ebiten/v2/text/v2" "github.com/pkg/profile" ) type Game struct { - a *izapple2.Apple2 - image *ebiten.Image - keyboard *ebitenKeyboard - speaker *ebitenSpeaker + a *izapple2.Apple2 + image *ebiten.Image + keyboard *ebitenKeyboard + speaker *ebitenSpeaker + fontSource *text.GoTextFaceSource paused bool title string + + updates uint64 + freq float64 } const ( virtualWidth = 1128 virtualHeight = 768 + hudFontSize = 50 ) +var hudColor = color.RGBA{208, 241, 141, 255} // Yellow + func (g *Game) Update() error { g.keyboard.update() g.speaker.update() @@ -39,7 +50,7 @@ func (g *Game) Update() error { g.paused = g.a.IsPaused() } - if !g.a.IsPaused() { + if g.updates%3 == 0 && !g.a.IsPaused() { // 20 times per second var img *image.RGBA vs := g.a.GetVideoSource() if g.keyboard.showHelp { @@ -59,6 +70,11 @@ func (g *Game) Update() error { } } + if g.updates%60 == 0 { // Once per second + g.freq = g.a.GetCurrentFreqMHz() + } + + g.updates++ return nil } @@ -72,6 +88,18 @@ func (g *Game) Draw(screen *ebiten.Image) { screen.DrawImage(g.image, op) } + + if g.keyboard.showFreq { + msg := fmt.Sprintf("%0.2f Hz, FPS %0.0f", g.freq, ebiten.ActualFPS()) + op := &text.DrawOptions{} + op.GeoM.Translate(20, 20) + op.ColorScale.ScaleWithColor(hudColor) + text.Draw(screen, msg, &text.GoTextFace{ + Source: g.fontSource, + Size: hudFontSize, + }, op) + + } } func (g *Game) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) { @@ -101,16 +129,20 @@ func ebitenRun(a *izapple2.Apple2) { title := "iz-" + a.Name + " (F1 for help)" ebiten.SetWindowTitle(title) - go a.Run() - game := &Game{ a: a, keyboard: newEbitenKeyBoard(a), speaker: newEbitenSpeaker(), } - a.SetSpeakerProvider(game.speaker) + var err error + game.fontSource, err = text.NewGoTextFaceSource(bytes.NewReader(fonts.MPlus1pRegular_ttf)) + if err != nil { + panic(err) + } + + go a.Run() if err := ebiten.RunGame(game); err != nil { fmt.Printf("Error: %v\n", err) } @@ -140,3 +172,8 @@ side of the window to load a disk Run izapple2 -h for more options https://github.com/ivanizag/izapple2 ` + +/* +To test the WebAssembly version, run: + go run github.com/hajimehoshi/wasmserve@latest . +*/ diff --git a/go.mod b/go.mod index 858e24e..b109a29 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/ebitengine/hideconsole v1.0.0 // indirect github.com/ebitengine/oto/v3 v3.3.1 // indirect github.com/ebitengine/purego v0.8.0 // indirect + github.com/go-text/typesetting v0.2.0 // indirect github.com/jezek/xgb v1.1.1 // indirect golang.org/x/sync v0.8.0 // indirect gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b // indirect diff --git a/go.sum b/go.sum index 09ff594..52883d2 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211024062804-40e447a793be/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240118000515-a250818d05e3 h1:nanQfMsOs3gnuKRm0E5jXWomedE/9YIFXdmHJNZYeqc= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240118000515-a250818d05e3/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-text/typesetting v0.2.0 h1:fbzsgbmk04KiWtE+c3ZD4W2nmCRzBqrqQOvYlwAOdho= +github.com/go-text/typesetting v0.2.0/go.mod h1:2+owI/sxa73XA581LAzVuEBZ3WEEV2pXeDswCH/3i1I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=