fdc mostly fixed

This commit is contained in:
Роман Бойков 2026-03-06 13:16:38 +03:00
parent 42fb80813c
commit b133807f05
10 changed files with 490 additions and 155 deletions

53
main.go
View File

@ -1,6 +1,7 @@
package main
import (
_ "embed"
"fmt"
"image/color"
"okemu/config"
@ -19,6 +20,14 @@ import (
var Version = "v1.0.0"
var BuildTime = "2026-03-01"
//go:embed hex/format.hex
var serialBytes []byte
//go:embed bin/TYPE.COM
var ramBytes []byte
var needReset = false
func main() {
fmt.Printf("Starting Ocean-240.2 emulator %s build at %s\n", Version, BuildTime)
@ -32,9 +41,19 @@ func main() {
conf := config.GetConfig()
// Reconfigure logging by config values
//logger.ReconfigureLogging(conf)
computer := okean240.New(conf)
// logger.ReconfigureLogging(conf)
computer := okean240.New(conf)
computer.SetSerialBytes(serialBytes)
w, raster, label := mainWindow(computer, conf)
go emulator(computer, raster, label, conf)
(*w).ShowAndRun()
}
func mainWindow(computer *okean240.ComputerType, emuConfig *config.OkEmuConfig) (*fyne.Window, *canvas.Raster, *widget.Label) {
emulatorApp := app.New()
w := emulatorApp.NewWindow("Океан 240.2")
w.Canvas().SetOnTypedKey(
@ -42,6 +61,11 @@ func main() {
computer.PutKey(key)
})
w.Canvas().SetOnTypedRune(
func(key rune) {
computer.PutRune(key)
})
addShortcuts(w.Canvas(), computer)
label := widget.NewLabel(fmt.Sprintf("Screen size: %dx%d", computer.ScreenWidth(), computer.ScreenHeight()))
@ -61,9 +85,22 @@ func main() {
widget.NewButton("Ctrl+C", func() {
computer.PutCtrlKey(0x03)
}),
widget.NewButton("Load Floppy", func() {
computer.LoadFloppy()
}),
widget.NewButton("Save Floppy", func() {
computer.SaveFloppy()
}),
widget.NewButton("RUN", func() {
computer.SetRamBytes(ramBytes)
}),
widget.NewButton("DUMP", func() {
computer.Dump(0x399, 15000)
}),
widget.NewSeparator(),
widget.NewButton("Reset", func() {
computer.Reset()
needReset = true
//computer.Reset(conf)
}),
widget.NewSeparator(),
widget.NewButton("Закрыть", func() {
@ -78,12 +115,10 @@ func main() {
w.SetContent(vBox)
go emulator(computer, raster, label)
w.ShowAndRun()
return &w, raster, label
}
func emulator(computer *okean240.ComputerType, raster *canvas.Raster, label *widget.Label) {
func emulator(computer *okean240.ComputerType, raster *canvas.Raster, label *widget.Label, emuConfig *config.OkEmuConfig) {
ticker := time.NewTicker(133 * time.Nanosecond)
var ticks = 0
var ticksCPU = 3
@ -97,6 +132,10 @@ func emulator(computer *okean240.ComputerType, raster *canvas.Raster, label *wid
nextSecond := time.Now().Add(time.Second).UnixMicro()
curScrWidth := 256
for range ticker.C {
if needReset {
computer.Reset(emuConfig)
needReset = false
}
ticks++
if ticks%5 == 0 {
// 1.5 MHz

View File

@ -1,12 +1,16 @@
package okean240
import (
_ "embed"
"encoding/binary"
"image/color"
"okemu/config"
fdc2 "okemu/okean240/fdc"
"okemu/okean240/pic"
"okemu/okean240/pit"
"okemu/okean240/usart"
"okemu/z80em"
"os"
"fyne.io/fyne/v2"
log "github.com/sirupsen/logrus"
@ -26,6 +30,7 @@ type ComputerType struct {
bgColor byte
dd70 *pit.I8253
dd72 *usart.I8251
dd75 *pic.I8259
fdc *fdc2.FloppyDriveController
kbdBuffer []byte
vShift byte
@ -45,7 +50,11 @@ type ComputerInterface interface {
Do() uint64
TimerClk()
PutKey(key *fyne.KeyEvent)
PutRune(key rune)
PutCtrlKey(shortcut fyne.Shortcut)
SaveFloppy()
LoadFloppy()
Dump(start uint16, length uint16)
}
func (c *ComputerType) M1MemRead(addr uint16) byte {
@ -81,25 +90,39 @@ func New(cfg *config.OkEmuConfig) *ComputerType {
c.dd70 = pit.NewI8253()
c.dd72 = usart.NewI8251()
c.dd75 = pic.NewI8259()
c.fdc = fdc2.NewFDCType()
return &c
}
func (c *ComputerType) Reset() {
func (c *ComputerType) Reset(cfg *config.OkEmuConfig) {
c.cpu.Reset()
c.cycles = 0
c.vShift = 0
c.hShift = 0
c.memory = Memory{}
c.memory.Init(cfg.MonitorFile, cfg.CPMFile)
c.cycles = 0
c.dd17EnableOut = false
c.screenWidth = 512
c.screenHeight = 256
c.vRAM = c.memory.allMemory[3]
}
func (c *ComputerType) Do() int {
s := c.cpu.GetState()
if s.PC == 0xe0db {
log.Debugf("breakpoint")
}
//s := c.cpu.GetState()
//if s.PC == 0xe0db {
// log.Debugf("breakpoint")
//}
ticks := uint64(c.cpu.RunInstruction())
c.cycles += ticks
//if c.cpu.PC == 0x2C2 {
// log.Debugf("%4X: H:%X L:%X", c.cpu.PC, c.cpu.H, c.cpu.L)
//}
return int(ticks)
}
@ -115,15 +138,17 @@ func (c *ComputerType) GetPixel(x uint16, y uint16) color.RGBA {
if x > 255 {
return CWhite
}
y += uint16(c.vShift)
x += uint16(c.hShift)
y += uint16(c.vShift) & 0x00ff
x += uint16(c.hShift) & 0x00ff
// Color 256x256 mode
addr = ((x & 0xf8) << 6) | (y & 0xff)
if c.vShift != 0 {
addr -= 8
}
var cl byte = (c.vRAM.memory[addr&0x3fff] >> (x & 0x07)) & 1
cl := (c.vRAM.memory[addr&0x3fff] >> (x & 0x07)) & 1
cl |= (c.vRAM.memory[(addr+0x100)&0x3fff] >> (x & 0x07)) & 1 << 1
if cl == 0 {
resColor = BgColorPalette[c.bgColor]
@ -174,10 +199,61 @@ func (c *ComputerType) TimerClk() {
// IRQ from timer
if c.dd70.Fired(0) {
c.ioPorts[PIC_DD75RS] |= Rst4TmrFlag
c.dd75.SetIRQ(RstTimerNo)
//c.ioPorts[PIC_DD75RS] |= Rst4Mask
}
// clock for SIO KR580VV51
if c.dd70.Fired(1) {
c.dd72.Tick()
}
}
func (c *ComputerType) LoadFloppy() {
c.fdc.LoadFloppy()
}
func (c *ComputerType) SaveFloppy() {
c.fdc.SaveFloppy()
}
func (c *ComputerType) SetSerialBytes(bytes []byte) {
c.dd72.SetRxBytes(bytes)
}
func (c *ComputerType) SetRamBytes(bytes []byte) {
addr := 0x100
for i := 0; i < len(bytes); i++ {
c.memory.MemWrite(uint16(addr), bytes[i])
addr++
}
pages := len(bytes) / 256
if len(bytes)%256 != 0 {
pages++
}
log.Debugf("Loaded bytes: %d; blocks: %d", len(bytes), pages)
//c.cpu.SP = 0x100
//c.cpu.PC = 0x100
}
func (c *ComputerType) Dump(start uint16, length uint16) {
file, err := os.Create("dump.dat")
if err != nil {
log.Error(err)
return
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
log.Error(err)
}
}(file)
var buffer []byte
for addr := 0; addr < 65535; addr++ {
buffer = append(buffer, c.memory.MemRead(uint16(addr)))
}
err = binary.Write(file, binary.LittleEndian, buffer)
if err != nil {
log.Error("Save memory dump failed:", err)
}
}

View File

@ -89,20 +89,23 @@ const TMR_DD70CTR = 0x63
* Programmable Interrupt controller PIC KR580VV59
*/
// PIC_DD75RS RS Port
const PIC_DD75RS = 0x80
const RstKbdNo = 1
const RstTimerNo = 4
const Rst0SysFlag = 0x01 // System interrupt
const Rst1KbdFlag = 0x02 // Keyboard interrupt
const Rst2SerFlag = 0x04 // Serial interface interrupt
const RstЗLptFlag = 0x08 // Printer ready
const Rst4TmrFlag = 0x10 // System timer
const Rst5PwrFlag = 0x20 // Power intRq
const Rst6UsrFlag = 0x40 // User device 1 interrupt
const Rst7UsrFlag = 0x80 // User device 1 interrupt
const Rst0Mask = 0x01 // System interrupt
const Rst1Mask = 0x02 // Keyboard interrupt
const Rst2Mask = 0x04 // Serial interface interrupt
const RstЗMask = 0x08 // Printer ready
const Rst4Mask = 0x10
const Rst5Mask = 0x20 // Power intRq
const Rst6Mask = 0x40 // User device 1 interrupt
const Rst7Mask = 0x80 // User device 1 interrupt
// PIC_DD75RM RM Port
const PIC_DD75RM = 0x81
// PIC_DD75A Port A (a0=0)
const PIC_DD75A = 0x80
// PIC_DD75B Port B (a0=1)
const PIC_DD75B = 0x81
/*
* КР580ВВ51 DD72

View File

@ -1,48 +1,82 @@
package fdc
/**
Floppy drive controller, based on
MB8877, К1818ВГ93
By Romych, 2025.03.05
*/
* Floppy drive controller, based on
* MB8877, К1818ВГ93
*
* By Romych, 2025.03.05
*/
import (
"encoding/binary"
"os"
"slices"
"strconv"
log "github.com/sirupsen/logrus"
)
const FloppySizeK = 360
// Floppy parameters
const (
FloppySizeK = 720
SectorSize = 128
SideCount = 2
SectorPerTrack = 36
const SectorSize = 128
const SideCount = 2
const SectorPerTrack = 36
SizeInSectors = FloppySizeK * 1024 / SectorSize
TracksCount = SizeInSectors / SideCount / SectorPerTrack
SectorsPerSide = SizeInSectors / SideCount
const SizeInSectors = FloppySizeK * 1024 / SectorSize
const TracksCount = SizeInSectors / SideCount / SectorPerTrack
const SectorsPerSide = SizeInSectors / SideCount
TrackHeaderSize = 146
TrackSectorSize = 626
TrackFooterSize = 256 * 3
TrackBufferSize = TrackHeaderSize + TrackSectorSize*9 + TrackFooterSize
)
// FDC Commands
const (
CmdRestore byte = 0x0
CmdSeek byte = 0x1
CmdStep byte = 0x2
CmdStepIn byte = 0x5
CmdStepOut byte = 0x7
CmdReadSector byte = 0x8
CmdReadSectorMulti byte = 0x9
CmdWriteSector byte = 0xa
CmdWriteTrack byte = 0xf
CmdNoCommand byte = 0xff
)
const (
StatusTR0 = 0x04 // TR0 - Head at track 0
StatusRNF = 0x10 // RNF - Record not found
StatusSeekError = 0x10 // Sector out of disk
StatusHeadLoaded = 0x20 // Head on disk
)
type SectorType []byte
type FloppyDriveController struct {
// Floppy controller port
sideSel byte
ddEn byte
init byte
drSel byte
mot1 byte
mot0 byte
intRq byte
motSt byte
sector byte
track byte
drq byte
sideNo byte
ddEn byte
init byte
drive byte
mot1 byte
mot0 byte
intRq byte
motSt byte
sectorNo byte
trackNo byte
drq byte
// FloppyStorage
sectors [SizeInSectors]SectorType
data byte
status byte
lastCmd byte
curSector *SectorType
bytePtr uint16
sectors [SizeInSectors]SectorType
data byte
status byte
lastCmd byte
//curSector *SectorType
bytePtr uint16
trackBuffer []byte
}
type FloppyDriveControllerInterface interface {
@ -55,59 +89,96 @@ type FloppyDriveControllerInterface interface {
SetData(value byte)
Data() byte
Drq() byte
SaveFloppy()
GetSectorNo() uint16
Track() byte
Sector() byte
}
func (f *FloppyDriveController) GetSectorNo() uint16 {
return uint16(f.sideNo)*SectorsPerSide + uint16(f.trackNo)*SectorPerTrack + uint16(f.sectorNo) - 1
}
func (f *FloppyDriveController) SetFloppy(val byte) {
// WR: 5-SSEN, 4-#DDEN, 3-INIT, 2-DRSEL, 1-MOT1, 0-MOT0
f.sideSel = val >> 5 & 0x01
// WR: 5-SSEL, 4-#DDEN, 3-INIT, 2-DRSEL, 1-MOT1, 0-MOT0
f.sideNo = val >> 5 & 0x01
f.ddEn = val >> 4 & 0x01
f.init = val >> 3 & 0x01
f.drSel = val >> 2 & 0x01
f.drive = val >> 2 & 0x01
f.mot1 = val >> 1 & 0x01
f.mot0 = val & 0x01
}
func (f *FloppyDriveController) GetFloppy() byte {
// RD: 7-MOTST, 6-SSEL, 5,4-x , 3-DRSEL, 2-MOT1, 1-MOT0, 0-INT
floppy := f.intRq | (f.mot0 << 1) | (f.mot1 << 2) | (f.drSel << 3) | (f.sideSel << 6) | (f.motSt << 7)
floppy := f.intRq | (f.mot0 << 1) | (f.mot1 << 2) | (f.drive << 3) | (f.sideNo << 6) | (f.motSt << 7)
return floppy
}
const (
FdcCmdRestore byte = 0
FdcCmdSeek byte = 1
FdcCmdStep byte = 2
FdcCmdReadSector byte = 8
)
func (f *FloppyDriveController) SetCmd(value byte) {
//log.Debugf("FCD CMD: %x", value)
f.lastCmd = value >> 4
switch f.lastCmd {
case FdcCmdRestore:
log.Debug("CMD Restore (seek track 0)")
f.status = 0x24 // TR0 & Head loaded
f.track = 0
case FdcCmdSeek:
case CmdRestore:
log.Debug("CMD Restore (seek trackNo 0)")
f.trackNo = 0
f.status = StatusTR0 | StatusHeadLoaded // TR0 & Head loaded
case CmdSeek:
log.Debugf("CMD Seek %x", value&0xf)
f.status = 0x04 // Head loaded
f.track = f.data
case FdcCmdStep:
f.status = StatusHeadLoaded
f.trackNo = f.data
case CmdStep:
log.Debugf("CMD Step %x", value&0xf)
f.status = 0x04 // Head loaded
f.track = f.data
case FdcCmdReadSector:
f.status = 0x04
sectorNo := uint16(f.sideSel)*SectorsPerSide + uint16(f.track)*SectorPerTrack + uint16(f.sector)
log.Debugf("CMD Read single sector: %d", sectorNo)
if sectorNo >= SizeInSectors {
f.status = 0x10 // RNF - Record not found
} else {
f.curSector = &f.sectors[sectorNo]
f.bytePtr = 0
f.status = StatusHeadLoaded
f.trackNo = f.data
case CmdStepIn:
log.Debugf("CMD StepIn (Next track) %x", value&0xf)
f.status = StatusHeadLoaded
if f.trackNo < TracksCount {
f.trackNo++
}
case CmdStepOut:
log.Debugf("CMD StepOut (Previous track) %x", value&0xf)
f.status = StatusHeadLoaded
if f.trackNo > 0 {
f.trackNo--
}
case CmdReadSector:
sectorNo := f.GetSectorNo()
log.Debugf("CMD Read single sectorNo: %d", sectorNo)
if sectorNo < SizeInSectors {
f.trackBuffer = slices.Clone(f.sectors[sectorNo])
f.drq = 1
f.status = 0x00
} else {
f.drq = 0
f.status = StatusRNF
}
case CmdReadSectorMulti:
sectorNo := f.GetSectorNo()
f.trackBuffer = []byte{}
for c := 0; c < SectorPerTrack; c++ {
f.trackBuffer = slices.Concat(f.trackBuffer, f.sectors[sectorNo])
sectorNo++
}
f.drq = 1
f.status = 0x0
case CmdWriteSector:
sectorNo := f.GetSectorNo()
log.Debugf("CMD Write Sector %d", sectorNo)
if sectorNo < SizeInSectors {
f.bytePtr = 0
f.drq = 1
f.status = 0x0
f.trackBuffer = []byte{}
} else {
f.drq = 0
f.status = StatusRNF
}
case CmdWriteTrack:
log.Debugf("CMD Write Track %x", f.trackNo)
f.status = 0x00
f.trackBuffer = []byte{}
f.drq = 1
default:
log.Debugf("Unknown CMD: %x VAL: %x", f.lastCmd, value&0xf)
}
@ -117,31 +188,72 @@ func (f *FloppyDriveController) Status() byte {
return f.status
}
func (f *FloppyDriveController) SetTrack(value byte) {
log.Debugf("FCD Track: %d", value)
f.track = value
func (f *FloppyDriveController) SetTrackNo(value byte) {
//log.Debugf("FDC Track: %d", value)
if value > TracksCount {
f.status |= 0x10 /// RNF
log.Error("Track not found!")
} else {
f.trackNo = value
}
}
func (f *FloppyDriveController) SetSector(value byte) {
log.Debugf("FCD Sector: %d", value)
f.sector = value
func (f *FloppyDriveController) SetSectorNo(value byte) {
//log.Debugf("FDC Sector: %d", value)
if value > SectorPerTrack {
f.status |= 0x10
log.Error("Record not found!")
} else {
f.sectorNo = value
}
}
func (f *FloppyDriveController) SetData(value byte) {
log.Debugf("FCD Data: %d", value)
//log.Debugf("FCD Data: %d", value)
if f.lastCmd == CmdWriteTrack {
if len(f.trackBuffer) < TrackBufferSize {
f.trackBuffer = append(f.trackBuffer, value)
f.drq = 1
f.status = 0x00
} else {
//f.dump()
f.drq = 0
f.status = 0x00
f.lastCmd = CmdNoCommand
}
} else if f.lastCmd == CmdWriteSector {
if len(f.trackBuffer) < SectorSize {
f.trackBuffer = append(f.trackBuffer, value)
if len(f.trackBuffer) == SectorSize {
f.drq = 0
} else {
f.drq = 1
}
}
if len(f.trackBuffer) == SectorSize {
f.drq = 0
f.sectors[f.GetSectorNo()] = slices.Clone(f.trackBuffer)
f.lastCmd = CmdNoCommand
}
}
f.data = value
}
func (f *FloppyDriveController) Data() byte {
if f.lastCmd == FdcCmdReadSector {
if f.bytePtr < SectorSize {
switch f.lastCmd {
case CmdReadSector, CmdReadSectorMulti:
if len(f.trackBuffer) > 0 {
f.drq = 1
f.data = (*f.curSector)[f.bytePtr]
f.bytePtr++
} else {
f.data = f.trackBuffer[0]
f.trackBuffer = f.trackBuffer[1:]
}
if len(f.trackBuffer) == 0 {
f.drq = 0
f.status = 0
f.lastCmd = CmdNoCommand
}
default:
f.data = 0xff
}
return f.data
}
@ -150,19 +262,78 @@ func (f *FloppyDriveController) Drq() byte {
return f.drq
}
func (f *FloppyDriveController) LoadFloppy() {
log.Debug("Load Floppy content.")
file, err := os.Open("floppy.okd")
if err != nil {
log.Error(err)
return
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
log.Error(err)
}
}(file)
for sector := 0; sector < SizeInSectors; sector++ {
var n int
n, err = file.Read(f.sectors[sector])
if n != SectorSize {
log.Error("Load floppy error, sector size: %d <> %d", n, SectorSize)
}
// err = binary.Read(file, binary.LittleEndian, f.sectors[sector])
if err != nil {
log.Error("Load floppy content failed:", err)
break
}
}
}
func (f *FloppyDriveController) SaveFloppy() {
log.Debug("Save Floppy content.")
file, err := os.Create("floppy.okd")
if err != nil {
log.Error(err)
return
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
log.Error(err)
}
}(file)
// Write the struct to the file in little-endian byte order
for sector := 0; sector < SizeInSectors; sector++ {
var n int
n, err = file.Write(f.sectors[sector])
if n != SectorSize {
log.Errorf("Save floppy error, sector %d size: %d <> %d", sector, n, SectorSize)
}
if err != nil {
log.Error("Save floppy content failed:", err)
break
}
}
}
func NewFDCType() *FloppyDriveController {
sec := [SizeInSectors]SectorType{}
for i := 0; i < int(SizeInSectors); i++ {
for i := 0; i < SizeInSectors; i++ {
sec[i] = make([]byte, SectorSize)
for s := 0; s < 128; s++ {
sec[i][s] = 0
sec[i][s] = 0xE5
}
}
return &FloppyDriveController{
sideSel: 0,
sideNo: 0,
ddEn: 0,
init: 0,
drSel: 0,
drive: 0,
mot1: 0,
mot0: 0,
intRq: 0,
@ -174,4 +345,33 @@ func NewFDCType() *FloppyDriveController {
}
}
func (f *FloppyDriveController) dump() {
log.Debug("Dump Buffer content.")
file, err := os.Create("track-" + strconv.Itoa(int(f.trackNo)) + ".dat")
if err != nil {
log.Error(err)
return
}
defer func(file *os.File) {
err := file.Close()
if err != nil {
log.Error(err)
}
}(file)
err = binary.Write(file, binary.LittleEndian, f.trackBuffer)
if err != nil {
log.Error("Save track content failed:", err)
}
}
func (f *FloppyDriveController) Track() byte {
return f.trackNo
}
func (f *FloppyDriveController) Sector() byte {
return f.sectorNo
}
//

View File

@ -12,16 +12,14 @@ import log "github.com/sirupsen/logrus"
func (c *ComputerType) IORead(port uint16) byte {
switch port & 0x00ff {
case PIC_DD75RS:
// PIO VN59
v := c.ioPorts[PIC_DD75RS]
c.ioPorts[PIC_DD75RS] = 0
return v
case PIC_DD75A:
// PIO xx59, get IRR register
return c.dd75.IRR()
case UART_DD72RR:
// SIO VV51 CMD
// USART VV51 CMD
return c.dd72.Status()
case UART_DD72RD:
// SIO VV51 Data
// USART VV51 Data
return c.dd72.Receive()
case KBD_DD78PA:
// Keyboard data
@ -36,6 +34,10 @@ func (c *ComputerType) IORead(port uint16) byte {
return c.fdc.GetFloppy()
case FDC_DATA:
return c.fdc.Data()
case FDC_TRACK:
return c.fdc.Track()
case FDC_SECT:
return c.fdc.Sector()
default:
log.Debugf("IORead from port: %x", port)
@ -89,23 +91,22 @@ func (c *ComputerType) IOWrite(port uint16, val byte) {
c.dd70.Load(2, val)
case UART_DD72RR:
// SIO VV51 CMD
// USART VV51 CMD
c.dd72.Command(val)
case UART_DD72RD:
// SIO VV51 Data
// USART VV51 Data
c.dd72.Send(val)
case FDC_CMD:
c.fdc.SetCmd(val)
case FDC_DATA:
c.fdc.SetData(val)
case FDC_TRACK:
c.fdc.SetTrack(val)
c.fdc.SetTrackNo(val)
case FDC_SECT:
c.fdc.SetSector(val)
c.fdc.SetSectorNo(val)
case FLOPPY:
c.fdc.SetFloppy(val)
default:
//log.Debugf("OUT to Unknown port (%x), %x", bp, val)
}
}

View File

@ -2,49 +2,25 @@ package okean240
import (
"fyne.io/fyne/v2"
log "github.com/sirupsen/logrus"
)
func (c *ComputerType) PutKey(key *fyne.KeyEvent) {
if key.Name == fyne.KeyUnknown {
log.Debugf("Unknown key scancode: %X", key.Physical.ScanCode)
return
code := RemapCmdKey[key.Name]
if code > 0 {
//log.Debugf("PutKey keyName: %s", key.Name)
c.ioPorts[KBD_DD78PA] = code
c.dd75.SetIRQ(RstKbdNo)
}
log.Debugf("PutKey keyName: %s", key.Name)
}
if len(c.kbdBuffer) < KbdBufferSize {
func (c *ComputerType) PutRune(key rune) {
var code byte
if (c.ioPorts[KBD_DD78PB] & 0x40) == 0 {
// No shift
code = RemapKey[key.Name]
} else {
// Shift
code = RemapKeyShift[key.Name]
}
c.ioPorts[KBD_DD78PB] &= 0x1f
if code != 0 {
c.ioPorts[KBD_DD78PA] = code
c.ioPorts[PIC_DD75RS] |= Rst1KbdFlag
} else {
switch key.Name {
case "LeftAlt", "RightAlt":
c.ioPorts[KBD_DD78PB] |= 0x80
case "LeftControl", "RightControl":
c.ioPorts[KBD_DD78PB] |= 0x20
case "LeftShift", "RightShift":
log.Debug("Shift")
c.ioPorts[KBD_DD78PB] |= 0x40
default:
log.Debugf("Unhandled KeyName: %s code: %X", key.Name, key.Physical.ScanCode)
}
}
}
//log.Debugf("Put Rune: %c Lo: %x, Hi: %x", key, key&0xff, key>>8)
c.ioPorts[KBD_DD78PA] = byte(key & 0xff)
c.dd75.SetIRQ(RstKbdNo)
}
/*
@ -62,6 +38,7 @@ func (c *ComputerType) PutKey(key *fyne.KeyEvent) {
func (c *ComputerType) PutCtrlKey(key byte) {
c.ioPorts[KBD_DD78PA] = key
c.ioPorts[PIC_DD75RS] |= Rst1KbdFlag
c.dd75.SetIRQ(RstKbdNo)
//c.ioPorts[PIC_DD75RS] |= Rst1Mask
c.ioPorts[KBD_DD78PB] &= 0x1f | 0x20
}

View File

@ -38,7 +38,7 @@ var ColorPalette = [8][4]color.RGBA{
// BgColorPalette Background color palette
var BgColorPalette = [8]color.RGBA{
CBlack, CBlue, CGreen, CLBlue, CRed, CCrimson, CYellow, CWhite,
CBlack, CBlue, CGreen, CLBlue, CRed, CCrimson /*CYellow*/, CBlack, CWhite,
}
//var MonoPalette = [8]color.RGBA{

View File

@ -2,6 +2,37 @@ package okean240
import "fyne.io/fyne/v2"
var RemapCmdKey = map[fyne.KeyName]byte{
fyne.KeyEscape: 0x1B,
fyne.KeyReturn: 0x0A,
fyne.KeyTab: 0x09,
fyne.KeyBackspace: 0x08,
fyne.KeyInsert: 0x00,
fyne.KeyDelete: 0x08,
fyne.KeyRight: 0x18,
fyne.KeyLeft: 0x08,
fyne.KeyDown: 0x0A,
fyne.KeyUp: 0x19,
fyne.KeyPageUp: 0x00,
fyne.KeyPageDown: 0x00,
fyne.KeyHome: 0x0C,
fyne.KeyEnd: 0x1A,
fyne.KeyF1: 0x00,
fyne.KeyF2: 0x00,
fyne.KeyF3: 0x00,
fyne.KeyF4: 0x00,
fyne.KeyF5: 0x00,
fyne.KeyF6: 0x00,
fyne.KeyF7: 0x00,
fyne.KeyF8: 0x00,
fyne.KeyF9: 0x00,
fyne.KeyF10: 0x00,
fyne.KeyF11: 0x00,
fyne.KeyF12: 0x00,
fyne.KeyEnter: 0x0D,
fyne.KeyUnknown: 0x00,
}
var RemapKey = map[fyne.KeyName]byte{
fyne.KeyEscape: 0x1B,
fyne.KeyReturn: 0x0A,
@ -162,5 +193,4 @@ var RemapKeyShift = map[fyne.KeyName]byte{
fyne.KeyAsterisk: 0x7E,
fyne.KeyPlus: 0x7E,
fyne.KeyBackTick: 0x60,
fyne.KeyUnknown: 0x00,
}

View File

@ -1,5 +1,7 @@
package usart
import log "github.com/sirupsen/logrus"
/**
Universal Serial Asynchronous Receiver/Transmitter
i8051, MSM82C51, КР580ВВ51
@ -133,12 +135,19 @@ func (s *I8251) Send(value byte) {
}
func (s *I8251) Receive() byte {
if s.rxe {
if len(s.bufferRx) > 0 {
res := s.bufferRx[0]
s.bufferRx = s.bufferRx[1:]
log.Debugf("ReceiveByte: %x", res)
return res
}
}
log.Debugf("ReceiveByte: empty buffer")
return 0
}
func (s *I8251) SetRxBytes(bytes []byte) {
s.bufferRx = append(s.bufferRx, bytes...)
}

View File

@ -1,4 +1,4 @@
logFile: "okemu.log"
logLevel: "info"
monitorFile: "rom/MON_r6.bin"
cpmFile: "rom/CPM_r7.bin"
monitorFile: "rom/MON_r8_9c6c6546.bin"
cpmFile: "rom/CPM_r8_bc0695e4.bin"