From b133807f05affadc62d6a201079fe66d2f837579 Mon Sep 17 00:00:00 2001 From: Roman Boykov Date: Fri, 6 Mar 2026 13:16:38 +0300 Subject: [PATCH] fdc mostly fixed --- main.go | 53 +++++- okean240/computer.go | 94 +++++++++- okean240/constants.go | 27 +-- okean240/fdc/fdc.go | 352 ++++++++++++++++++++++++++++-------- okean240/ioports.go | 25 +-- okean240/keyboard.go | 47 ++--- okean240/palette.go | 2 +- okean240/remapkey.go | 32 +++- okean240/usart/usart8251.go | 9 + okemu.yml | 4 +- 10 files changed, 490 insertions(+), 155 deletions(-) diff --git a/main.go b/main.go index 1eed26a..126ab85 100644 --- a/main.go +++ b/main.go @@ -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 diff --git a/okean240/computer.go b/okean240/computer.go index 424751a..5db80e1 100644 --- a/okean240/computer.go +++ b/okean240/computer.go @@ -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) + } +} diff --git a/okean240/constants.go b/okean240/constants.go index d779c28..bc5b278 100644 --- a/okean240/constants.go +++ b/okean240/constants.go @@ -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 diff --git a/okean240/fdc/fdc.go b/okean240/fdc/fdc.go index 101fb0e..3450c6b 100644 --- a/okean240/fdc/fdc.go +++ b/okean240/fdc/fdc.go @@ -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 +} + // diff --git a/okean240/ioports.go b/okean240/ioports.go index 401d8e2..efdbe43 100644 --- a/okean240/ioports.go +++ b/okean240/ioports.go @@ -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) - } } diff --git a/okean240/keyboard.go b/okean240/keyboard.go index 3a44d0c..348dd3e 100644 --- a/okean240/keyboard.go +++ b/okean240/keyboard.go @@ -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 } diff --git a/okean240/palette.go b/okean240/palette.go index 379dbd4..0f726ab 100644 --- a/okean240/palette.go +++ b/okean240/palette.go @@ -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{ diff --git a/okean240/remapkey.go b/okean240/remapkey.go index f3bf7da..47b23a1 100644 --- a/okean240/remapkey.go +++ b/okean240/remapkey.go @@ -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, } diff --git a/okean240/usart/usart8251.go b/okean240/usart/usart8251.go index d7ef131..7950dbd 100644 --- a/okean240/usart/usart8251.go +++ b/okean240/usart/usart8251.go @@ -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...) +} diff --git a/okemu.yml b/okemu.yml index 6a80b08..d1de349 100644 --- a/okemu.yml +++ b/okemu.yml @@ -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"