mirror of
https://github.com/JetSetIlly/Gopher2600.git
synced 2024-06-02 20:18:20 -04:00
added stats server option to debug and play mode
package from https://github.com/go-echarts/statsview
This commit is contained in:
parent
8d85624023
commit
3880066322
BIN
.screenshots/statsserver_debug.png
Normal file
BIN
.screenshots/statsserver_debug.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 135 KiB |
84
README.md
84
README.md
|
@ -24,6 +24,65 @@ The graphical [debugger](#debugger) is still in development but the current feat
|
|||
<img src=".screenshots/games/krull.png" height="200" alt="krull"/> <img src=".screenshots/games/ladybug.png" height="200" alt="ladybug"/>
|
||||
<img src=".screenshots/games/thrust.png" height="200" alt="thrust"/> <img src=".screenshots/games/pandachase.png" height="200" alt="panda chase"/> <img src=".screenshots/games/mangoesdown.png" height="200" alt="man goes down"/> <img src=".screenshots/games/beast.png" height="200" alt="legacy of the beast"/> <img src=".screenshots/games/chiphead.png" height="200" alt="chiphead"/> <img src=".screenshots/games/genesis.png" height="200" alt="egypt genesis"/>
|
||||
|
||||
## Scope of the project
|
||||
|
||||
`Gopher2600` was started as for fun and educational purposes, as way of
|
||||
learning more about the `Atari 2600` and also about the
|
||||
[Go programming language](https://golang.org/).
|
||||
|
||||
The original intent was to provide a tool for static analysis of a 6507
|
||||
program. I soon realised that I would need to emulate more and more of the
|
||||
2600 and not just the CPU. Eventually, I realised I would also need a way of see the
|
||||
video output from the TIA. At this point it became obvious that I was indeed
|
||||
writing a complete 2600 emulator.
|
||||
|
||||
Because of its origins, any flaws or limitations in the design should be borne
|
||||
in mind while the project is still in development. I am open to any suggestions
|
||||
on how to improve the project.
|
||||
|
||||
### Self-reflection
|
||||
|
||||
There are some design decisions that would perhaps be made differently if I had
|
||||
known where the program was going. For instance, because the project was a way
|
||||
of learning a new programming language I chose to implement my own "database"
|
||||
to [store regression test information](#regression-database). A more natural
|
||||
choice would be to use SQlite but actually the current solution works quite
|
||||
well.
|
||||
|
||||
A couple of packages may well be useful in other projects. The `prefs` package
|
||||
is quite versatile. With a bit of work it could be generalised and put to use
|
||||
in other projects. I think though, this package is a natural candidate to be
|
||||
rewritten with type parameters. Not yet available in Go but scheduled for
|
||||
release in 2022.
|
||||
|
||||
I would also replace the `commandline` package. It works quite nicely but as
|
||||
you would expect from a home-baked solution there are limitations to the
|
||||
parser. It should be rewritten with `flex` & `yacc`.
|
||||
|
||||
### Performance
|
||||
|
||||
The development machine for `Gopher2600` was an i3-3225 with 16GB of RAM. Host
|
||||
operating system throughout the development has been a GNU/Linux system.
|
||||
|
||||
In playmode I can get a sustained frame rate of 60fps. However, video output is
|
||||
not properly vsynced and the audio buffer is not handled very well, sometimes
|
||||
running out of bits, resulting in pops and stutters in the sound.
|
||||
|
||||
In debug mode, I can get around 35fps - good enough for development work.
|
||||
|
||||
To get a performance rating for your installation you can run the following:
|
||||
|
||||
> gopher2600 performance -display -fpscap=false
|
||||
|
||||
Which gives the maximum frame rate with the display.
|
||||
|
||||
Memory usage is around 40MB of system memory in playmode and around 120MB in
|
||||
debug mode. This can vary on the ROM used however. It shouldn't ever be a
|
||||
problem on modern hardware.
|
||||
|
||||
A `statsview` is also available. See the section below on [Statistics Viewer](#statistics-viewer) for
|
||||
details.
|
||||
|
||||
## Compilation
|
||||
|
||||
The project has most recently been tested with Go v1.15. Earlier versions may work
|
||||
|
@ -407,7 +466,7 @@ This area of the emulation will be expanded upon in the future.
|
|||
* M-Network (E7)
|
||||
* DPC
|
||||
|
||||
In also supports the `Supercharger` format in both the `.bin` format and is also able to load from an `MP3` recording of the supercharger tape.
|
||||
In also supports the [Supercharger](#supercharger-roms) format in both the `.bin` format and is also able to load from an `MP3` recording of the supercharger tape.
|
||||
|
||||
Modern formats supported:
|
||||
|
||||
|
@ -418,6 +477,25 @@ Modern formats supported:
|
|||
|
||||
The `DPC+` is supported but the emulator does not currently emulate the `ARM7` present in the `Harmony` cartridge. This is planned for the future.
|
||||
|
||||
## Statistics Viewer
|
||||
|
||||
Playmode and debug mode can both be launched with a statistics viewer available
|
||||
locally on your machine `localhost:12600/debug/statsview`.
|
||||
|
||||
> gopher2600 -statsserver <rom>
|
||||
|
||||
> gopher2600 debug -statsserver <rom>
|
||||
|
||||
The screen below shows an example of the available statistics. In this
|
||||
instance, this is the debugger running a 4k Atari cartridge (specifically,
|
||||
Pitfall).
|
||||
|
||||
<img src=".screenshots/statsserver_debug.png" width="600" alt="stats server example charts (for the debugger)"/>
|
||||
|
||||
For people who really want to dig deep into the running program,
|
||||
`localhost:12600/debug/pprof/` gives more raw, but still useful
|
||||
information.
|
||||
|
||||
## Gopher2600 Tools
|
||||
|
||||
See the https://github.com/JetSetIlly/Gopher2600-Utils/ repository for examples of tools
|
||||
|
@ -500,6 +578,10 @@ The following projects are used in the `Gopher2600` project:
|
|||
* https://github.com/hajimehoshi/go-mp3
|
||||
* https://github.com/pkg/term
|
||||
|
||||
Stats server provided by:
|
||||
|
||||
* https://github.com/go-echarts/statsview
|
||||
|
||||
For testing instrumentation:
|
||||
|
||||
* https://github.com/bradleyjkemp/memviz v0.2.3
|
||||
|
|
1
go.mod
1
go.mod
|
@ -7,6 +7,7 @@ go 1.15
|
|||
//replace github.com/inkyblackness/imgui-go/v2 v2.5.0 => /home/steve/Go/steve_forks/imgui-go
|
||||
|
||||
require (
|
||||
github.com/go-echarts/statsview v0.3.0
|
||||
github.com/bradleyjkemp/memviz v0.2.3
|
||||
github.com/go-audio/audio v1.0.0
|
||||
github.com/go-audio/wav v1.0.0
|
||||
|
|
13
go.sum
13
go.sum
|
@ -15,6 +15,10 @@ github.com/go-audio/riff v1.0.0 h1:d8iCGbDvox9BfLagY94fBynxSPHO80LmZCaOsmKxokA=
|
|||
github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
|
||||
github.com/go-audio/wav v1.0.0 h1:WdSGLhtyud6bof6XHL28xKeCQRzCV06pOFo3LZsFdyE=
|
||||
github.com/go-audio/wav v1.0.0/go.mod h1:3yoReyQOsiARkvPl3ERCi8JFjihzG6WhjYpZCf5zAWE=
|
||||
github.com/go-echarts/go-echarts/v2 v2.2.2 h1:GRx69WvDwbXkYW11Z5JaDLEkUwypqcLyms8A8n1JWC0=
|
||||
github.com/go-echarts/go-echarts/v2 v2.2.2/go.mod h1:6TOomEztzGDVDkOSCFBq3ed7xOYfbOqhaBzD0YV771A=
|
||||
github.com/go-echarts/statsview v0.3.0 h1:RTa3DjHnBP2rH2wk8/1HZH71NjznAeVF5dSU/0tZtEg=
|
||||
github.com/go-echarts/statsview v0.3.0/go.mod h1:MVu0ODAoc/gwQ4wv09+Ev+4O2GghebSMN0vk1WkHTe8=
|
||||
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw=
|
||||
github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.1 h1:pn/SKU1+/rfK8KaZXdGEC2G/KCB2aLRjbTCrwKcokao=
|
||||
|
@ -30,13 +34,19 @@ github.com/inkyblackness/imgui-go/v2 v2.5.0 h1:kz7oO/di/TmxHKgh5So+RyOgWMtK4jLfG
|
|||
github.com/inkyblackness/imgui-go/v2 v2.5.0/go.mod h1:cwQKd6U2onyuT5qwSC3DKCRsUE1SQ58TSVVpLoW/pDs=
|
||||
github.com/inkyblackness/imgui-go/v2 v2.5.1-0.20200909052151-c2b62c6be2a7 h1:rYHbANjC8SF9JP7n85+f9tgUm8Akvdc7wUhLDA0Whj4=
|
||||
github.com/inkyblackness/imgui-go/v2 v2.5.1-0.20200909052151-c2b62c6be2a7/go.mod h1:cwQKd6U2onyuT5qwSC3DKCRsUE1SQ58TSVVpLoW/pDs=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942 h1:A7GG7zcGjl3jqAqGPmcNjd/D9hzL95SuoOQAaFNdLU0=
|
||||
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
||||
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/veandco/go-sdl2 v0.4.1 h1:HmSBvVmKWI8LAOeCfTTM8R33rMyPcs6U3o8n325c9Qg=
|
||||
github.com/veandco/go-sdl2 v0.4.1/go.mod h1:FB+kTpX9YTE+urhYiClnRzpOXbiWgaU3+5F2AB78DPg=
|
||||
github.com/veandco/go-sdl2 v0.4.4 h1:coOJGftOdvNvGoUIZmm4XD+ZRQF4mg9ZVHmH3/42zFQ=
|
||||
|
@ -47,3 +57,6 @@ golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCc
|
|||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
@ -24,6 +24,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-echarts/statsview"
|
||||
"github.com/go-echarts/statsview/viewer"
|
||||
"github.com/jetsetilly/gopher2600/cartridgeloader"
|
||||
"github.com/jetsetilly/gopher2600/debugger"
|
||||
"github.com/jetsetilly/gopher2600/debugger/terminal"
|
||||
|
@ -270,6 +272,7 @@ func play(md *modalflag.Modes, sync *mainSync) error {
|
|||
hiscore := md.AddBool("hiscore", false, "contact hiscore server [EXPERIMENTAL]")
|
||||
log := md.AddBool("log", false, "echo debugging log to stdout")
|
||||
useSavekey := md.AddBool("savekey", false, "use savekey in player 1 port")
|
||||
statsServer := md.AddBool("statsserver", false, fmt.Sprintf("run stats server (%s)", statsServerAddress))
|
||||
|
||||
p, err := md.Parse()
|
||||
if err != nil || p != modalflag.ParseContinue {
|
||||
|
@ -283,6 +286,10 @@ func play(md *modalflag.Modes, sync *mainSync) error {
|
|||
logger.SetEcho(nil)
|
||||
}
|
||||
|
||||
if *statsServer {
|
||||
launchStatsServer()
|
||||
}
|
||||
|
||||
switch len(md.RemainingArgs()) {
|
||||
case 0:
|
||||
return fmt.Errorf("2600 cartridge required for %s mode", md)
|
||||
|
@ -382,12 +389,17 @@ func debug(md *modalflag.Modes, sync *mainSync) error {
|
|||
initScript := md.AddString("initscript", defInitScript, "script to run on debugger start")
|
||||
profile := md.AddBool("profile", false, "run debugger through cpu profiler")
|
||||
useSavekey := md.AddBool("savekey", false, "use savekey in player 1 port")
|
||||
statsServer := md.AddBool("statsserver", false, fmt.Sprintf("run stats server (%s)", statsServerAddress))
|
||||
|
||||
p, err := md.Parse()
|
||||
if err != nil || p != modalflag.ParseContinue {
|
||||
return err
|
||||
}
|
||||
|
||||
if *statsServer {
|
||||
launchStatsServer()
|
||||
}
|
||||
|
||||
tv, err := television.NewTelevision(*spec)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -889,3 +901,17 @@ type nopWriter struct{}
|
|||
func (*nopWriter) Write(p []byte) (n int, err error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
const statsServerAddress = "localhost:12600"
|
||||
const statsServerURL = "/debug/statsview"
|
||||
|
||||
// launch a goroutine running the stats viewer https://github.com/go-echarts/statsview
|
||||
func launchStatsServer() {
|
||||
go func() {
|
||||
viewer.SetConfiguration(viewer.WithAddr(statsServerAddress))
|
||||
mgr := statsview.New()
|
||||
mgr.Start()
|
||||
}()
|
||||
|
||||
fmt.Printf("stats server available at %s%s\n", statsServerAddress, statsServerURL)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue