mirror of
https://github.com/romychs/Ocean-240.2-Emulator.git
synced 2026-04-21 11:03:21 +03:00
142 lines
2.7 KiB
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
|
|
}
|
|
}
|
|
}
|