mirror of
https://github.com/romychs/Ocean-240.2-Emulator.git
synced 2026-04-21 11:03:21 +03:00
fix cpu timings, fix irq for keyboard handling, fix cursor keys
This commit is contained in:
parent
a74841b048
commit
18df702750
8
go.mod
8
go.mod
@ -5,7 +5,10 @@ go 1.25
|
||||
require (
|
||||
fyne.io/fyne/v2 v2.7.3
|
||||
github.com/PaesslerAG/gval v1.2.4
|
||||
github.com/PaesslerAG/jsonpath v0.1.0
|
||||
github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6
|
||||
github.com/loov/hrtime v1.0.4
|
||||
github.com/shopspring/decimal v1.3.1
|
||||
github.com/sirupsen/logrus v1.9.4
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
@ -29,12 +32,12 @@ require (
|
||||
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/kr/text v0.2.0 // indirect
|
||||
github.com/kr/pretty v0.3.1 // 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/rogpeppe/go-internal v1.10.0 // indirect
|
||||
github.com/rymdport/portal v0.4.2 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // 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
|
||||
@ -43,4 +46,5 @@ require (
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
)
|
||||
|
||||
17
go.sum
17
go.sum
@ -49,18 +49,27 @@ github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wH
|
||||
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
|
||||
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/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/loov/hrtime v1.0.4 h1:K0wPQBsd9mWer2Sx8zIfpyAlF4ckZovtkEMUR/l9wpU=
|
||||
github.com/loov/hrtime v1.0.4/go.mod h1:VbIwDNS2gYTRoo0RjQFdqdDlBjJLXrkDIOgoA7Jvupk=
|
||||
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 h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
|
||||
github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo=
|
||||
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/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU=
|
||||
github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
@ -84,7 +93,7 @@ golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
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/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
199
main.go
199
main.go
@ -9,16 +9,19 @@ import (
|
||||
"okemu/debug"
|
||||
"okemu/debug/listener"
|
||||
"okemu/logger"
|
||||
"okemu/nanotime"
|
||||
"okemu/okean240"
|
||||
"okemu/z80/dis"
|
||||
"os"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
//log "github.com/sirupsen/logrus"
|
||||
"github.com/loov/hrtime"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var Version = "v1.0.0"
|
||||
@ -41,6 +44,21 @@ func main() {
|
||||
|
||||
fmt.Printf("Starting Ocean-240.2 emulator %s build at %s\n", Version, BuildTime)
|
||||
|
||||
f, err := os.Create("okemu.prof")
|
||||
if err != nil {
|
||||
log.Warn("Can not create prof file", err)
|
||||
}
|
||||
defer func(f *os.File) {
|
||||
err := f.Close()
|
||||
if err != nil {
|
||||
log.Warn("Can not close prof file", err)
|
||||
}
|
||||
}(f)
|
||||
if err := pprof.StartCPUProfile(f); err != nil {
|
||||
log.Warn("Can not start CPU profiling", err)
|
||||
}
|
||||
defer pprof.StopCPUProfile()
|
||||
|
||||
// Create a context that can be cancelled
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
@ -68,7 +86,7 @@ func main() {
|
||||
w, raster, label := mainWindow(computer, conf)
|
||||
|
||||
go emulator(ctx, computer)
|
||||
// go timerClock(ctx, computer)
|
||||
go timerClock(ctx, computer)
|
||||
go screen(ctx, computer, raster, label)
|
||||
|
||||
if conf.Debugger.Enabled {
|
||||
@ -86,9 +104,9 @@ func screen(ctx context.Context, computer *okean240.ComputerType, raster *canvas
|
||||
frame := 0
|
||||
var pre uint64 = 0
|
||||
var preTim uint64 = 0
|
||||
var freq float64 = 0
|
||||
var freqTim float64 = 0
|
||||
timeStart := time.Now()
|
||||
var cpuFreq float64 = 0
|
||||
var timerFreq float64 = 0
|
||||
timeStart := hrtime.Now()
|
||||
|
||||
for {
|
||||
select {
|
||||
@ -98,30 +116,21 @@ func screen(ctx context.Context, computer *okean240.ComputerType, raster *canvas
|
||||
fyne.Do(func() {
|
||||
// status for every 50 frames
|
||||
if frame%50 == 0 {
|
||||
timeElapsed := time.Since(timeStart)
|
||||
timeElapsed := hrtime.Since(timeStart)
|
||||
period := float64(timeElapsed.Nanoseconds()) / 1_000_000.0
|
||||
|
||||
freq = math.Round(float64(computer.Cycles()-pre)/period) / 1000.0
|
||||
freqTim = math.Round(float64(timerTicks.Load()-preTim)/period) / 1000.0
|
||||
label.SetText(formatLabel(computer, freq, freqTim))
|
||||
//cpuFreq = math.Round(float64(computer.Cycles()-pre)/period) / 1000.0
|
||||
cpuFreq = math.Round(float64(cpuTicks.Load()-pre)/period) / 1000.0
|
||||
timerFreq = math.Round(float64(timerTicks.Load()-preTim)/period) / 1000.0
|
||||
label.SetText(formatLabel(computer, cpuFreq, timerFreq))
|
||||
|
||||
// adjust cpu clock
|
||||
if freq > 2.55 && cpuClkPeriod.Load() < defaultCpuClkPeriod+40 {
|
||||
cpuClkPeriod.Add(1)
|
||||
} else if freq < 2.45 && cpuClkPeriod.Load() > defaultCpuClkPeriod-40 {
|
||||
cpuClkPeriod.Add(-1)
|
||||
}
|
||||
// adjust timer clock
|
||||
if freqTim > 1.53 && timerClkPeriod.Load() < defaultTimerClkPeriod+20 {
|
||||
timerClkPeriod.Add(1)
|
||||
} else if freqTim < 1.47 && timerClkPeriod.Load() > defaultTimerClkPeriod-20 {
|
||||
timerClkPeriod.Add(-1)
|
||||
}
|
||||
adjustTimers(cpuFreq, timerFreq)
|
||||
|
||||
//log.Debugf("Cpu clk period: %d, Timer clock period: %d, period: %1.3f", cpuClkPeriod.Load(), timerClkPeriod.Load(), period)
|
||||
pre = computer.Cycles()
|
||||
//pre = computer.Cycles()
|
||||
pre = cpuTicks.Load()
|
||||
preTim = timerTicks.Load()
|
||||
timeStart = time.Now()
|
||||
timeStart = hrtime.Now()
|
||||
}
|
||||
raster.Refresh()
|
||||
})
|
||||
@ -131,76 +140,104 @@ func screen(ctx context.Context, computer *okean240.ComputerType, raster *canvas
|
||||
}
|
||||
}
|
||||
|
||||
func adjustTimers(cpuFreq float64, timerFreq float64) {
|
||||
// adjust cpu clock
|
||||
if cpuFreq > 2.55 && cpuClkPeriod.Load() < defaultCpuClkPeriod+defaultCpuClkPeriod/2 {
|
||||
cpuClkPeriod.Add(1)
|
||||
// cpuTicker.Reset(time.Duration(cpuClkPeriod.Load()))
|
||||
} else if cpuFreq < 2.45 && cpuClkPeriod.Load() > 3 {
|
||||
cpuClkPeriod.Add(-2)
|
||||
// cpuTicker.Reset(time.Duration(cpuClkPeriod.Load()))
|
||||
}
|
||||
// adjust timerClock clock
|
||||
if timerFreq > 1.53 && timerClkPeriod.Load() < defaultTimerClkPeriod+defaultTimerClkPeriod/2 {
|
||||
timerClkPeriod.Add(1)
|
||||
//timerTicker.Reset(time.Duration(timerClkPeriod.Load()))
|
||||
} else if timerFreq < 1.47 && timerClkPeriod.Load() > 3 {
|
||||
timerClkPeriod.Add(-2)
|
||||
//timerTicker.Reset(time.Duration(timerClkPeriod.Load()))
|
||||
}
|
||||
}
|
||||
|
||||
func formatLabel(computer *okean240.ComputerType, freq float64, freqTim float64) string {
|
||||
return fmt.Sprintf("Screen size: %dx%d | Fcpu: %1.2fMHz | Ftmr: %1.2fMHz | Debugger: %s", computer.ScreenWidth(), computer.ScreenHeight(), freq, freqTim, computer.DebuggerState())
|
||||
return fmt.Sprintf("Screen size: %dx%d | Fcpu: %1.3fMHz | Ftmr: %1.3fMHz | Debugger: %s", computer.ScreenWidth(), computer.ScreenHeight(), freq, freqTim, computer.DebuggerState())
|
||||
}
|
||||
|
||||
var timerTicks atomic.Uint64
|
||||
|
||||
const defaultTimerClkPeriod = 564 // = 1_000_000_000 / 1_607_900 // period in nanos for 1.5MHz frequency
|
||||
const defaultCpuClkPeriod = 221 // = 1_000_000_000 / 2_770_000 // period in nanos for 2.5MHz frequency
|
||||
const defaultTimerClkPeriod = 430 // = 1_000_000_000 / 1_607_900 // period in nanos for 1.5MHz frequency
|
||||
const defaultCpuClkPeriod = 311 // = 1_000_000_000 / 2_770_000 // period in nanos for 2.5MHz frequency
|
||||
|
||||
var timerClkPeriod atomic.Int64 // = 1_000_000_000 / 1_607_900 // period in nanos for 1.5MHz frequency
|
||||
var cpuClkPeriod atomic.Int64 // = 1_000_000_000 / 2_770_000 // period in nanos for 2.5MHz frequency
|
||||
|
||||
func emulator(ctx context.Context, computer *okean240.ComputerType) {
|
||||
ticker := time.NewTicker(133 * time.Nanosecond)
|
||||
defer ticker.Stop()
|
||||
//var timerTicker *time.Ticker
|
||||
|
||||
cpuClkPeriod.Store(defaultCpuClkPeriod)
|
||||
//var cpuTicker *time.Ticker
|
||||
|
||||
func timerClock(ctx context.Context, computer *okean240.ComputerType) {
|
||||
timerClkPeriod.Store(defaultTimerClkPeriod)
|
||||
|
||||
cpuTicks := uint64(0)
|
||||
nextTick := uint64(0)
|
||||
|
||||
cpuTStart := nanotime.Now()
|
||||
tmrTStart := cpuTStart
|
||||
|
||||
var bp uint16
|
||||
var bpType byte
|
||||
|
||||
timeStart := hrtime.Now()
|
||||
for {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
tmrElapsed := nanotime.Since(tmrTStart)
|
||||
// TIMER CLK
|
||||
if tmrElapsed.Nanoseconds() >= timerClkPeriod.Load() {
|
||||
computer.TimerClk()
|
||||
timerTicks.Add(1)
|
||||
tmrTStart = nanotime.Now()
|
||||
}
|
||||
|
||||
// CPU
|
||||
cpuElapsed := nanotime.Since(cpuTStart)
|
||||
if cpuElapsed.Nanoseconds() >= cpuClkPeriod.Load() {
|
||||
cpuTicks++
|
||||
bp = 0
|
||||
bpType = 0
|
||||
|
||||
if fullSpeed.Load() {
|
||||
// Max frequency
|
||||
_, bp, bpType = computer.Do()
|
||||
} else {
|
||||
// 2.5MHz frequency
|
||||
if cpuTicks >= nextTick {
|
||||
var t uint32
|
||||
t, bp, bpType = computer.Do()
|
||||
nextTick += uint64(t)
|
||||
}
|
||||
}
|
||||
// Breakpoint hit
|
||||
if bp > 0 || bpType != 0 {
|
||||
listener.BreakpointHit(bp, bpType)
|
||||
}
|
||||
if needReset {
|
||||
computer.Reset()
|
||||
needReset = false
|
||||
}
|
||||
cpuTStart = nanotime.Now()
|
||||
}
|
||||
case <-ctx.Done():
|
||||
return
|
||||
elapsed := hrtime.Since(timeStart)
|
||||
if int64(elapsed) > timerClkPeriod.Load() {
|
||||
timeStart = hrtime.Now()
|
||||
computer.TimerClk()
|
||||
timerTicks.Add(1)
|
||||
runtime.Gosched()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var cpuTicks atomic.Uint64
|
||||
|
||||
func emulator(ctx context.Context, computer *okean240.ComputerType) {
|
||||
cpuClkPeriod.Store(defaultCpuClkPeriod)
|
||||
//cpuTicker = time.NewTicker(time.Duration(cpuClkPeriod.Load()) * time.Nanosecond)
|
||||
//defer cpuTicker.Stop()
|
||||
|
||||
cpuTicks.Store(0) // := uint64(0)
|
||||
nextTick := uint64(0)
|
||||
|
||||
var bp uint16
|
||||
var bpType byte
|
||||
timeStart := hrtime.Now()
|
||||
|
||||
for {
|
||||
//select {
|
||||
//case <-cpuTicker.C:
|
||||
// CPU
|
||||
elapsed := hrtime.Since(timeStart)
|
||||
if int64(elapsed) >= cpuClkPeriod.Load() {
|
||||
timeStart = hrtime.Now()
|
||||
bp = 0
|
||||
bpType = 0
|
||||
|
||||
// 2.5MHz frequency
|
||||
cpuTicks.Add(1)
|
||||
if fullSpeed.Load() {
|
||||
// Max frequency
|
||||
_, bp, bpType = computer.Do()
|
||||
} else if cpuTicks.Load() >= nextTick {
|
||||
var t uint32
|
||||
t, bp, bpType = computer.Do()
|
||||
nextTick = cpuTicks.Load() + uint64(t)
|
||||
runtime.Gosched()
|
||||
}
|
||||
|
||||
// Breakpoint hit
|
||||
if bp > 0 || bpType != 0 {
|
||||
listener.BreakpointHit(bp, bpType)
|
||||
}
|
||||
if needReset {
|
||||
computer.Reset()
|
||||
needReset = false
|
||||
}
|
||||
}
|
||||
//case <-ctx.Done():
|
||||
// return
|
||||
//}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -20,7 +20,6 @@ import (
|
||||
"okemu/z80/c99"
|
||||
//"okemu/z80/js"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -50,6 +49,7 @@ type ComputerType struct {
|
||||
//
|
||||
debugger *debug.Debugger
|
||||
config *config.OkEmuConfig
|
||||
kbAck bool
|
||||
}
|
||||
|
||||
type Snapshot struct {
|
||||
@ -62,20 +62,20 @@ const VRAMBlock1 = 7
|
||||
const VidVsuBit = 0x80
|
||||
const VidColorBit = 0x40
|
||||
|
||||
type ComputerInterface interface {
|
||||
Run()
|
||||
Reset()
|
||||
GetPixel(x uint16, y uint16) color.RGBA
|
||||
Do() uint64
|
||||
TimerClk()
|
||||
PutKey(key *fyne.KeyEvent)
|
||||
PutRune(key rune)
|
||||
PutCtrlKey(shortcut fyne.Shortcut)
|
||||
SaveFloppy()
|
||||
LoadFloppy()
|
||||
CPUState() *z80.CPU
|
||||
SetCPUState(state *z80.CPU)
|
||||
}
|
||||
//type ComputerInterface interface {
|
||||
// Run()
|
||||
// Reset()
|
||||
// GetPixel(x uint16, y uint16) color.RGBA
|
||||
// Do() uint64
|
||||
// TimerClk()
|
||||
// PutKey(key *fyne.KeyEvent)
|
||||
// PutRune(key rune)
|
||||
// PutCtrlKey(shortcut fyne.Shortcut)
|
||||
// SaveFloppy()
|
||||
// LoadFloppy()
|
||||
// CPUState() *z80.CPU
|
||||
// SetCPUState(state *z80.CPU)
|
||||
//}
|
||||
|
||||
func (c *ComputerType) GetCPUState() *z80.CPU {
|
||||
return c.cpu.GetState()
|
||||
@ -120,6 +120,7 @@ func NewComputer(cfg *config.OkEmuConfig, deb *debug.Debugger) *ComputerType {
|
||||
//c.aOffset = 0x100
|
||||
|
||||
c.pit = pit.New()
|
||||
c.kbAck = false
|
||||
c.usart = usart.New()
|
||||
c.pic = pic.New()
|
||||
c.fdc = fdc.NewFDC(cfg)
|
||||
@ -223,10 +224,14 @@ func (c *ComputerType) GetPixel(x uint16, y uint16) color.RGBA {
|
||||
// Color 256x256 mode
|
||||
addr = ((x & 0xf8) << 6) | y
|
||||
|
||||
cl := (c.vRAM.memory[(addr-offset)&0x3fff] >> (x & 0x07)) & 1
|
||||
cl |= ((c.vRAM.memory[(addr+0x100-offset)&0x3fff] >> (x & 0x07)) & 1) << 1
|
||||
a1 := (addr - offset) & 0x3fff
|
||||
a2 := (a1 + 0x100) & 0x3fff
|
||||
|
||||
cl := (c.vRAM.memory[a1] >> (x & 0x07)) & 1
|
||||
cl |= ((c.vRAM.memory[a2] >> (x & 0x07)) & 1) << 1
|
||||
if cl == 0 {
|
||||
resColor = BgColorPalette[c.bgColor]
|
||||
resColor = ColorPalette[c.palette][cl]
|
||||
} else {
|
||||
resColor = ColorPalette[c.palette][cl]
|
||||
}
|
||||
|
||||
20
okean240/computer_test.go
Normal file
20
okean240/computer_test.go
Normal file
@ -0,0 +1,20 @@
|
||||
package okean240
|
||||
|
||||
func calculateVAddress(x uint16, y uint16) (uint16, uint16) {
|
||||
|
||||
var offset uint16
|
||||
if (c.vShift != 0) && (y > 255-uint16(c.vShift)) {
|
||||
offset = 0x100
|
||||
} else {
|
||||
offset = 0
|
||||
}
|
||||
y += uint16(c.vShift) & 0x00ff
|
||||
x += uint16(c.hShift-7) & 0x00ff
|
||||
|
||||
// Color 256x256 mode
|
||||
addr = ((x & 0xf8) << 6) | y
|
||||
|
||||
a1 := (addr - offset) & 0x3fff
|
||||
a2 := (addr + 0x100 - offset) & 0x3fff
|
||||
|
||||
}
|
||||
@ -57,7 +57,7 @@ const KbdDd78pa = 0x40
|
||||
const KbdDd78pb = 0x41
|
||||
|
||||
// KBD_DD78PC Port C - [PC7:5],[KBD_ACK],[PC3:0]
|
||||
//const KBD_DD78PC = 0x42
|
||||
const KbdDd78pc = 0x42
|
||||
|
||||
// KBD_DD78CTR Control port
|
||||
// Configure: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI]
|
||||
|
||||
@ -14,7 +14,12 @@ func (c *ComputerType) IORead(port uint16) byte {
|
||||
switch port & 0x00ff {
|
||||
case PicDd75a:
|
||||
// PIO xx59, get IRR register
|
||||
return c.pic.IRR()
|
||||
irr := c.pic.IRR()
|
||||
// if irq from keyboard and no ACK applied, re-fire
|
||||
if irr&0x10 != 0 && !c.kbAck {
|
||||
c.pic.SetIRQ(RstKbdNo)
|
||||
}
|
||||
return irr
|
||||
case PicDd75b:
|
||||
return c.pic.CSW()
|
||||
case UartDd72rr:
|
||||
@ -110,6 +115,14 @@ func (c *ComputerType) IOWrite(port uint16, val byte) {
|
||||
c.fdc.SetSectorNo(val)
|
||||
case Floppy:
|
||||
c.fdc.SetFloppy(val)
|
||||
|
||||
case KbdDd78pc:
|
||||
if val&0x80 != 0 {
|
||||
c.kbAck = true
|
||||
} else {
|
||||
//c.kbAck = false
|
||||
}
|
||||
|
||||
default:
|
||||
//log.Debugf("OUT to Unknown port (%x), %x", bp, val)
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ func (c *ComputerType) PutKey(key *fyne.KeyEvent) {
|
||||
//log.Debugf("PutKey keyName: %s", key.Name)
|
||||
c.ioPorts[KbdDd78pa] = code
|
||||
c.pic.SetIRQ(RstKbdNo)
|
||||
c.kbAck = false
|
||||
}
|
||||
|
||||
}
|
||||
@ -21,6 +22,7 @@ func (c *ComputerType) PutRune(key rune) {
|
||||
|
||||
c.ioPorts[KbdDd78pa] = byte(key & 0xff)
|
||||
c.pic.SetIRQ(RstKbdNo)
|
||||
c.kbAck = false
|
||||
}
|
||||
|
||||
/*
|
||||
@ -39,6 +41,7 @@ func (c *ComputerType) PutRune(key rune) {
|
||||
func (c *ComputerType) PutCtrlKey(key byte) {
|
||||
c.ioPorts[KbdDd78pa] = key
|
||||
c.pic.SetIRQ(RstKbdNo)
|
||||
c.kbAck = false
|
||||
//c.ioPorts[PIC_DD75RS] |= Rst1Mask
|
||||
c.ioPorts[KbdDd78pb] &= 0x1f | 0x20
|
||||
}
|
||||
|
||||
@ -7,8 +7,6 @@ package pic
|
||||
By Romych, 2025.03.05
|
||||
*/
|
||||
|
||||
import log "github.com/sirupsen/logrus"
|
||||
|
||||
type I8259 struct {
|
||||
irr byte
|
||||
csw byte
|
||||
@ -42,12 +40,11 @@ func (c *I8259) IRR() byte {
|
||||
return irr
|
||||
}
|
||||
|
||||
func (c *I8259) ResetIRQ(irq byte) {
|
||||
c.irr &= ^(byte(1) << (irq & 0x07))
|
||||
}
|
||||
func (c *I8259) SetIRQ(irq byte) {
|
||||
if irq < 8 {
|
||||
c.irr |= 1 << irq
|
||||
} else {
|
||||
log.Warnf("SetIRQ out of range [0..7]: %d", irq)
|
||||
}
|
||||
c.irr |= 1 << (irq & 0x07)
|
||||
}
|
||||
|
||||
func (c *I8259) CSW() byte {
|
||||
|
||||
@ -9,10 +9,10 @@ var RemapCmdKey = map[fyne.KeyName]byte{
|
||||
fyne.KeyBackspace: 0x08,
|
||||
fyne.KeyInsert: 0x00,
|
||||
fyne.KeyDelete: 0x08,
|
||||
fyne.KeyRight: 0x18,
|
||||
fyne.KeyLeft: 0x08,
|
||||
fyne.KeyRight: 0x84, //0x18,
|
||||
fyne.KeyLeft: 0x93, //0x08,
|
||||
fyne.KeyDown: 0x0A,
|
||||
fyne.KeyUp: 0x19,
|
||||
fyne.KeyUp: 0x85, //0x19,
|
||||
fyne.KeyPageUp: 0x00,
|
||||
fyne.KeyPageDown: 0x00,
|
||||
fyne.KeyHome: 0x0C,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user