diff --git a/config/config.go b/config/config.go index 1b049f0..cd0e23c 100644 --- a/config/config.go +++ b/config/config.go @@ -7,8 +7,8 @@ import ( "gopkg.in/yaml.v3" ) -const defaultMonitorFile = "okean240/MON_r6.BIN" -const defaultCPMFile = "okean240/CPM_r7.BIN" +const defaultMonitorFile = "rom/MON_v5.bin" +const defaultCPMFile = "rom/CPM_v5.bin" type OkEmuConfig struct { LogFile string `yaml:"logFile"` diff --git a/go.mod b/go.mod index 1ec5960..09f0b4a 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module z80em +module okemu go 1.25 @@ -7,4 +7,38 @@ require ( gopkg.in/yaml.v3 v3.0.1 ) -require golang.org/x/sys v0.13.0 // indirect +require ( + fyne.io/fyne/v2 v2.7.3 // indirect + fyne.io/systray v1.12.0 // indirect + github.com/BurntSushi/toml v1.5.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/fredbi/uri v1.1.1 // indirect + github.com/fsnotify/fsnotify v1.9.0 // indirect + github.com/fyne-io/gl-js v0.2.0 // indirect + github.com/fyne-io/glfw-js v0.3.0 // indirect + github.com/fyne-io/image v0.1.1 // indirect + github.com/fyne-io/mobile v0.1.2 // indirect + github.com/fyne-io/oksvg v0.2.0 // indirect + github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect + github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect + github.com/go-text/render v0.2.0 // indirect + github.com/go-text/typesetting v0.3.3 // indirect + github.com/godbus/dbus/v5 v5.1.0 // indirect + github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff // indirect + github.com/hack-pad/go-indexeddb v0.3.2 // indirect + github.com/hack-pad/safejs v0.1.0 // indirect + github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect + github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect + github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect + github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rymdport/portal v0.4.2 // indirect + github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect + github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect + github.com/stretchr/testify v1.11.1 // indirect + github.com/yuin/goldmark v1.7.8 // indirect + golang.org/x/image v0.24.0 // indirect + golang.org/x/net v0.35.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect +) diff --git a/go.sum b/go.sum index 63fc67a..d159b5f 100644 --- a/go.sum +++ b/go.sum @@ -1,14 +1,138 @@ +fyne.io/fyne v1.4.3 h1:356CnXCiYrrfaLGsB7qLK3c6ktzyh8WR05v/2RBu51I= +fyne.io/fyne v1.4.3/go.mod h1:8kiPBNSDmuplxs9WnKCkaWYqbcXFy0DeAzwa6PBO9Z8= +fyne.io/fyne/v2 v2.7.3 h1:xBT/iYbdnNHONWO38fZMBrVBiJG8rV/Jypmy4tVfRWE= +fyne.io/fyne/v2 v2.7.3/go.mod h1:gu+dlIcZWSzKZmnrY8Fbnj2Hirabv2ek+AKsfQ2bBlw= +fyne.io/systray v1.12.0 h1:CA1Kk0e2zwFlxtc02L3QFSiIbxJ/P0n582YrZHT7aTM= +fyne.io/systray v1.12.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= +github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= +github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I= +github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fredbi/uri v1.1.1 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko= +github.com/fredbi/uri v1.1.1/go.mod h1:4+DZQ5zBjEwQCDmXW5JdIjz0PUA+yJbvtBv+u+adr5o= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs= +github.com/fyne-io/gl-js v0.2.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI= +github.com/fyne-io/glfw-js v0.3.0 h1:d8k2+Y7l+zy2pc7wlGRyPfTgZoqDf3AI4G+2zOWhWUk= +github.com/fyne-io/glfw-js v0.3.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk= +github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA= +github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM= +github.com/fyne-io/mobile v0.1.2 h1:0HaXDtOOwyOTn3Umi0uKVCOgJtfX73c6unC4U8i5VZU= +github.com/fyne-io/mobile v0.1.2/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY= +github.com/fyne-io/oksvg v0.2.0 h1:mxcGU2dx6nwjJsSA9PCYZDuoAcsZ/OuJlvg/Q9Njfo8= +github.com/fyne-io/oksvg v0.2.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI= +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/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA= +github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3 h1:q521PfSp5/z6/sD9FZZOWj4d1MLmfQW8PkRnI9M6PCE= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc= +github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU= +github.com/go-text/typesetting v0.3.3 h1:ihGNJU9KzdK2QRDy1Bm7FT5RFQoYb+3n3EIhI/4eaQc= +github.com/go-text/typesetting v0.3.3/go.mod h1:vIRUT25mLQaSh4C8H/lIsKppQz/Gdb8Pu/tNwpi52ts= +github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= +github.com/godbus/dbus/v5 v5.0.3/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= +github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8= +github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw= +github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A= +github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0= +github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8= +github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio= +github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc= +github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE= +github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o= +github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE= +github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M= +github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw= +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/lucor/goinfo v0.0.0-20200401173949-526b5363a13a/go.mod h1:ORP3/rB5IsulLEBwQZCJyyV6niqmI7P4EWSmkug+1Ng= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= +github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= +github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk= +github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU= +github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 h1:HunZiaEKNGVdhTRQOVpMmj5MQnGnv+e8uZNu3xFLgyM= +github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4= +github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= +github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= +github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 h1:m59mIOBO4kfcNCEzJNy71UkeF4XIx2EVmL9KLwDQdmM= +github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU= +github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= +github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= +github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= +golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= +golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/logger/logger.go b/logger/logger.go index f3fd979..29dcec5 100644 --- a/logger/logger.go +++ b/logger/logger.go @@ -3,6 +3,7 @@ package logger import ( "bufio" "fmt" + "okemu/config" "os" "path/filepath" "strconv" @@ -53,7 +54,7 @@ func FlushLogs() { } // ReconfigureLogging Reconfigure logging by config values -func ReconfigureLogging(config *config.ServiceConfig) { +func ReconfigureLogging(config *config.OkEmuConfig) { // redirect logging if log file specified if len(config.LogFile) > 0 { var err error diff --git a/main.go b/main.go index c9271b4..dc746e7 100644 --- a/main.go +++ b/main.go @@ -1,9 +1,18 @@ package main import ( - "z80em/config" - "z80em/logger" - "z80em/okean240" + "fmt" + "image/color" + "okemu/config" + "okemu/logger" + "okemu/okean240" + "time" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/app" + "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/widget" ) var Version = "v1.0.0" @@ -20,10 +29,89 @@ func main() { conf := config.GetConfig() // Reconfigure logging by config values - logger.ReconfigureLogging(conf) + //logger.ReconfigureLogging(conf) - println("Init computer") - computer := okean240.New(config) - println("Run computer") - computer.Run() + emuapp := app.New() + w := emuapp.NewWindow("Океан 240.2") + + computer := okean240.New(conf) + + label := widget.NewLabel(fmt.Sprintf("Screen size: %dx%d", computer.ScreenWidth(), computer.ScreenHeight())) + + raster := canvas.NewRasterWithPixels( + func(x, y, w, h int) color.Color { + return computer.GetPixel(uint16(x/2), uint16(y/2)) + }) + raster.Resize(fyne.NewSize(512, 512)) + raster.SetMinSize(fyne.NewSize(512, 512)) + w.Resize(fyne.NewSize(600, 600)) + + hBox := container.NewHBox( + widget.NewButton("Reset", func() { + computer.Reset() + }), + widget.NewButton("Закрыть", func() { + emuapp.Quit() + }), + ) + vBox := container.NewVBox( + raster, + label, + hBox, + ) + w.SetContent(vBox) + + go emulator(computer, raster, label) + + w.ShowAndRun() + + //println("Tick computer") + //computer := okean240.New(conf) + //println("Run computer") + //computer.Run() +} + +const TicksPerFrame = 20_000_000 / 133 + +func emulator(computer *okean240.ComputerType, raster *canvas.Raster, label *widget.Label) { + ticker := time.NewTicker(133 * time.Nanosecond) + var ticks = 0 + var ticksCPU = 3 + //var ticksSCR = TicksPerFrame + //var frameStartTime = time.Now().UnixMicro() + frameNextTime := time.Now().UnixMicro() + 20000 + frame := 0 + curScrWidth := 256 + for range ticker.C { + ticks++ + if ticks%5 == 0 { + // 1.5 MHz + computer.TimerClk() + } + if ticks > ticksCPU { + ticksCPU = ticks + computer.Do()*3 + } + + //if ticks >= ticksSCR { + if time.Now().UnixMicro() > frameNextTime { + frameNextTime = time.Now().UnixMicro() + 20000 + //ticksSCR = ticks + TicksPerFrame + frame++ + // redraw screen here + fyne.Do(func() { + // check for screen mode changed + if computer.ScreenWidth() != curScrWidth { + curScrWidth = computer.ScreenWidth() + newSize := fyne.NewSize(float32(curScrWidth*2), float32(computer.ScreenHeight()*2)) + raster.SetMinSize(newSize) + raster.Resize(newSize) + } + // status for every 25 frames + if frame%25 == 0 { + label.SetText(fmt.Sprintf("Screen size: %dx%d Tick: %d", computer.ScreenWidth(), computer.ScreenHeight(), computer.Cycles())) + } + raster.Refresh() + }) + } + } } diff --git a/okean240/computer.go b/okean240/computer.go index 6be0e2e..2ccb199 100644 --- a/okean240/computer.go +++ b/okean240/computer.go @@ -1,8 +1,9 @@ package okean240 import ( - "z80em/config" - "z80em/z80em" + "image/color" + "okemu/config" + "okemu/z80em" log "github.com/sirupsen/logrus" ) @@ -13,11 +14,27 @@ type ComputerType struct { ioPorts [256]byte cycles uint64 dd17EnableOut bool + colorMode bool + screenWidth int + screenHeight int + vRAM *RamBlock + palette byte + bgColor byte + dd70 *Timer8253 + dd72 *Sio8251 } +const VRAMBlock0 = 3 +const VRAMBlock1 = 7 +const VidVsuBit = 0x80 +const VidColorBit = 0x40 + type ComputerInterface interface { - //Init(rom0 string, rom1 string) Run() + Reset() + GetPixel(x uint16, y uint16) color.RGBA + Do() uint64 + TimerClk() } func (c *ComputerType) M1MemRead(addr uint16) byte { @@ -33,26 +50,69 @@ func (c *ComputerType) MemWrite(addr uint16, val byte) { } func (c *ComputerType) IORead(port uint16) byte { - return c.ioPorts[port] + switch port & 0x00ff { + case PIC_DD75RS: + v := c.ioPorts[PIC_DD75RS] + c.ioPorts[PIC_DD75RS] = 0 + return v + default: + log.Debugf("IORead from port: %x", port) + } + return c.ioPorts[byte(port&0x00ff)] } func (c *ComputerType) IOWrite(port uint16, val byte) { - c.ioPorts[byte(port&0x00ff)] = val - switch byte(port & 0x00ff) { + bp := byte(port & 0x00ff) + c.ioPorts[bp] = val + //log.Debugf("OUT (%x), %x", bp, val) + switch bp { case SYS_DD17PB: - if c.dd17EnableOut { c.memory.Configure(val) } case SYS_DD17CTR: c.dd17EnableOut = val == 0x80 + case VID_DD67PB: + if val&VidVsuBit == 0 { + // video page 0 + c.vRAM = c.memory.allMemory[VRAMBlock0] + } else { + // video page 1 + c.vRAM = c.memory.allMemory[VRAMBlock1] + } + if val&VidColorBit != 0 { + c.colorMode = true + c.screenWidth = 256 + } else { + c.colorMode = false + c.screenWidth = 512 + } + c.palette = val & 0x07 + c.bgColor = val & 0x38 >> 3 + case DD67CTR: + + case TMR_DD70CTR: + // Timer VI63 config register + c.dd70.Configure(val) + case TMR_DD70C1: + // Timer VI63 counter0 register + c.dd70.Load(0, val) + case TMR_DD70C2: + // Timer VI63 counter1 register + c.dd70.Load(1, val) + case TMR_DD70C3: + // Timer VI63 counter2 register + c.dd70.Load(2, val) + case KBD_DD78CTR: + default: + //log.Debugf("OUT to Unknown port (%x), %x", bp, val) } } // New Builds new computer -func New(cfg config.OkEmuConfig) *ComputerType { +func New(cfg *config.OkEmuConfig) *ComputerType { c := ComputerType{} c.memory = Memory{} c.memory.Init(cfg.MonitorFile, cfg.CPMFile) @@ -61,15 +121,109 @@ func New(cfg config.OkEmuConfig) *ComputerType { c.cycles = 0 c.dd17EnableOut = false + c.screenWidth = 512 + c.screenHeight = 256 + c.vRAM = c.memory.allMemory[3] + c.palette = 0 + c.bgColor = 0 + + c.dd70 = NewTimer8253() + c.dd72 = NewSio8251() + return &c } -func (c *ComputerType) Run() { +func (c *ComputerType) Reset() { c.cpu.Reset() - for { - state := c.cpu.GetState() - log.Infof("%d - [%x]: %x\n", c.cycles, state.PC, c.MemRead(state.PC)) - c.cycles += uint64(c.cpu.RunInstruction()) + c.cycles = 0 +} +func (c *ComputerType) Do() int { + s := c.cpu.GetState() + if s.PC == 0xe0db { + log.Debugf("breakpoint") + } + ticks := uint64(c.cpu.RunInstruction()) + c.cycles += ticks + return int(ticks) +} + +func (c *ComputerType) GetPixel(x uint16, y uint16) color.RGBA { + if y > 255 { + return CWhite + } + + var addr uint16 + var resColor color.RGBA + + if c.colorMode { + if x > 255 { + return CWhite + } + // Color 256x256 mode + addr = ((x & 0xf8) << 6) | y + var mask byte = 1 << (x & 0x07) + pix1 := c.vRAM.memory[addr]&(mask) != 0 + pix2 := c.vRAM.memory[addr+0x100]&(mask) != 0 + var cl byte = 0 + if pix1 { + cl |= 1 + } + if pix2 { + cl |= 2 + } + if cl == 0 { + resColor = BgColorPalette[c.bgColor] + } else { + resColor = ColorPalette[c.palette][cl] + } + } else { + if x > 511 { + return CWhite + } + // Mono 512x256 mode + addr = ((x & 0xf8) << 5) | y + pix := c.vRAM.memory[addr]&(1<>14].memory[addr&0x3fff] = val + window := addr >> 14 + offset := addr & 0x3fff + if window == 1 { + //log.Debugf("at vram [%2x][%4x]", window, offset) + } + m.memoryWindow[window].memory[offset] = val } diff --git a/okean240/palette.go b/okean240/palette.go new file mode 100644 index 0000000..1522340 --- /dev/null +++ b/okean240/palette.go @@ -0,0 +1,51 @@ +package okean240 + +import "image/color" + +var CRed = color.RGBA{R: 0xff, G: 0, B: 0, A: 0xff} +var CLGreen = color.RGBA{R: 0x00, G: 0xff, B: 0, A: 0xff} +var CGreen = color.RGBA{R: 0x12, G: 0x76, B: 0x22, A: 0xff} +var CBlue = color.RGBA{R: 0x2A, G: 0x60, B: 0x99, A: 0xff} +var CLBlue = color.RGBA{R: 0x72, G: 0x9F, B: 0xCF, A: 0xff} +var CCrimson = color.RGBA{R: 0x80, G: 0x00, B: 0x80, A: 0xff} +var CWhite = color.RGBA{R: 0xff, G: 0xff, B: 0xff, A: 0xff} +var CYellow = color.RGBA{R: 0xff, G: 0xff, B: 0x00, A: 0xff} +var CBlack = color.RGBA{R: 0, G: 0, B: 0, A: 0xff} + +// R5 - Style Palette +//var ColorPalette = [8][4]color.RGBA{ +// {CBlack, CRed, CGreen, CBlue}, // 000 +// {CWhite, CRed, CGreen, CBlue}, // 001 +// {CRed, CGreen, CLBlue, CYellow}, // 010 +// {CBlack, CRed, CCrimson, CWhite}, // 011 +// {CBlack, CRed, CWhite, CBlue}, // 100 +// {CBlack, CRed, CWhite, CYellow}, // 101 +// {CGreen, CWhite, CYellow, CBlue}, // 110 +// {CBlack, CBlack, CBlack, CBlack}, // 111 +//} + +// ColorPalette R8 style palette +var ColorPalette = [8][4]color.RGBA{ + {CBlack, CGreen, CBlue, CRed}, // 000 + {CWhite, CGreen, CBlue, CRed}, // 001 + {CGreen, CBlue, CCrimson, CLBlue}, // 010 + {CBlack, CGreen, CYellow, CWhite}, // 011 + {CBlack, CGreen, CLBlue, CRed}, // 100 + {CBlack, CRed, CBlue, CLBlue}, // 101 + {CBlue, CWhite, CLBlue, CRed}, // 110 + {CBlack, CBlack, CBlack, CBlack}, // 111 +} + +// BgColorPalette Background color palette +var BgColorPalette = [8]color.RGBA{ + CBlack, CBlue, CGreen, CLBlue, CRed, CCrimson, CYellow, CWhite, +} + +//var MonoPalette = [8]color.RGBA{ +// CWhite, CRed, CGreen, CBlue, CLBlue, CYellow, CLGreen, CBlack, +//} + +// MonoPalette R8 Style monochrome mode palette +var MonoPalette = [8]color.RGBA{ + CRed, CBlue, CCrimson, CGreen, CYellow, CLBlue, CWhite, CBlack, +} diff --git a/okean240/sio8251.go b/okean240/sio8251.go new file mode 100644 index 0000000..47cfdf2 --- /dev/null +++ b/okean240/sio8251.go @@ -0,0 +1,19 @@ +package okean240 + +type Sio8251 struct { + counter uint64 +} + +type Sio8251Interface interface { + Tick() +} + +func NewSio8251() *Sio8251 { + return &Sio8251{ + counter: 0, + } +} + +func (s *Sio8251) Tick() { + s.counter++ +} diff --git a/okean240/tmr8253.go b/okean240/tmr8253.go new file mode 100644 index 0000000..201d503 --- /dev/null +++ b/okean240/tmr8253.go @@ -0,0 +1,148 @@ +package okean240 + +/* + Timer config: [sc1,sc0][rl1,rl0][m2,m1,m0][bcd] + sc - timer, rl=01-LSB, 10-MSB, 11-LSB+MSB + mode 000 - int on fin, + 001 - one shot, + x10 - rate gen, + x11 - sq wave +*/ + +const ( + TimerModeIntOnFin = iota + TimerModeOneShot + TimerModeRateGen + TimerModeSqWave +) + +const ( + TimerRLMsbLsb = iota + TimerRLLsbLsb + TimerRLMsb + TimerRLLsbMsb +) + +type Timer8253Ch struct { + rl byte + mode byte + bcd bool + load uint16 + counter uint16 + fb bool + start bool + fired bool +} +type Timer8253 struct { + //chNo byte + channel [3]Timer8253Ch +} + +type Timer8253Interface interface { + //Init() + Configure(value byte) + Load(chNo int, value byte) + Counter(chNo int) uint16 + Fired(chNo int) bool + Start(chNo int) bool +} + +func NewTimer8253() *Timer8253 { + return &Timer8253{ + //chNo: 0, + channel: [3]Timer8253Ch{ + {0, 0, false, 0, 0, true, false, false}, + {0, 0, false, 0, 0, true, false, false}, + {0, 0, false, 0, 0, true, false, false}, + }, + } +} + +func (t *Timer8253) Tick(chNo int) { + tmr := &t.channel[chNo] + if tmr.start { + tmr.counter-- + if tmr.counter == 0 { + switch tmr.mode { + case TimerModeIntOnFin: + { + tmr.start = false + tmr.fired = true + } + case TimerModeOneShot: + tmr.start = false + case TimerModeRateGen: + tmr.start = false + case TimerModeSqWave: + { + tmr.start = true + tmr.counter = tmr.load + tmr.fired = true + } + } + } + } +} + +func (t *Timer8253) Counter(chNo int) uint16 { + return t.channel[chNo].counter +} + +func (t *Timer8253) Fired(chNo int) bool { + f := t.channel[chNo].fired + if f { + t.channel[chNo].fired = false + } + return f +} + +func (t *Timer8253) Start(chNo int) bool { + return t.channel[chNo].start +} + +func (t *Timer8253) Configure(value byte) { + chNo := (value & 0xC0) >> 6 + rl := value & 0x30 >> 4 + t.channel[chNo].start = false + t.channel[chNo].rl = rl + t.channel[chNo].mode = (value & 0x0E) >> 1 + t.channel[chNo].fb = true + t.channel[chNo].bcd = value&0x01 == 1 + t.channel[chNo].load = 0 +} + +func (t *Timer8253) Load(chNo byte, value byte) { + timer := &t.channel[chNo] + if timer.rl == 0 { + // MSB+LSB + if timer.fb { + // MSB + timer.load = uint16(value) << 8 + timer.fb = false + } else { + // LSB + timer.load |= uint16(value) + timer.start = true + } + } else if timer.rl == 1 { + // LSB Only + timer.load = (timer.load & 0xff00) | uint16(value) + timer.start = true + } else if timer.rl == 2 { + // MSB Only + timer.load = (timer.load & 0x00ff) | (uint16(value) << 8) + timer.start = true + } else { + // LSB+MSB + if timer.fb { + // LSB + timer.load = uint16(value) + timer.fb = false + } else { + // MSB + timer.load = (uint16(value) << 8) | (timer.load & 0x00ff) + timer.start = true + timer.counter = timer.load + } + } +} diff --git a/okemu.yml b/okemu.yml index 2e711a1..8cfc7d7 100644 --- a/okemu.yml +++ b/okemu.yml @@ -1,4 +1,4 @@ logFile: "okemu.log" logLevel: "info" -monitorFile: "okean240/MON_r6.BIN" -cpmFile: "okean240/CPM_r7.BIN" +monitorFile: "rom/MON_v5.bin" +cpmFile: "rom/CPM_v5.bin"