fix cpu timings, fix irq for keyboard handling, fix cursor keys

This commit is contained in:
Роман Бойков 2026-03-24 18:23:55 +03:00
parent a74841b048
commit 18df702750
11 changed files with 206 additions and 116 deletions

8
go.mod
View File

@ -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
View File

@ -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
View File

@ -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
//}
}
}

View File

@ -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
View 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
}

View File

@ -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]

View File

@ -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)
}

View File

@ -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
}

View File

@ -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 {

View File

@ -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,

View File

@ -2,6 +2,8 @@ logFile: okemu.log
logLevel: info
monitorFile: rom/MON_r8_9c6c6546.bin
cpmFile: rom/CPM_r8_bc0695e4.bin
#monitorFile: rom/MON_r5.bin
#cpmFile: rom/CPM_r5.bin
fdc:
- autoLoad: true
autoSave: true