From eb4339b86a17c611905b898a7361b58aa963d00a Mon Sep 17 00:00:00 2001 From: Roman Boykov Date: Sat, 7 Mar 2026 23:58:41 +0300 Subject: [PATCH] z80 emulator refactoring and fixes --- main.go | 39 +++-- okean240/computer.go | 69 ++++----- okean240/constants.go | 149 +++++++++---------- okean240/fdc/fdc.go | 6 +- okean240/ioports.go | 56 +++---- okean240/keyboard.go | 8 +- okean240/pit/pit8253.go | 1 - okean240/remapkey.go | 322 ++++++++++++++++++++-------------------- z80em/opcode.go | 16 +- z80em/opcodeCB.go | 20 +-- z80em/opcodeDD.go | 122 +++++++-------- z80em/opcodeED.go | 40 ++--- z80em/z80em.go | 250 ++++++++++++------------------- 13 files changed, 510 insertions(+), 588 deletions(-) diff --git a/main.go b/main.go index 9256651..763700a 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,7 @@ var BuildTime = "2026-03-01" //go:embed hex/format.hex var serialBytes []byte -//go:embed bin/zexall.com +//go:embed bin/TET.COM var ramBytes []byte var needReset = false @@ -47,14 +47,14 @@ func main() { computer.SetSerialBytes(serialBytes) computer.LoadFloppy() - w, raster, label := mainWindow(computer, conf) + w, raster, label := mainWindow(computer) go emulator(computer) go screen(computer, raster, label, conf) (*w).ShowAndRun() } -func mainWindow(computer *okean240.ComputerType, emuConfig *config.OkEmuConfig) (*fyne.Window, *canvas.Raster, *widget.Label) { +func mainWindow(computer *okean240.ComputerType) (*fyne.Window, *canvas.Raster, *widget.Label) { emulatorApp := app.New() w := emulatorApp.NewWindow("Океан 240.2") w.Canvas().SetOnTypedKey( @@ -107,9 +107,9 @@ func mainWindow(computer *okean240.ComputerType, emuConfig *config.OkEmuConfig) widget.NewButton("RUN", func() { computer.SetRamBytes(ramBytes) }), - widget.NewButton("DUMP", func() { - computer.Dump(0x399, 15000) - }), + //widget.NewButton("DUMP", func() { + // computer.Dump(0x399, 15000) + //}), widget.NewSeparator(), widget.NewButton("Reset", func() { needReset = true @@ -138,10 +138,6 @@ func screen(computer *okean240.ComputerType, raster *canvas.Raster, label *widge var freq uint64 = 0 for range ticker.C { - if needReset { - computer.Reset(emuConfig) - needReset = false - } frame++ // redraw screen here fyne.Do(func() { @@ -156,20 +152,31 @@ func screen(computer *okean240.ComputerType, raster *canvas.Raster, label *widge } } +const ticksPerTicker = 3 + func emulator(computer *okean240.ComputerType) { - ticker := time.NewTicker(133 * time.Nanosecond) + ticker := time.NewTicker(66 * time.Nanosecond) var ticks = 0 - var ticksCPU = 0 + var nextClock = ticks + ticksPerTicker + //var ticksCPU = 3 for range ticker.C { - time.Sleep(133 * time.Nanosecond) + //for { + //time.Sleep(133 * time.Nanosecond) ticks++ - if ticks%5 == 0 { + if ticks%10 == 0 { // 1.5 MHz computer.TimerClk() } - if ticks > ticksCPU { - ticksCPU = ticks + computer.Do()*2 + if ticks >= nextClock { + nextClock = ticks + computer.Do()*ticksPerTicker } + if needReset { + computer.Reset() + needReset = false + } + //if ticks > ticksCPU { + //ticksCPU = ticks + computer.Do()*2 + //} } } diff --git a/okean240/computer.go b/okean240/computer.go index aff0c81..688b09a 100644 --- a/okean240/computer.go +++ b/okean240/computer.go @@ -2,7 +2,6 @@ package okean240 import ( _ "embed" - "encoding/binary" "image/color" "okemu/config" "okemu/okean240/fdc" @@ -10,7 +9,6 @@ import ( "okemu/okean240/pit" "okemu/okean240/usart" "okemu/z80em" - "os" "fyne.io/fyne/v2" log "github.com/sirupsen/logrus" @@ -54,7 +52,7 @@ type ComputerInterface interface { PutCtrlKey(shortcut fyne.Shortcut) SaveFloppy() LoadFloppy() - Dump(start uint16, length uint16) + //Dump(start uint16, length uint16) } func (c *ComputerType) M1MemRead(addr uint16) byte { @@ -97,20 +95,17 @@ func New(cfg *config.OkEmuConfig) *ComputerType { return &c } -func (c *ComputerType) Reset(cfg *config.OkEmuConfig) { +func (c *ComputerType) Reset() { 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] + //c.vShift = 0 + //c.hShift = 0 + //c.memory = Memory{} + //c.memory.Init(cfg.MonitorFile, cfg.CPMFile) + //c.dd17EnableOut = false + //c.screenWidth = 256 + //c.screenHeight = 256 + //c.vRAM = c.memory.allMemory[3] } @@ -250,25 +245,25 @@ func (c *ComputerType) SetRamBytes(bytes []byte) { //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) - } -} +//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 bc5b278..84c6ccb 100644 --- a/okean240/constants.go +++ b/okean240/constants.go @@ -5,154 +5,151 @@ package okean240 */ // USR_DD79PA User port A -const USR_DD79PA = 0x00 +//const USR_DD79PA = 0x00 // USR_DD79PB User port B -const USR_DD79PB = 0x01 +//const USR_DD79PB = 0x01 // USR_DD79PC User port C -const USR_DD79PC = 0x02 +//const USR_DD79PC = 0x02 // USR_DD79CTR Config -const USR_DD79CTR = 0x03 // Config: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI] +// Configure: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI] // Set bit: [0][xxx][bbb][0|1] +//const USR_DD79CTR = 0x03 /* * КР1818ВГ93 FDC Controller */ -// FDC_CMD FDC Command -const FDC_CMD = 0x20 +// FdcCmd FDC Command +const FdcCmd = 0x20 -// FDC_TRACK FDC Track No -const FDC_TRACK = 0x21 +// FdcTrack FDC Track No +const FdcTrack = 0x21 -// FDC_SECT FDC Sector -const FDC_SECT = 0x22 +// FdcSect FDC Sector +const FdcSect = 0x22 -// FDC_DATA FDC Data -const FDC_DATA = 0x23 +// FdcData FDC Data +const FdcData = 0x23 -// FDC_DRQ Read DRQ state from FDC -const FDC_DRQ = 0x24 +// FdcDrq Read DRQ state from FDC +const FdcDrq = 0x24 /* * Floppy Controller port */ -// FLOPPY Floppy Controller port -const FLOPPY = 0x25 // WR: 5-SSEN, 4-#DDEN, 3-INIT, 2-DRSEL, 1-MOT1, 0-MOT0 +// Floppy Controller port +// WR: 5-SSEN, 4-#DDEN, 3-INIT, 2-DRSEL, 1-MOT1, 0-MOT0 // RD: 7-MOTST, 6-SSEL, 5,4-x , 3-DRSEL, 2-MOT1, 1-MOT0, 0-INT +const Floppy = 0x25 /* * КР580ВВ55 DD78 Keyboard */ -// KBD_DD78PA Port A - Keyboard Data -const KBD_DD78PA = 0x40 +// KbdDd78pa Port A - Keyboard Data +const KbdDd78pa = 0x40 -// KBD_DD78PB Port B - JST3,SHFT,CTRL,ACK,TAPE5,TAPE4,GK,GC -const KBD_DD78PB = 0x41 +// KbdDd78pb Port B - JST3,SHFT,CTRL,ACK,TAPE5,TAPE4,GK,GC +const KbdDd78pb = 0x41 // KBD_DD78PC Port C - [PC7:5],[KBD_ACK],[PC3:0] -const KBD_DD78PC = 0x42 +//const KBD_DD78PC = 0x42 // KBD_DD78CTR Control port -const KBD_DD78CTR = 0x43 // Сonfig: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI] +// Configure: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI] // Set bit: [0][xxx][bbb][0|1] +// const KBD_DD78CTR = 0x43 /* * КР580ВИ53 DD70 */ -// TMR_DD70C1 Timer load 1 -const TMR_DD70C1 = 0x60 +// TmrDd70c1 Timer load 1 +const TmrDd70c1 = 0x60 -// TMR_DD70C2 Timer load 2 -const TMR_DD70C2 = 0x61 +// TmrDd70c2 Timer load 2 +const TmrDd70c2 = 0x61 -// TMR_DD70C3 Timer load 3 -const TMR_DD70C3 = 0x62 +// TmrDd70c3 Timer load 3 +const TmrDd70c3 = 0x62 + +// TmrDd70ctr +// Timer config: [sc1,sc0][rl1,rl0][m2,m1,m0][bcd] +// +// sc - timer, rl=01-LSB, 10-MSB, 11-LSB+MSB +// mode 000 - intRq on fin, +// 001 - one shot, +// x10 - rate gen, +// x11-sq wave +const TmrDd70ctr = 0x63 /* - TMR_DD70CTR - Timer config: [sc1,sc0][rl1,rl0][m2,m1,m0][bcd] - sc - timer, rl=01-LSB, 10-MSB, 11-LSB+MSB - mode 000 - intRq on fin, - 001 - one shot, - x10 - rate gen, - x11-sq wave -*/ -const TMR_DD70CTR = 0x63 - -/* - * Programmable Interrupt controller PIC KR580VV59 + * Programmable Interrupt controller PIC КР580ВН59 */ const RstKbdNo = 1 const RstTimerNo = 4 -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 +//const Rst0Mask = 0x01 // System interrupt +//const Rst1Mask = 0x02 // Keyboard interrupt +//const Rst2Mask = 0x04 // Serial interface interrupt +//const Rst3Mask = 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_DD75A Port A (a0=0) -const PIC_DD75A = 0x80 +// PicDd75a Port A (a0=0) +//const PicDd75a = 0x80 // PIC_DD75B Port B (a0=1) -const PIC_DD75B = 0x81 +//const PIC_DD75B = 0x81 /* * КР580ВВ51 DD72 */ -// UART_DD72RD Serial data -const UART_DD72RD = 0xA0 +// UartDd72rd Serial data +const UartDd72rd = 0xA0 -// UART_DD72RR Serial status [RST,RQ_RX,RST_ERR,PAUSE,RX_EN,RX_RDY,TX_RDY] -const UART_DD72RR = 0xA1 +// UartDd72rr Serial status [RST,RQ_RX,RST_ERR,PAUSE,RX_EN,RX_RDY,TX_RDY] +const UartDd72rr = 0xA1 /* * КР580ВВ55 DD17 System port */ -// Port A - VShift[8..1] Vertical shift -const SYS_DD17PA = 0xC0 +// SysDd17pa Port A - VShift[8..1] Vertical shift +const SysDd17pa = 0xC0 -// Port B - Memory mapper [ROM14,13][REST][ENROM-][A18,17,16][32k] -const SYS_DD17PB = 0xC1 +// SysDd17pb Port B - Memory mapper [ROM14,13][REST][ENROM-][A18,17,16][32k] +const SysDd17pb = 0xC1 -// Port C - HShift[HS5..1,SB3..1] Horisontal shift -const SYS_DD17PC = 0xC2 +// SysDd17pc Port C - HShift[HS5..1,SB3..1] Horisontal shift +const SysDd17pc = 0xC2 -/* - * SYS_DD17CTR - * Сonfig: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI] - * Set bit: [0][xxx][bbb][0|1] - */ -const SYS_DD17CTR = 0xC3 +// SysDd17ctr Configure: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI] +// Set bit: [0][xxx][bbb][0|1] +const SysDd17ctr = 0xC3 /* * КР580ВВ55 DD67 */ // LPT_DD67PA Port A - Printer Data -const LPT_DD67PA = 0xE0 +//const LPT_DD67PA = 0xE0 // VID_DD67PB Port B - Video control [VSU,C/M,FL3:1,COL3:1] -const VID_DD67PB = 0xE1 +//const VID_DD67PB = 0xE1 // DD67PC Port C - [USER3:1, STB-LP, BELL, TAPE3:1] -const DD67PC = 0xE2 +//const DD67PC = 0xE2 -/* - * DD67CTR - * Сonfig: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI] - * Set bit: [0][xxx][bbb][0|1] - */ -const DD67CTR = 0xE3 +// DD67CTR +// Configure: [1][ma1,ma0][0-aO|1-aI],[0-chO,1-chI],[mb],[0-bO|1-bI],[0-clO,1-clI] +// Set bit: [0][xxx][bbb][0|1] +// const DD67CTR = 0xE3 diff --git a/okean240/fdc/fdc.go b/okean240/fdc/fdc.go index f27f5c5..e7554a7 100644 --- a/okean240/fdc/fdc.go +++ b/okean240/fdc/fdc.go @@ -48,9 +48,9 @@ const ( ) const ( - StatusTR0 = 0x04 // TR0 - Head at track 0 - StatusRNF = 0x10 // RNF - Record not found - StatusSeekError = 0x10 // Sector out of disk + StatusTR0 = 0x04 // TR0 - Head at track 0 + StatusRNF = 0x10 // RNF - Record not found + // StatusSeekError = 0x10 // Sector out of disk StatusHeadLoaded = 0x20 // Head on disk ) diff --git a/okean240/ioports.go b/okean240/ioports.go index 0d069b9..14bcc10 100644 --- a/okean240/ioports.go +++ b/okean240/ioports.go @@ -12,31 +12,31 @@ import log "github.com/sirupsen/logrus" func (c *ComputerType) IORead(port uint16) byte { switch port & 0x00ff { - case PIC_DD75A: + case PicDd75a: // PIO xx59, get IRR register return c.pic.IRR() - case UART_DD72RR: + case UartDd72rr: // USART VV51 CMD return c.usart.Status() - case UART_DD72RD: + case UartDd72rd: // USART VV51 Data return c.usart.Receive() - case KBD_DD78PA: + case KbdDd78pa: // Keyboard data - return c.ioPorts[KBD_DD78PA] - case KBD_DD78PB: - return c.ioPorts[KBD_DD78PB] - case FDC_CMD: + return c.ioPorts[KbdDd78pa] + case KbdDd78pb: + return c.ioPorts[KbdDd78pb] + case FdcCmd: return c.fdc.Status() - case FDC_DRQ: + case FdcDrq: return c.fdc.Drq() - case FLOPPY: + case Floppy: return c.fdc.GetFloppy() - case FDC_DATA: + case FdcData: return c.fdc.Data() - case FDC_TRACK: + case FdcTrack: return c.fdc.Track() - case FDC_SECT: + case FdcSect: return c.fdc.Sector() default: @@ -50,11 +50,11 @@ func (c *ComputerType) IOWrite(port uint16, val byte) { c.ioPorts[bp] = val //log.Debugf("OUT (%x), %x", bp, val) switch bp { - case SYS_DD17PB: + case SysDd17pb: if c.dd17EnableOut { c.memory.Configure(val) } - case SYS_DD17CTR: + case SysDd17ctr: c.dd17EnableOut = val == 0x80 case VID_DD67PB: if val&VidVsuBit == 0 { @@ -73,38 +73,38 @@ func (c *ComputerType) IOWrite(port uint16, val byte) { } c.palette = val & 0x07 c.bgColor = (val >> 3) & 0x07 - case SYS_DD17PA: + case SysDd17pa: c.vShift = val - case SYS_DD17PC: + case SysDd17pc: c.hShift = val - case TMR_DD70CTR: + case TmrDd70ctr: // Timer VI63 config register c.pit.Configure(val) - case TMR_DD70C1: + case TmrDd70c1: // Timer VI63 counter0 register c.pit.Load(0, val) - case TMR_DD70C2: + case TmrDd70c2: // Timer VI63 counter1 register c.pit.Load(1, val) - case TMR_DD70C3: + case TmrDd70c3: // Timer VI63 counter2 register c.pit.Load(2, val) - case UART_DD72RR: + case UartDd72rr: // USART VV51 CMD c.usart.Command(val) - case UART_DD72RD: + case UartDd72rd: // USART VV51 Data c.usart.Send(val) - case FDC_CMD: + case FdcCmd: c.fdc.SetCmd(val) - case FDC_DATA: + case FdcData: c.fdc.SetData(val) - case FDC_TRACK: + case FdcTrack: c.fdc.SetTrackNo(val) - case FDC_SECT: + case FdcSect: c.fdc.SetSectorNo(val) - case FLOPPY: + 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 f01dc5f..dd7401d 100644 --- a/okean240/keyboard.go +++ b/okean240/keyboard.go @@ -9,7 +9,7 @@ func (c *ComputerType) PutKey(key *fyne.KeyEvent) { code := RemapCmdKey[key.Name] if code > 0 { //log.Debugf("PutKey keyName: %s", key.Name) - c.ioPorts[KBD_DD78PA] = code + c.ioPorts[KbdDd78pa] = code c.pic.SetIRQ(RstKbdNo) } @@ -19,7 +19,7 @@ func (c *ComputerType) PutRune(key rune) { //log.Debugf("Put Rune: %c Lo: %x, Hi: %x", key, key&0xff, key>>8) - c.ioPorts[KBD_DD78PA] = byte(key & 0xff) + c.ioPorts[KbdDd78pa] = byte(key & 0xff) c.pic.SetIRQ(RstKbdNo) } @@ -37,8 +37,8 @@ func (c *ComputerType) PutRune(key rune) { */ func (c *ComputerType) PutCtrlKey(key byte) { - c.ioPorts[KBD_DD78PA] = key + c.ioPorts[KbdDd78pa] = key c.pic.SetIRQ(RstKbdNo) //c.ioPorts[PIC_DD75RS] |= Rst1Mask - c.ioPorts[KBD_DD78PB] &= 0x1f | 0x20 + c.ioPorts[KbdDd78pb] &= 0x1f | 0x20 } diff --git a/okean240/pit/pit8253.go b/okean240/pit/pit8253.go index 1de7999..9cb5fff 100644 --- a/okean240/pit/pit8253.go +++ b/okean240/pit/pit8253.go @@ -39,7 +39,6 @@ type I8253 struct { } type I8253Interface interface { - //Init() Configure(value byte) Load(chNo int, value byte) Counter(chNo int) uint16 diff --git a/okean240/remapkey.go b/okean240/remapkey.go index 4e3f4e7..dd220be 100644 --- a/okean240/remapkey.go +++ b/okean240/remapkey.go @@ -33,164 +33,164 @@ var RemapCmdKey = map[fyne.KeyName]byte{ fyne.KeyUnknown: 0x00, } -var RemapKey = 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.Key0: 0x30, - fyne.Key1: 0x31, - fyne.Key2: 0x32, - fyne.Key3: 0x33, - fyne.Key4: 0x34, - fyne.Key5: 0x35, - fyne.Key6: 0x36, - fyne.Key7: 0x37, - fyne.Key8: 0x38, - fyne.Key9: 0x39, - fyne.KeyA: 0x61, - fyne.KeyB: 0x62, - fyne.KeyC: 0x63, - fyne.KeyD: 0x64, - fyne.KeyE: 0x65, - fyne.KeyF: 0x66, - fyne.KeyG: 0x67, - fyne.KeyH: 0x68, - fyne.KeyI: 0x69, - fyne.KeyJ: 0x6a, - fyne.KeyK: 0x6b, - fyne.KeyL: 0x6c, - fyne.KeyM: 0x6d, - fyne.KeyN: 0x6e, - fyne.KeyO: 0x6f, - fyne.KeyP: 0x70, - fyne.KeyQ: 0x71, - fyne.KeyR: 0x72, - fyne.KeyS: 0x73, - fyne.KeyT: 0x74, - fyne.KeyU: 0x75, - fyne.KeyV: 0x76, - fyne.KeyW: 0x77, - fyne.KeyX: 0x78, - fyne.KeyY: 0x79, - fyne.KeyZ: 0x7A, - fyne.KeySpace: 0x20, - fyne.KeyApostrophe: 0x27, - fyne.KeyComma: 0x2c, - fyne.KeyMinus: 0x2d, - fyne.KeyPeriod: 0x2E, - fyne.KeySlash: 0x2F, - fyne.KeyBackslash: 0x5C, - fyne.KeyLeftBracket: 0x5B, - fyne.KeyRightBracket: 0x5D, - fyne.KeySemicolon: 0x3B, - fyne.KeyEqual: 0x3D, - fyne.KeyAsterisk: 0x2A, - fyne.KeyPlus: 0x2B, - fyne.KeyBackTick: 0x60, - fyne.KeyUnknown: 0x00, -} - -var RemapKeyShift = 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.Key0: 0x29, - fyne.Key1: 0x21, - fyne.Key2: 0x40, - fyne.Key3: 0x23, - fyne.Key4: 0x24, - fyne.Key5: 0x25, - fyne.Key6: 0x5E, - fyne.Key7: 0x26, - fyne.Key8: 0x2A, - fyne.Key9: 0x28, - fyne.KeyA: 0x41, - fyne.KeyB: 0x42, - fyne.KeyC: 0x43, - fyne.KeyD: 0x44, - fyne.KeyE: 0x45, - fyne.KeyF: 0x46, - fyne.KeyG: 0x47, - fyne.KeyH: 0x48, - fyne.KeyI: 0x49, - fyne.KeyJ: 0x4a, - fyne.KeyK: 0x4b, - fyne.KeyL: 0x4c, - fyne.KeyM: 0x4d, - fyne.KeyN: 0x4e, - fyne.KeyO: 0x4f, - fyne.KeyP: 0x50, - fyne.KeyQ: 0x51, - fyne.KeyR: 0x52, - fyne.KeyS: 0x53, - fyne.KeyT: 0x54, - fyne.KeyU: 0x55, - fyne.KeyV: 0x56, - fyne.KeyW: 0x57, - fyne.KeyX: 0x58, - fyne.KeyY: 0x59, - fyne.KeyZ: 0x5A, - fyne.KeySpace: 0x20, - fyne.KeyApostrophe: 0x22, - fyne.KeyComma: 0x3C, - fyne.KeyMinus: 0x5F, - fyne.KeyPeriod: 0x3E, - fyne.KeySlash: 0x3F, - fyne.KeyBackslash: 0x7C, - fyne.KeyLeftBracket: 0x7B, - fyne.KeyRightBracket: 0x7D, - fyne.KeySemicolon: 0x3A, - fyne.KeyEqual: 0x2B, - fyne.KeyAsterisk: 0x7E, - fyne.KeyPlus: 0x7E, - fyne.KeyBackTick: 0x60, -} +//var RemapKey = 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.Key0: 0x30, +// fyne.Key1: 0x31, +// fyne.Key2: 0x32, +// fyne.Key3: 0x33, +// fyne.Key4: 0x34, +// fyne.Key5: 0x35, +// fyne.Key6: 0x36, +// fyne.Key7: 0x37, +// fyne.Key8: 0x38, +// fyne.Key9: 0x39, +// fyne.KeyA: 0x61, +// fyne.KeyB: 0x62, +// fyne.KeyC: 0x63, +// fyne.KeyD: 0x64, +// fyne.KeyE: 0x65, +// fyne.KeyF: 0x66, +// fyne.KeyG: 0x67, +// fyne.KeyH: 0x68, +// fyne.KeyI: 0x69, +// fyne.KeyJ: 0x6a, +// fyne.KeyK: 0x6b, +// fyne.KeyL: 0x6c, +// fyne.KeyM: 0x6d, +// fyne.KeyN: 0x6e, +// fyne.KeyO: 0x6f, +// fyne.KeyP: 0x70, +// fyne.KeyQ: 0x71, +// fyne.KeyR: 0x72, +// fyne.KeyS: 0x73, +// fyne.KeyT: 0x74, +// fyne.KeyU: 0x75, +// fyne.KeyV: 0x76, +// fyne.KeyW: 0x77, +// fyne.KeyX: 0x78, +// fyne.KeyY: 0x79, +// fyne.KeyZ: 0x7A, +// fyne.KeySpace: 0x20, +// fyne.KeyApostrophe: 0x27, +// fyne.KeyComma: 0x2c, +// fyne.KeyMinus: 0x2d, +// fyne.KeyPeriod: 0x2E, +// fyne.KeySlash: 0x2F, +// fyne.KeyBackslash: 0x5C, +// fyne.KeyLeftBracket: 0x5B, +// fyne.KeyRightBracket: 0x5D, +// fyne.KeySemicolon: 0x3B, +// fyne.KeyEqual: 0x3D, +// fyne.KeyAsterisk: 0x2A, +// fyne.KeyPlus: 0x2B, +// fyne.KeyBackTick: 0x60, +// fyne.KeyUnknown: 0x00, +//} +// +//var RemapKeyShift = 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.Key0: 0x29, +// fyne.Key1: 0x21, +// fyne.Key2: 0x40, +// fyne.Key3: 0x23, +// fyne.Key4: 0x24, +// fyne.Key5: 0x25, +// fyne.Key6: 0x5E, +// fyne.Key7: 0x26, +// fyne.Key8: 0x2A, +// fyne.Key9: 0x28, +// fyne.KeyA: 0x41, +// fyne.KeyB: 0x42, +// fyne.KeyC: 0x43, +// fyne.KeyD: 0x44, +// fyne.KeyE: 0x45, +// fyne.KeyF: 0x46, +// fyne.KeyG: 0x47, +// fyne.KeyH: 0x48, +// fyne.KeyI: 0x49, +// fyne.KeyJ: 0x4a, +// fyne.KeyK: 0x4b, +// fyne.KeyL: 0x4c, +// fyne.KeyM: 0x4d, +// fyne.KeyN: 0x4e, +// fyne.KeyO: 0x4f, +// fyne.KeyP: 0x50, +// fyne.KeyQ: 0x51, +// fyne.KeyR: 0x52, +// fyne.KeyS: 0x53, +// fyne.KeyT: 0x54, +// fyne.KeyU: 0x55, +// fyne.KeyV: 0x56, +// fyne.KeyW: 0x57, +// fyne.KeyX: 0x58, +// fyne.KeyY: 0x59, +// fyne.KeyZ: 0x5A, +// fyne.KeySpace: 0x20, +// fyne.KeyApostrophe: 0x22, +// fyne.KeyComma: 0x3C, +// fyne.KeyMinus: 0x5F, +// fyne.KeyPeriod: 0x3E, +// fyne.KeySlash: 0x3F, +// fyne.KeyBackslash: 0x7C, +// fyne.KeyLeftBracket: 0x7B, +// fyne.KeyRightBracket: 0x7D, +// fyne.KeySemicolon: 0x3A, +// fyne.KeyEqual: 0x2B, +// fyne.KeyAsterisk: 0x7E, +// fyne.KeyPlus: 0x7E, +// fyne.KeyBackTick: 0x60, +//} diff --git a/z80em/opcode.go b/z80em/opcode.go index f111809..fda8fcb 100644 --- a/z80em/opcode.go +++ b/z80em/opcode.go @@ -190,7 +190,7 @@ var instructions = []func(s *Z80Type){ }, // 0x22 : LD (nn), HL 0x22: func(s *Z80Type) { - addr := s.getAddr() + addr := s.nextWord() s.core.MemWrite(addr, s.L) s.core.MemWrite(addr+1, s.H) }, @@ -252,7 +252,7 @@ var instructions = []func(s *Z80Type){ }, // 0x2a : LD HL, (nn) 0x2A: func(s *Z80Type) { - addr := s.getAddr() + addr := s.nextWord() s.L = s.core.MemRead(addr) s.H = s.core.MemRead(addr + 1) }, @@ -293,7 +293,7 @@ var instructions = []func(s *Z80Type){ }, // 0x32 : LD (nn), A 0x32: func(s *Z80Type) { - s.core.MemWrite(s.getAddr(), s.A) + s.core.MemWrite(s.nextWord(), s.A) }, // 0x33 : INC SP 0x33: func(s *Z80Type) { @@ -329,7 +329,7 @@ var instructions = []func(s *Z80Type){ }, // 0x3a : LD A, (nn) 0x3A: func(s *Z80Type) { - s.A = s.core.MemRead(s.getAddr()) + s.A = s.core.MemRead(s.nextWord()) }, // 0x3b : DEC SP 0x3B: func(s *Z80Type) { @@ -648,10 +648,10 @@ var instructions = []func(s *Z80Type){ }, } -func (z *Z80Type) getAddr() uint16 { +func (z *Z80Type) nextWord() uint16 { z.PC++ - addr := uint16(z.core.MemRead(z.PC)) + word := uint16(z.core.MemRead(z.PC)) z.PC++ - addr |= uint16(z.core.MemRead(z.PC)) << 8 - return addr + word |= uint16(z.core.MemRead(z.PC)) << 8 + return word } diff --git a/z80em/opcodeCB.go b/z80em/opcodeCB.go index 3f33156..7d8fc42 100644 --- a/z80em/opcodeCB.go +++ b/z80em/opcodeCB.go @@ -1,7 +1,7 @@ package z80em func (z *Z80Type) opcodeCB() { - z.R = (z.R & 0x80) | (((z.R & 0x7f) + 1) & 0x7f) + z.incR() z.PC++ opcode := z.core.M1MemRead(z.PC) bitNumber := (opcode & 0x38) >> 3 @@ -29,28 +29,30 @@ func (z *Z80Type) opcodeCB() { } } else if opcode < 0x80 { // BIT instructions + mask := byte(1 << bitNumber) switch regCode { case 0: - z.Flags.Z = z.B&(1<>8)) + s.setWord(s.nextWord(), s.IX) }, // 0x23 : INC IX 0x23: func(s *Z80Type) { @@ -42,8 +40,7 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x2a : LD IX, (nn) 0x2A: func(s *Z80Type) { - addr := s.getAddr() - s.IX = (uint16(s.core.MemRead(addr)) << 8) | uint16(s.core.MemRead(addr+1)) + s.IX = s.getWord(s.nextWord()) }, // 0x2b : DEC IX 0x2B: func(s *Z80Type) { @@ -94,8 +91,7 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x46 : LD B, (IX+n) 0x46: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.B = s.core.MemRead(offset) + s.B = s.core.MemRead(s.getOffset(s.IX)) }, // 0x4c : LD C, IXH (Undocumented) 0x4C: func(s *Z80Type) { @@ -107,8 +103,7 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x4e : LD C, (IX+n) 0x4E: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.C = s.core.MemRead(offset) + s.C = s.core.MemRead(s.getOffset(s.IX)) }, // 0x54 : LD D, IXH (Undocumented) 0x54: func(s *Z80Type) { @@ -116,7 +111,7 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x55 : LD D, IXL (Undocumented) 0x55: func(s *Z80Type) { - s.D = byte(s.IX & 0x00ff) + s.D = byte(s.IX) }, // 0x56 : LD D, (IX+n) 0x56: func(s *Z80Type) { @@ -125,12 +120,11 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x5d : LD E, IXL (Undocumented) 0x5D: func(s *Z80Type) { - s.E = byte(s.IX & 0x00ff) + s.E = byte(s.IX) }, // 0x5e : LD E, (IX+n) 0x5E: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.E = s.core.MemRead(offset) + s.E = s.core.MemRead(s.getOffset(s.IX)) }, // 0x60 : LD IXH, B (Undocumented) 0x60: func(s *Z80Type) { @@ -158,8 +152,7 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x66 : LD H, (IX+n) 0x66: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.H = s.core.MemRead(offset) + s.H = s.core.MemRead(s.getOffset(s.IX)) }, // 0x67 : LD IXH, A (Undocumented) 0x67: func(s *Z80Type) { @@ -191,8 +184,7 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x6e : LD L, (IX+n) 0x6e: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.L = s.core.MemRead(offset) + s.L = s.core.MemRead(s.getOffset(s.IX)) }, // 0x6f : LD IXL, A (Undocumented) 0x6f: func(s *Z80Type) { @@ -200,38 +192,31 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x70 : LD (IX+n), B 0x70: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.core.MemWrite(offset, s.B) + s.core.MemWrite(s.getOffset(s.IX), s.B) }, // 0x71 : LD (IX+n), C 0x71: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.core.MemWrite(offset, s.C) + s.core.MemWrite(s.getOffset(s.IX), s.C) }, // 0x72 : LD (IX+n), D 0x72: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.core.MemWrite(offset, s.D) + s.core.MemWrite(s.getOffset(s.IX), s.D) }, // 0x73 : LD (IX+n), E 0x73: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.core.MemWrite(offset, s.E) + s.core.MemWrite(s.getOffset(s.IX), s.E) }, // 0x74 : LD (IX+n), H 0x74: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.core.MemWrite(offset, s.H) + s.core.MemWrite(s.getOffset(s.IX), s.H) }, // 0x75 : LD (IX+n), L 0x75: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.core.MemWrite(offset, s.L) + s.core.MemWrite(s.getOffset(s.IX), s.L) }, // 0x77 : LD (IX+n), A 0x77: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.core.MemWrite(offset, s.A) + s.core.MemWrite(s.getOffset(s.IX), s.A) }, // 0x7c : LD A, IXH (Undocumented) 0x7C: func(s *Z80Type) { @@ -243,8 +228,7 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x7e : LD A, (IX+n) 0x7E: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.A = s.core.MemRead(offset) + s.A = s.core.MemRead(s.getOffset(s.IX)) }, // 0x84 : ADD A, IXH (Undocumented) 0x84: func(s *Z80Type) { @@ -252,12 +236,11 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x85 : ADD A, IXL (Undocumented) 0x85: func(s *Z80Type) { - s.doAdd(byte(s.IX & 0x00ff)) + s.doAdd(byte(s.IX)) }, // 0x86 : ADD A, (IX+n) 0x86: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.doAdd(s.core.MemRead(offset)) + s.doAdd(s.core.MemRead(s.getOffset(s.IX))) }, // 0x8c : ADC A, IXH (Undocumented) 0x8C: func(s *Z80Type) { @@ -265,12 +248,11 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x8d : ADC A, IXL (Undocumented) 0x8D: func(s *Z80Type) { - s.doAdc(byte(s.IX & 0x00ff)) + s.doAdc(byte(s.IX)) }, // 0x8e : ADC A, (IX+n) 0x8E: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.doAdc(s.core.MemRead(offset)) + s.doAdc(s.core.MemRead(s.getOffset(s.IX))) }, // 0x94 : SUB IXH (Undocumented) 0x94: func(s *Z80Type) { @@ -278,12 +260,11 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x95 : SUB IXL (Undocumented) 0x95: func(s *Z80Type) { - s.doSub(byte(s.IX & 0x00ff)) + s.doSub(byte(s.IX)) }, // 0x96 : SUB A, (IX+n) 0x96: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.doSub(s.core.MemRead(offset)) + s.doSub(s.core.MemRead(s.getOffset(s.IX))) }, // 0x9c : SBC IXH (Undocumented) 0x9C: func(s *Z80Type) { @@ -291,12 +272,11 @@ var ddInstructions = []func(s *Z80Type){ }, // 0x9d : SBC IXL (Undocumented) 0x9D: func(s *Z80Type) { - s.doSbc(byte(s.IX & 0x00ff)) + s.doSbc(byte(s.IX)) }, // 0x9e : SBC A, (IX+n) 0x9E: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.doSbc(s.core.MemRead(offset)) + s.doSbc(s.core.MemRead(s.getOffset(s.IX))) }, // 0xa4 : AND IXH (Undocumented) 0xA4: func(s *Z80Type) { @@ -304,12 +284,11 @@ var ddInstructions = []func(s *Z80Type){ }, // 0xa5 : AND IXL (Undocumented) 0xA5: func(s *Z80Type) { - s.doAnd(byte(s.IX & 0x00ff)) + s.doAnd(byte(s.IX)) }, // 0xa6 : AND A, (IX+n) 0xA6: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.doAnd(s.core.MemRead(offset)) + s.doAnd(s.core.MemRead(s.getOffset(s.IX))) }, // 0xac : XOR IXH (Undocumented) 0xAC: func(s *Z80Type) { @@ -317,12 +296,11 @@ var ddInstructions = []func(s *Z80Type){ }, // 0xad : XOR IXL (Undocumented) 0xAD: func(s *Z80Type) { - s.doXor(byte(s.IX & 0x00ff)) + s.doXor(byte(s.IX)) }, // 0xae : XOR A, (IX+n) 0xAE: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.doXor(s.core.MemRead(offset)) + s.doXor(s.core.MemRead(s.getOffset(s.IX))) }, // 0xb4 : OR IXH (Undocumented) 0xB4: func(s *Z80Type) { @@ -330,12 +308,11 @@ var ddInstructions = []func(s *Z80Type){ }, // 0xb5 : OR IXL (Undocumented) 0xB5: func(s *Z80Type) { - s.doOr(byte(s.IX & 0x00ff)) + s.doOr(byte(s.IX)) }, // 0xb6 : OR A, (IX+n) 0xB6: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.doOr(s.core.MemRead(offset)) + s.doOr(s.core.MemRead(s.getOffset(s.IX))) }, // 0xbc : CP IXH (Undocumented) 0xBC: func(s *Z80Type) { @@ -343,12 +320,11 @@ var ddInstructions = []func(s *Z80Type){ }, // 0xbd : CP IXL (Undocumented) 0xBD: func(s *Z80Type) { - s.doCp(byte(s.IX & 0x00ff)) + s.doCp(byte(s.IX)) }, // 0xbe : CP A, (IX+n) 0xBE: func(s *Z80Type) { - offset := s.getOffset(s.IX) - s.doCp(s.core.MemRead(offset)) + s.doCp(s.core.MemRead(s.getOffset(s.IX))) }, // 0xcb : CB Prefix (IX bit instructions) 0xCB: func(s *Z80Type) { @@ -360,11 +336,9 @@ var ddInstructions = []func(s *Z80Type){ }, // 0xe3 : EX (SP), IX 0xE3: func(s *Z80Type) { - temp := s.IX - s.IX = uint16(s.core.MemRead(s.SP)) - s.IX |= uint16(s.core.MemRead(s.SP+1)) << 8 - s.core.MemWrite(s.SP, byte(temp&0x00ff)) - s.core.MemWrite(s.SP+1, byte(temp>>8)) + ix := s.IX + s.IX = s.getWord(s.SP) + s.setWord(s.SP, ix) }, // 0xe5 : PUSH IX 0xE5: func(s *Z80Type) { @@ -393,13 +367,12 @@ func (z *Z80Type) getOffset(reg uint16) uint16 { } func (z *Z80Type) opcodeDD() { - z.R = (z.R & 0x80) | (((z.R & 0x7f) + 1) & 0x7f) + z.incR() z.PC++ opcode := z.core.M1MemRead(z.PC) fun := ddInstructions[opcode] if fun != nil { - //func = func.bind(this); fun(z) z.CycleCounter += CycleCountsDd[opcode] } else { @@ -481,3 +454,22 @@ func (z *Z80Type) opcodeDDCB() { z.CycleCounter += CycleCountsCb[opcode] + 8 } + +// opcodeFD do same for IY as for IX (DD prefix) +func (z *Z80Type) opcodeFD() { + z.incR() + z.PC++ + opcode := z.core.M1MemRead(z.PC) + fun := ddInstructions[opcode] + if fun != nil { + var temp = z.IX + z.IX = z.IY + fun(z) + z.IY = z.IX + z.IX = temp + z.CycleCounter += CycleCountsDd[opcode] + } else { + z.PC-- + z.CycleCounter += CycleCounts[0] + } +} diff --git a/z80em/opcodeED.go b/z80em/opcodeED.go index 8c9ae06..7afbb13 100644 --- a/z80em/opcodeED.go +++ b/z80em/opcodeED.go @@ -3,21 +3,19 @@ package z80em var edInstructions = []func(s *Z80Type){ // 0x40 : IN B, (C) 0x40: func(s *Z80Type) { - s.B = s.doIn((uint16(s.B) << 8) | uint16(s.C)) + s.B = s.doIn(s.bc()) }, // 0x41 : OUT (C), B 0x41: func(s *Z80Type) { - s.core.IOWrite((uint16(s.B)<<8)|uint16(s.C), s.B) + s.core.IOWrite(s.bc(), s.B) }, // 0x42 : SBC HL, BC 0x42: func(s *Z80Type) { - s.doHlSbc(uint16(s.C) | (uint16(s.B) << 8)) + s.doHlSbc(s.bc()) }, // 0x43 : LD (nn), BC 0x43: func(s *Z80Type) { - addr := s.getAddr() - s.core.MemWrite(addr, s.C) - s.core.MemWrite(addr+1, s.B) + s.setWord(s.nextWord(), s.bc()) }, // 0x44 : NEG 0x44: func(s *Z80Type) { @@ -50,9 +48,7 @@ var edInstructions = []func(s *Z80Type){ }, // 0x4b : LD BC, (nn) 0x4B: func(s *Z80Type) { - addr := s.getAddr() - s.C = s.core.MemRead(addr) - s.B = s.core.MemRead(addr + 1) + s.setBc(s.getWord(s.nextWord())) }, // 0x4c : NEG (Undocumented) 0x4C: func(s *Z80Type) { @@ -84,9 +80,7 @@ var edInstructions = []func(s *Z80Type){ }, // 0x53 : LD (nn), DE 0x53: func(s *Z80Type) { - addr := s.getAddr() - s.core.MemWrite(addr, s.E) - s.core.MemWrite(addr+1, s.D) + s.setWord(s.nextWord(), s.de()) }, // 0x54 : NEG (Undocumented) 0x54: func(s *Z80Type) { @@ -126,9 +120,7 @@ var edInstructions = []func(s *Z80Type){ }, // 0x5b : LD DE, (nn) 0x5B: func(s *Z80Type) { - addr := s.getAddr() - s.E = s.core.MemRead(addr) - s.D = s.core.MemRead(addr + 1) + s.setDe(s.getWord(s.nextWord())) }, // 0x5c : NEG (Undocumented) 0x5C: func(s *Z80Type) { @@ -168,9 +160,7 @@ var edInstructions = []func(s *Z80Type){ }, // 0x63 : LD (nn), HL (Undocumented) 0x63: func(s *Z80Type) { - addr := s.getAddr() - s.core.MemWrite(addr, s.L) - s.core.MemWrite(addr+1, s.H) + s.setWord(s.nextWord(), s.hl()) }, // 0x64 : NEG (Undocumented) 0x64: func(s *Z80Type) { @@ -215,9 +205,7 @@ var edInstructions = []func(s *Z80Type){ }, // 0x6b : LD HL, (nn) (Undocumented) 0x6B: func(s *Z80Type) { - addr := s.getAddr() - s.L = s.core.MemRead(addr) - s.H = s.core.MemRead(addr + 1) + s.setHl(s.getWord(s.nextWord())) }, // 0x6C : NEG (Undocumented) 0x6C: func(s *Z80Type) { @@ -262,9 +250,7 @@ var edInstructions = []func(s *Z80Type){ }, // 0x73 : LD (nn), SP 0x73: func(s *Z80Type) { - addr := s.getAddr() - s.core.MemWrite(addr, byte(s.SP&0x00ff)) - s.core.MemWrite(addr+1, byte(s.SP>>8)) + s.setWord(s.nextWord(), s.SP) }, // 0x74 : NEG (Undocumented) 0x74: func(s *Z80Type) { @@ -293,9 +279,7 @@ var edInstructions = []func(s *Z80Type){ }, // 0x7b : LD SP, (nn) 0x7B: func(s *Z80Type) { - addr := s.getAddr() - s.SP = uint16(s.core.MemRead(addr)) - s.SP |= uint16(s.core.MemRead(addr+1)) << 8 + s.SP = s.getWord(s.nextWord()) }, // 0x7c : NEG (Undocumented) 0x7C: func(s *Z80Type) { @@ -409,7 +393,7 @@ var edInstructions = []func(s *Z80Type){ } func (z *Z80Type) opcodeED() { - z.R = (z.R & 0x80) | (((z.R & 0x7f) + 1) & 0x7f) + z.incR() z.PC++ opcode := z.core.M1MemRead(z.PC) diff --git a/z80em/z80em.go b/z80em/z80em.go index f2eb13e..00f48e9 100644 --- a/z80em/z80em.go +++ b/z80em/z80em.go @@ -52,7 +52,7 @@ type Z80Type struct { } type MemIoRW interface { - // M1MemRead Read byte from memory for specified address + // M1MemRead Read byte from memory for specified address @ M1 cycle M1MemRead(addr uint16) byte // MemRead Read byte from memory for specified address MemRead(addr uint16) byte @@ -198,12 +198,7 @@ func New(memIoRW MemIoRW) *Z80Type { func (z *Z80Type) RunInstruction() byte { - // R is incremented at the start of every instruction cycle, - // before the instruction actually runs. - // The high bit of R is not affected by this increment, - // it can only be changed using the LD R, A instruction. - // Note: also a HALT does increment the R register. - z.R = (z.R & 0x80) | (((z.R & 0x7f) + 1) & 0x7f) + z.incR() if !z.Halted { // If the previous instruction was a DI or an EI, @@ -242,11 +237,13 @@ func (z *Z80Type) RunInstruction() byte { cycleCounter := z.CycleCounter z.CycleCounter = 0 return cycleCounter - } else { // HALTED - // During HALT, NOPs are executed which is 4T - z.core.M1MemRead(z.PC) // HALT does a normal M1 fetch to keep the memory refresh active. The result is ignored (NOP). - return 4 } + + // HALTED + // During HALT, NOPs are executed which is 4T + z.core.M1MemRead(z.PC) // HALT does a normal M1 fetch to keep the memory refresh active. The result is ignored (NOP). + return 4 + } // Simulates pulsing the processor's INT (or NMI) pin @@ -262,7 +259,7 @@ func (z *Z80Type) interrupt(nonMaskable bool, data byte) { // The high bit of R is not affected by this increment, // it can only be changed using the LD R, A instruction. - z.R = (z.R & 0x80) | (((z.R & 0x7f) + 1) & 0x7f) + z.incR() // Non-maskable interrupts are always handled the same way; // clear IFF1 and then do a CALL 0x0066. @@ -283,7 +280,7 @@ func (z *Z80Type) interrupt(nonMaskable bool, data byte) { // The high bit of R is not affected by this increment, // it can only be changed using the LD R,A instruction. - z.R = (z.R & 0x80) | (((z.R & 0x7f) + 1) & 0x7f) + z.incR() z.Halted = false z.Iff1 = 0 @@ -312,7 +309,7 @@ func (z *Z80Type) interrupt(nonMaskable bool, data byte) { // but it doesn't appear that this is actually the case on the hardware, // so we don't attempt to enforce that here. vectorAddress := (uint16(z.I) << 8) | uint16(data) - z.PC = uint16(z.core.MemRead(vectorAddress)) | (uint16(z.core.MemRead(vectorAddress+1)) << 8) + z.PC = z.getWord(vectorAddress) //uint16( z.core.MemRead(vectorAddress)) | (uint16(z.core.MemRead(vectorAddress+1)) << 8) z.CycleCounter += 19 // A "notification" is generated so that the calling program can break on it. z.interruptOccurred = true @@ -342,7 +339,7 @@ func (z *Z80Type) getOperand(opcode byte) byte { case 5: return z.L case 6: - return z.core.MemRead(uint16(z.H)<<8 | uint16(z.L)) + return z.core.MemRead(z.hl()) default: return z.A } @@ -381,7 +378,7 @@ func (z *Z80Type) load8bit(opcode byte, operand byte) { case 5: z.L = operand case 6: - z.core.MemWrite(uint16(z.H)<<8|uint16(z.L), operand) + z.core.MemWrite(z.hl(), operand) default: z.A = operand } @@ -409,10 +406,6 @@ func (z *Z80Type) alu8bit(opcode byte, operand byte) { } } -func (z *Z80Type) otherInstructions(opcode byte) { - -} - // getFlagsRegister return whole F register func (z *Z80Type) getFlagsRegister() byte { return getFlags(&z.Flags) @@ -478,10 +471,6 @@ func (z *Z80Type) updateXYFlags(result byte) { z.Flags.X = result&0x08 != 0 } -func getParity(value byte) bool { - return ParityBits[value] -} - // PushWord - Decrement stack pointer and put specified word value to stack func (z *Z80Type) PushWord(operand uint16) { z.SP-- @@ -507,8 +496,7 @@ func (z *Z80Type) doConditionalAbsoluteJump(condition bool) { // because the instruction decoder increments the PC // unconditionally at the end of every instruction, // and we need to counteract that so we end up at the jump target. - // TODO: Check for increment CycleCounter - z.PC = uint16(z.core.MemRead(z.PC+1)) | (uint16(z.core.MemRead(z.PC+2)) << 8) + z.PC = z.getWord(z.PC + 1) //uint16( z.core.MemRead(z.PC+1)) | (uint16(z.core.MemRead(z.PC+2)) << 8) z.PC-- } else { // We're not taking this jump, just move the PC past the operand. @@ -540,7 +528,7 @@ func (z *Z80Type) doConditionalCall(condition bool) { if condition { z.CycleCounter += 7 z.PushWord(z.PC + 3) - z.PC = uint16(z.core.MemRead(z.PC+1)) | (uint16(z.core.MemRead(z.PC+2)) << 8) + z.PC = z.getWord(z.PC + 1) // uint16( z.core.MemRead(z.PC+1)) | (uint16(z.core.MemRead(z.PC+2)) << 8) z.PC-- } else { z.PC += 2 @@ -560,16 +548,6 @@ func (z *Z80Type) doReset(address uint16) { z.PC = address - 1 } -//func (z *Z80Type) setBaseFlags(operand byte, result uint16) { -// z.Flags.S = result&0x80 != 0 -// z.Flags.Z = result&0x00ff == 0 -// z.Flags.H = (((operand & 0x0f) + (z.A & 0x0f)) & 0x10) != 0 -// // An overflow has happened if the sign bits of the accumulator and the operand -// // don't match the sign bit of the result value. -// z.Flags.P = ((z.A & 0x80) == (operand & 0x80)) && (z.A&0x80 != byte(result&0x80)) -// z.Flags.C = result&0x0100 != 0 -//} - // doAdd Handle ADD A, [operand] instructions. func (z *Z80Type) doAdd(operand byte) { var result = uint16(z.A) + uint16(operand) @@ -585,6 +563,7 @@ func (z *Z80Type) doAdd(operand byte) { z.updateXYFlags(z.A) } +// doAdc Handle ADC A, [operand] instructions. func (z *Z80Type) doAdc(operand byte) { add := byte(0) if z.Flags.C { @@ -603,6 +582,7 @@ func (z *Z80Type) doAdc(operand byte) { z.updateXYFlags(z.A) } +// doSub Handle SUB A, [operand] instructions. func (z *Z80Type) doSub(operand byte) { var result = uint16(z.A) - uint16(operand) @@ -617,6 +597,7 @@ func (z *Z80Type) doSub(operand byte) { z.updateXYFlags(z.A) } +// doSbc Handle SBC A, [operand] instructions. func (z *Z80Type) doSbc(operand byte) { sub := byte(0) if z.Flags.C { @@ -635,6 +616,7 @@ func (z *Z80Type) doSbc(operand byte) { z.updateXYFlags(z.A) } +// setLogicFlags Set common flags for logic ALU Ops func (z *Z80Type) setLogicFlags() { z.Flags.S = z.A&0x80 != 0 z.Flags.Z = z.A == 0 @@ -643,6 +625,7 @@ func (z *Z80Type) setLogicFlags() { z.Flags.C = false } +// doAnd handle AND [operand] instructions. func (z *Z80Type) doAnd(operand byte) { z.A &= operand z.setLogicFlags() @@ -650,6 +633,7 @@ func (z *Z80Type) doAnd(operand byte) { z.updateXYFlags(z.A) } +// doXor handle XOR [operand] instructions. func (z *Z80Type) doXor(operand byte) { z.A ^= operand z.setLogicFlags() @@ -657,6 +641,7 @@ func (z *Z80Type) doXor(operand byte) { z.updateXYFlags(z.A) } +// doOr handle OR [operand] instructions. func (z *Z80Type) doOr(operand byte) { z.A |= operand z.setLogicFlags() @@ -664,6 +649,7 @@ func (z *Z80Type) doOr(operand byte) { z.updateXYFlags(z.A) } +// doCp handle CP [operand] instructions. func (z *Z80Type) doCp(operand byte) { tmp := z.A z.doSub(operand) @@ -671,6 +657,7 @@ func (z *Z80Type) doCp(operand byte) { z.updateXYFlags(operand) } +// doInc handle INC [operand] instructions. func (z *Z80Type) doInc(operand byte) byte { var result = uint16(operand) + 1 r8 := byte(result & 0xff) @@ -685,6 +672,7 @@ func (z *Z80Type) doInc(operand byte) byte { return r8 } +// doDec handle DEC [operand] instructions. func (z *Z80Type) doDec(operand byte) byte { var result = uint16(operand) - 1 r8 := byte(result & 0xff) @@ -699,27 +687,30 @@ func (z *Z80Type) doDec(operand byte) byte { return r8 } +// doHlAdd handle ADD HL,[operand] instructions. func (z *Z80Type) doHlAdd(operand uint16) { // The HL arithmetic instructions are the same as the A ones, // just with twice as many bits happening. - hl := uint16(z.L) | (uint16(z.H) << 8) + hl := z.hl() //uint16(z.L) | (uint16(z.H) << 8) result := uint32(hl) + uint32(operand) z.Flags.N = false z.Flags.C = result > 0xffff z.Flags.H = ((hl&0x0fff)+(operand&0x0fff))&0x1000 > 0 - z.L = byte(result & 0xff) - z.H = byte((result & 0xff00) >> 8) + z.setHl(uint16(result)) + //z.L = byte(result & 0xff) + //z.H = byte((result & 0xff00) >> 8) z.updateXYFlags(z.H) } +// doHlAdc handle ADC HL,[operand] instructions. func (z *Z80Type) doHlAdc(operand uint16) { if z.Flags.C { operand++ } - hl := uint16(z.L) | (uint16(z.H) << 8) + hl := z.hl() result := uint32(hl) + uint32(operand) z.Flags.S = (result & 0x8000) != 0 @@ -729,18 +720,20 @@ func (z *Z80Type) doHlAdc(operand uint16) { z.Flags.N = false z.Flags.C = result > 0xffff - z.L = byte(result & 0xff) - z.H = byte((result & 0xff00) >> 8) + z.setHl(uint16(result)) + //z.L = byte(result & 0xff) + //z.H = byte((result & 0xff00) >> 8) z.updateXYFlags(z.H) } +// doHlSbc handle SBC HL,[operand] instructions. func (z *Z80Type) doHlSbc(operand uint16) { if z.Flags.C { operand++ } - hl := uint16(z.L) | (uint16(z.H) << 8) + hl := z.hl() //uint16(z.L) | (uint16(z.H) << 8) result := uint32(hl) - uint32(operand) z.Flags.S = (result & 0x8000) != 0 @@ -750,8 +743,9 @@ func (z *Z80Type) doHlSbc(operand uint16) { z.Flags.N = true z.Flags.C = result > 0xffff - z.L = byte(result & 0xff) - z.H = byte((result & 0xff00) >> 8) + z.setHl(uint16(result)) + //z.L = byte(result & 0xff) + //z.H = byte((result & 0xff00) >> 8) z.updateXYFlags(z.H) } @@ -786,10 +780,8 @@ func (z *Z80Type) doNeg() { func (z *Z80Type) doLdi() { // Copy the value that we're supposed to copy. - hl := uint16(z.L) | (uint16(z.H) << 8) - de := uint16(z.E) | (uint16(z.D) << 8) - readValue := z.core.MemRead(hl) - z.core.MemWrite(de, readValue) + readValue := z.core.MemRead(z.hl()) + z.core.MemWrite(z.de(), readValue) z.incDe() z.incHl() @@ -802,63 +794,49 @@ func (z *Z80Type) doLdi() { z.Flags.X = ((z.A+readValue)&0x08)>>3 != 0 } +func (z *Z80Type) fhv() byte { + if z.Flags.H { + return 1 + } + return 0 +} + func (z *Z80Type) doCpi() { tempCarry := z.Flags.C - hl := uint16(z.L) | (uint16(z.H) << 8) - readValue := z.core.MemRead(hl) + readValue := z.core.MemRead(z.hl()) z.doCp(readValue) z.Flags.C = tempCarry - var fh byte = 0 - if z.Flags.H { - fh = 1 - } + fh := z.fhv() z.Flags.Y = ((z.A-readValue-fh)&0x02)>>1 != 0 z.Flags.X = ((z.A-readValue-fh)&0x08)>>3 != 0 - z.incHl() z.decBc() - z.Flags.P = (z.B | z.C) != 0 } func (z *Z80Type) doIni() { - hl := (uint16(z.H) << 8) | uint16(z.L) - bc := (uint16(z.B) << 8) | uint16(z.C) - z.core.MemWrite(hl, z.core.IORead(bc)) - + z.core.MemWrite(z.hl(), z.core.IORead(z.bc())) z.incHl() - z.B = z.doDec(z.B) z.Flags.N = true } func (z *Z80Type) doOuti() { - // Zilog pseudo code is wrong, see: https://github.com/maziac/z80-instruction-set/pull/10 z.B = z.doDec(z.B) - hl := (uint16(z.H) << 8) | uint16(z.L) - bc := (uint16(z.B) << 8) | uint16(z.C) - z.core.IOWrite(bc, z.core.MemRead(hl)) - + z.core.IOWrite(z.bc(), z.core.MemRead(z.hl())) z.incHl() - z.Flags.N = true } func (z *Z80Type) doLdd() { z.Flags.N = false z.Flags.H = false - - hl := (uint16(z.H) << 8) | uint16(z.L) - de := (uint16(z.D) << 8) | uint16(z.E) - - readValue := z.core.MemRead(hl) - z.core.MemWrite(de, readValue) - + readValue := z.core.MemRead(z.hl()) + z.core.MemWrite(z.de(), readValue) z.decDe() z.decHl() z.decBc() - z.Flags.P = (z.C | z.B) != 0 z.Flags.Y = ((z.A+readValue)&0x02)>>1 != 0 z.Flags.X = ((z.A+readValue)&0x08)>>3 != 0 @@ -866,16 +844,12 @@ func (z *Z80Type) doLdd() { func (z *Z80Type) doCpd() { tempCarry := z.Flags.C - hl := uint16(z.L) | (uint16(z.H) << 8) - readValue := z.core.MemRead(hl) + readValue := z.core.MemRead(z.hl()) z.doCp(readValue) z.Flags.C = tempCarry - var fh byte = 0 - if z.Flags.H { - fh = 1 - } + fh := z.fhv() z.Flags.Y = ((z.A-readValue-fh)&0x02)>>1 != 0 z.Flags.X = ((z.A-readValue-fh)&0x08)>>3 != 0 @@ -887,20 +861,15 @@ func (z *Z80Type) doCpd() { } func (z *Z80Type) doInd() { - hl := (uint16(z.H) << 8) | uint16(z.L) - bc := (uint16(z.B) << 8) | uint16(z.C) - z.core.MemWrite(hl, z.core.IORead(bc)) + z.core.MemWrite(z.hl(), z.core.IORead(z.bc())) z.decHl() z.B = z.doDec(z.B) z.Flags.N = true } func (z *Z80Type) doOutd() { - // Zilog pseudo code is wrong, see: https://github.com/maziac/z80-instruction-set/pull/10 z.B = z.doDec(z.B) - hl := (uint16(z.H) << 8) | uint16(z.L) - bc := (uint16(z.B) << 8) | uint16(z.C) - z.core.IOWrite(bc, z.core.MemRead(hl)) + z.core.IOWrite(z.bc(), z.core.MemRead(z.hl())) z.decHl() z.Flags.N = true } @@ -999,29 +968,6 @@ func (z *Z80Type) setShiftFlags(operand byte) { z.updateXYFlags(operand) } -//type Operation func() - -func (z *Z80Type) opcodeFD() { - z.R = (z.R & 0x80) | (((z.R & 0x7f) + 1) & 0x7f) - z.PC++ - opcode := z.core.M1MemRead(z.PC) - fun := ddInstructions[opcode] - if fun != nil { - // Rather than copy and paste all the IX instructions into IY instructions, - // what we'll do is sneakily copy IY into IX, run the IX instruction, - // and then copy the result into IY and restore the old IX. - var temp = z.IX - z.IX = z.IY - fun(z) - z.IY = z.IX - z.IX = temp - z.CycleCounter += CycleCountsDd[opcode] - } else { - z.PC-- - z.CycleCounter += CycleCounts[0] - } -} - // ============== get register pairs func (z *Z80Type) bc() uint16 { @@ -1039,58 +985,58 @@ func (z *Z80Type) hl() uint16 { // ============ helper fn func (z *Z80Type) incBc() { - z.changeBc(+1) + z.setBc(z.bc() + 1) } func (z *Z80Type) decBc() { - z.changeBc(-1) -} - -func (z *Z80Type) incHl() { - z.changeHl(+1) -} - -func (z *Z80Type) decHl() { - z.changeHl(-1) + z.setBc(z.bc() - 1) } func (z *Z80Type) incDe() { - z.changeDe(+1) + z.setDe(z.de() + 1) } func (z *Z80Type) decDe() { - z.changeDe(-1) + z.setDe(z.de() - 1) } -func (z *Z80Type) changeDe(val int8) { - de := (uint16(z.D) << 8) | uint16(z.E) - if val < 0 { - de-- - } else { - de++ - } - z.E = byte(de & 0xff) - z.D = byte(de >> 8) +func (z *Z80Type) incHl() { + z.setHl(z.hl() + 1) } -func (z *Z80Type) changeBc(val int8) { - bc := (uint16(z.B) << 8) | uint16(z.C) - if val < 0 { - bc-- - } else { - bc++ - } - z.C = byte(bc & 0x00ff) - z.B = byte(bc >> 8) +func (z *Z80Type) decHl() { + z.setHl(z.hl() - 1) } -func (z *Z80Type) changeHl(val int8) { - hl := (uint16(z.H) << 8) | uint16(z.L) - if val < 0 { - hl-- - } else { - hl++ - } - z.L = byte(hl & 0xff) - z.H = byte(hl >> 8) +func (z *Z80Type) setHl(val uint16) { + z.L = byte(val & 0xff) + z.H = byte(val >> 8) +} + +func (z *Z80Type) setDe(val uint16) { + z.E = byte(val & 0xff) + z.D = byte(val >> 8) +} + +func (z *Z80Type) setBc(val uint16) { + z.C = byte(val & 0xff) + z.B = byte(val >> 8) +} + +// incR Increment R at the start of every instruction cycle. +// The high bit of R is not affected by this increment, +// it can only be changed using the LD R, A instruction. +// Note: also a HALT does increment the R register. +func (z *Z80Type) incR() { + z.R = (z.R & 0x80) | (((z.R & 0x7f) + 1) & 0x7f) +} + +// getWord Return 16bit value from memory by specified address +func (z *Z80Type) getWord(address uint16) uint16 { + return (uint16(z.core.MemRead(address+1)) << 8) | uint16(z.core.MemRead(address)) +} + +func (z *Z80Type) setWord(address uint16, value uint16) { + z.core.MemWrite(address, byte(value)) + z.core.MemWrite(address+1, byte(value>>8)) }