Ocean-240.2-Emulator/main.go

142 lines
2.7 KiB
Go

package main
import (
_ "embed"
"fmt"
"okemu/config"
"okemu/debug"
"okemu/debug/listener"
"okemu/logger"
"okemu/okean240"
"okemu/okean240/fdc"
"okemu/z80/dis"
"sync/atomic"
"time"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/widget"
)
var Version = "v1.0.0"
var BuildTime = "2026-03-01"
//go:embed hex/m80.hex
var serialBytes []byte
//go:embed bin/main.com
var ramBytes1 []byte
//go:embed bin/PLOT.BAS
var ramBytes2 []byte
var needReset = false
var fullSpeed atomic.Bool
func main() {
fmt.Printf("Starting Ocean-240.2 emulator %s build at %s\n", Version, BuildTime)
// base log init
logger.InitLogging()
// load config yml file
config.LoadConfig()
conf := config.GetConfig()
// Reconfigure logging by config values
// logger.ReconfigureLogging(conf)
debugger := debug.NewDebugger()
computer := okean240.NewComputer(conf, debugger)
computer.SetSerialBytes(serialBytes)
if conf.FDC.AutoLoadB {
err := computer.LoadFloppy(fdc.FloppyB)
if err != nil {
// show message
}
}
if conf.FDC.AutoLoadC {
err := computer.LoadFloppy(fdc.FloppyC)
if err != nil {
// show message
}
}
disasm := dis.NewDisassembler(computer)
w, raster, label := mainWindow(computer)
go emulator(computer)
go screen(computer, raster, label)
if conf.Debugger.Enabled {
go listener.SetupTcpHandler(conf, debugger, disasm, computer)
}
(*w).ShowAndRun()
}
func screen(computer *okean240.ComputerType, raster *canvas.Raster, label *widget.Label) {
ticker := time.NewTicker(20 * time.Millisecond)
frame := 0
var pre uint64 = 0
var freq uint64 = 0
for range ticker.C {
frame++
// redraw screen here
fyne.Do(func() {
// status for every 50 frames
if frame%50 == 0 {
freq = computer.Cycles() - pre
pre = computer.Cycles()
label.SetText(formatLabel(computer, freq))
}
raster.Refresh()
})
}
}
func formatLabel(computer *okean240.ComputerType, freq uint64) string {
return fmt.Sprintf("Screen size: %dx%d | F: %d | Debugger: %s", computer.ScreenWidth(), computer.ScreenHeight(), freq, computer.DebuggerState())
}
const ticksPerTact uint64 = 4
func emulator(computer *okean240.ComputerType) {
ticker := time.NewTicker(66 * time.Nanosecond)
var ticks uint64 = 0
var nextClock = ticks + ticksPerTact
//var ticksCPU = 3
for range ticker.C {
ticks++
if ticks%10 == 0 {
// 1.5 MHz
computer.TimerClk()
}
var bp uint16 = 0
var typ byte = 0
if fullSpeed.Load() {
_, bp, typ = computer.Do()
} else {
if ticks >= nextClock {
var t uint32
t, bp, typ = computer.Do()
nextClock = ticks + uint64(t)*ticksPerTact
}
}
// Breakpoint hit
if bp > 0 || typ != 0 {
listener.BreakpointHit(bp, typ)
}
if needReset {
computer.Reset()
needReset = false
}
}
}