From b200f269a01eca21c337aa72e0b0d4909af883e1 Mon Sep 17 00:00:00 2001 From: Roman Boykov Date: Sat, 14 Mar 2026 00:02:00 +0300 Subject: [PATCH] ZEsarUX ZRCP Partial debug protocol implementation --- config/config.go | 11 +- debuger/listener.go | 469 +++++++++++++++++++++++++++++++++++++++++ dezog/protocol.go | 74 +++++++ go.mod | 6 +- go.sum | 82 ++----- main.go | 44 +++- okean240/computer.go | 113 +++++++++- okean240/constants.go | 4 +- okean240/fdc/fdc.go | 49 +++-- okemu.yml | 4 +- rom/CPM_r7.bin | Bin 8192 -> 0 bytes z80/c99/helper.go | 2 +- z80/c99/opcodes.go | 294 +++++++++++++------------- z80/c99/opcodesCB.go | 40 ++-- z80/c99/opcodesDDFD.go | 52 ++--- z80/c99/opcodesED.go | 18 +- z80/cpu.go | 40 ++++ z80/cpu_test.go | 4 - 18 files changed, 992 insertions(+), 314 deletions(-) create mode 100644 debuger/listener.go create mode 100644 dezog/protocol.go delete mode 100644 rom/CPM_r7.bin diff --git a/config/config.go b/config/config.go index 9f48ae5..4d97f56 100644 --- a/config/config.go +++ b/config/config.go @@ -9,6 +9,7 @@ import ( const defaultMonitorFile = "rom/MON_v5.bin" const defaultCPMFile = "rom/CPM_v5.bin" +const DefaultDebufPort = 10000 type OkEmuConfig struct { LogFile string `yaml:"logFile"` @@ -17,6 +18,8 @@ type OkEmuConfig struct { CPMFile string `yaml:"cpmFile"` FloppyB string `yaml:"floppyB"` FloppyC string `yaml:"floppyC"` + Host string `yaml:"host"` + Port int `yaml:"port"` } var config *OkEmuConfig @@ -59,7 +62,9 @@ func LoadConfig() { } func checkConfig(conf *OkEmuConfig) { - + if conf.Host == "" { + conf.Host = "localhost" + } } func setDefaultConf(conf *OkEmuConfig) { @@ -75,4 +80,8 @@ func setDefaultConf(conf *OkEmuConfig) { if conf.CPMFile == "" { conf.CPMFile = defaultCPMFile } + if conf.Port < 80 || conf.Port > 65535 { + log.Infof("Port %d incorrect, using default: %d", conf.Port, DefaultDebufPort) + conf.Port = DefaultDebufPort + } } diff --git a/debuger/listener.go b/debuger/listener.go new file mode 100644 index 0000000..ea9dd0d --- /dev/null +++ b/debuger/listener.go @@ -0,0 +1,469 @@ +package debuger + +import ( + "bufio" + "fmt" + "io" + "net" + "okemu/config" + "okemu/okean240" + "os" + "strings" + //"okemu/logger" + "strconv" + + log "github.com/sirupsen/logrus" +) + +const welcomeMessage = "Welcome to ZEsarUX remote command protocol (ZRCP)\nWrite help for available commands\n\ncommand> " +const emptyResponse = "\ncommand> " +const aboutResponse = "ZEsarUX remote command protocol" +const getVersionResponse = "12.1" +const getRegistersResponse = "PC=%04x SP=%04x AF=%04x BC=%04x HL=%04x DE=%04x IX=%04x IY=%04x AF'=%04x BC'=%04x HL'=%04x DE'=%04x I=%02x R=%02x F=%s F'=%s MEMPTR=%04x IM0 IFF%s VPS: 0 MMU=00000000000000000000000000000000" +const inCpuStepResponse = "\ncommand@cpu-step> " +const getMachineResponse = "64K RAM, no ZX\n" +const respErrorLoading = "ERROR loading file" +const quitResponse = "Sayonara baby\n" + +// Receive messages, split to strings and parse +func handleConnection(c net.Conn) { + reader := bufio.NewReader(c) + writer := bufio.NewWriter(c) + if !writeWelcomeMessage(writer) { + return + } + activeWriter = writer + for { + str, err := reader.ReadString('\n') + if err != nil { + if err == io.EOF { + break + } else { + log.Errorf("TCP error: %v", err) + return + } + } + if !HandleCommand(str, writer) { + log.Debug("Closing connection") + writeResponseMessage(writer, quitResponse) + break + } + //byteBuffer.WriteByte(b) + } + activeWriter = nil + //log.Trace("TCP Connection closed") + err := c.Close() + if err != nil { + log.Warnf("Can not close socket: %v", err) + } + +} + +var activeWriter *bufio.Writer = nil + +func writeWelcomeMessage(writer *bufio.Writer) bool { + return writeResponseMessage(writer, welcomeMessage) +} + +//command@cpu-step + +func writeResponseMessage(writer *bufio.Writer, message string) bool { + prompt := emptyResponse + if computer.IsStepMode() { + prompt = inCpuStepResponse + } + + _, err := writer.WriteString(message + prompt) + if err != nil { + log.Errorf("TCP error: %v", err) + return false + } + err = writer.Flush() + if err != nil { + log.Errorf("TCP error: %v", err) + return false + } + return true +} + +var computer *okean240.ComputerType + +// SetupTcpHandler Setup TCP listener, handle connections +func SetupTcpHandler(config *config.OkEmuConfig, comp *okean240.ComputerType) { + port := config.Host + ":" + strconv.Itoa(config.Port) + computer = comp + log.Infof("Serve TCP connections on %s", port) + + l, err := net.Listen("tcp4", port) + if err != nil { + fmt.Println(err) + return + } + + defer func(l net.Listener) { + err := l.Close() + if err != nil { + log.Warnf("Error closing listener connection %v", err) + } + }(l) + + for { + c, err := l.Accept() + if err != nil { + log.Errorf("Accept connection: %v", err) + return + } + go handleConnection(c) + } + +} + +// HandleCommand HandleLogLine Parse log line(s) and send it to redis +func HandleCommand(str string, writer *bufio.Writer) bool { + quit := false + str = strings.TrimSpace(str) + if str == "" { + return false + } + log.Debugf("Command: '%s'", str) + + pos := strings.Index(str, " ") + cmd := str + params := "" + + if pos > 1 { + cmd = str[:pos] + params = strings.TrimSpace(str[pos+1:]) + } + + switch cmd { + case "cpu-step": + computer.Do() + writeResponseMessage(writer, " "+fmt.Sprintf("%04X", computer.GetCPUState().PC)) + case "run": + _, e := writer.WriteString("Running until a breakpoint, key press or data sent, menu opening or other event\n") + if e != nil { + log.Warnf("Error writing to buffer: %v", e) + } + e = writer.Flush() + if e != nil { + log.Warnf("Error flushing the buffer: %v", e) + } + computer.SetRunMode(true) + case "get-tstates-partial": + writeResponseMessage(writer, strconv.FormatUint(computer.Cycles(), 10)) + case "close-all-menus": + writeResponseMessage(writer, "") + case "about": + writeResponseMessage(writer, aboutResponse) + case "get-version": + writeResponseMessage(writer, getVersionResponse) + case "get-registers": + writeResponseMessage(writer, registersResponse()) + case "set-register": + writeResponseMessage(writer, setRegister(params)) + case "hard-reset-cpu": + computer.Reset() + writeResponseMessage(writer, "") + case "enter-cpu-step": + computer.SetStepMode(true) + writeResponseMessage(writer, "") + case "exit-cpu-step": + computer.SetStepMode(false) + writeResponseMessage(writer, "") + case "set-debug-settings": + log.Debugf("Set debug settings to %s", params) + writeResponseMessage(writer, "") + case "get-current-machine": + writeResponseMessage(writer, getMachineResponse) + case "clear-membreakpoints": + computer.ClearMemBreakpoints() + writeResponseMessage(writer, "") + case "enable-breakpoints": + computer.SetBreakpointsEnabled(true) + writeResponseMessage(writer, "") + case "disable-breakpoints": + computer.SetBreakpointsEnabled(false) + writeResponseMessage(writer, "") + case "enable-breakpoint": + writeResponseMessage(writer, setBreakpointState(params, true)) + case "disable-breakpoint": + writeResponseMessage(writer, setBreakpointState(params, false)) + case "get-cpu-frequency": + writeResponseMessage(writer, strconv.Itoa(int(computer.CPUFrequency()))) + case "set-breakpoint": + // 1 PC=0010Bh + writeResponseMessage(writer, setBreakpoint(params)) + case "cpu-code-coverage": + //"enabled no" + writeResponseMessage(writer, "") + case "cpu-history": + // "enabled yes" + // "set-max-size 1000" + // "clear" + // "started yes" + // "ignrephalt yes" + // "ignrepldxr yes" + writeResponseMessage(writer, "") + case "extended-stack": + // "enabled no" + // "enabled yes" + if strings.HasPrefix(params, "get") { + writeResponseMessage(writer, getExtendedStack(params)) + } else { + writeResponseMessage(writer, "") + } + case "load-binary": + writeResponseMessage(writer, loadBinary(params)) + case "read-memory": + writeResponseMessage(writer, readMemory(params)) + case "quit": + quit = true + default: + log.Debugf("Unhandled Command: %s", str) + writeResponseMessage(writer, "") + } + return !quit +} + +func loadBinary(param string) string { + params := strings.Split(param, " ") + if len(params) < 2 { + log.Errorf("Invalid load parameters: %s", param) + return respErrorLoading + } + fn := strings.TrimSpace(params[0]) + if strings.HasPrefix(fn, "\"") { + fn = fn[1:] + } + if strings.HasSuffix(fn, "\"") && len(fn) > 1 { + fn = fn[:len(fn)-1] + } + offset, e := strconv.Atoi(params[1]) + length := 0 + if e != nil || offset < 0 || offset > 65535 || len(fn) == 0 { + log.Errorf("Invalid load parameters: %s", param) + return respErrorLoading + } + if len(params) > 2 { + length, e = strconv.Atoi(params[1]) + if e != nil { + length = 0 + } + } + data, err := os.ReadFile(fn) + if err != nil { + log.Errorf("Error reading file: %v", err) + return respErrorLoading + } + if length != 0 && len(data) < length { + log.Errorf("File too short. Expected %d bytes, got %d", len(data), length) + return respErrorLoading + } + if length == 0 { + length = len(data) + } + // Loaded Ok, move file to memory + for addr := uint16(0); addr < uint16(length); addr++ { + computer.MemWrite(addr+uint16(offset), data[addr]) + } + + return "" +} + +func toW(hi, lo byte) uint16 { + return uint16(lo) | (uint16(hi) << 8) +} + +func iifStr(iif1, iif2 bool) string { + flags := []byte{'-', '-'} + if iif1 { + flags[0] = '1' + } + if iif2 { + flags[1] = '2' + } + return string(flags) +} + +// registersResponse Build string +// PC=%4x SP=%4x AF=%4x BC=%4x HL=%4x DE=%4x IX=%4x IY=%4x AF'=%4x BC'=%4x HL'=%4x DE'=%4x I=%2x +// R=%2x F=%s F'=%s MEMPTR=%4x IM0 IFF-- VPS: 0 MMU=00000000000000000000000000000000 +func registersResponse() string { + state := computer.GetCPUState() + resp := fmt.Sprintf(getRegistersResponse, + state.PC, + state.SP, + toW(state.A, state.Flags.GetFlags()), + toW(state.B, state.C), + toW(state.H, state.L), + toW(state.D, state.E), + state.IX, + state.IY, + toW(state.AAlt, state.FlagsAlt.GetFlags()), + toW(state.BAlt, state.CAlt), + toW(state.HAlt, state.LAlt), + toW(state.DAlt, state.EAlt), + state.I, + state.R, + state.Flags.GetFlagsStr(), + state.FlagsAlt.GetFlagsStr(), + state.MemPtr, + iifStr(state.Iff1, state.Iff2), + ) + log.Debug(resp) + return resp +} + +func setRegister(param string) string { + state := computer.GetCPUState() + params := strings.Split(param, "=") + if len(params) != 2 { + log.Errorf("Invalid set register parameter: %s", param) + return registersResponse() + } + val, e := strconv.Atoi(params[1]) + if e != nil { + log.Errorf("Invalid set register parameter value: %s", params[1]) + return registersResponse() + } + switch params[0] { + case "SP": + state.SP = uint16(val) + case "PC": + state.PC = uint16(val) + case "IX": + state.IX = uint16(val) + case "IY": + state.IY = uint16(val) + case "A": + state.A = uint8(val) + case "B": + state.B = uint8(val) + case "C": + state.C = uint8(val) + case "D": + state.D = uint8(val) + case "E": + state.E = uint8(val) + case "H": + state.H = uint8(val) + case "L": + state.L = uint8(val) + + case "I": + state.I = uint8(val) + case "R": + state.R = uint8(val) + default: + log.Errorf("Unsupported set register parameter: %s", param) + } + computer.SetCPUState(state) + return registersResponse() +} + +func readMemory(param string) string { + params := strings.Split(param, " ") + if len(params) != 2 { + log.Errorf("Invalid read memory parameter: %s", param) + return registersResponse() + } + offset, e := strconv.Atoi(params[0]) + if e != nil { + log.Errorf("Invalid read memory parameter offset: %s", params[0]) + } + + size, e := strconv.Atoi(params[1]) + if e != nil { + log.Errorf("Invalid read memory parameter size: %s", params[1]) + } + resp := "" + for i := 0; i < size; i++ { + resp += fmt.Sprintf("%02X", computer.MemRead(uint16(offset)+uint16(i))) + } + log.Tracef("ReadMemory[%d,%d]:\n%s", offset, size, resp) + return resp +} + +func getExtendedStack(param string) string { + params := strings.Split(param, " ") + if len(params) < 2 { + log.Errorf("Will be 2 or 3 params: %s", param) + return "" + } + size, err := strconv.Atoi(params[1]) + if err != nil || size < 0 || size > 65636 { + log.Errorf("Invalid size param: %s", param) + } + + sp := computer.GetCPUState().SP + if len(params) == 3 { + psp, err := strconv.ParseUint(params[2], 10, 16) + if err != nil { + log.Errorf("Invalid SP param: %s", params[2]) + } else { + sp = uint16(psp) + } + } + + resp := "" + spEnd := sp - uint16(size*2) + for i := sp; i > spEnd; i -= 2 { + resp += fmt.Sprintf("%04XH default\n", computer.MemRead(i)) + } + log.Debugf("Stack[%d,%d]:\n%s", sp, size, resp) + return resp +} + +func setBreakpointState(param string, enable bool) string { + no, e := strconv.Atoi(param) + if e != nil { + log.Errorf("Invalid breakpoint parameter: %s", param) + return "" + } + if enable && !computer.IsBreakpointsEnabled() { + return "Error. You must enable breakpoints first" + } + computer.SetBreakpointEnabled(uint16(no), enable) + return "" +} + +func setBreakpoint(param string) string { + // 1 PC=0010Bh + params := strings.Split(param, " ") + if len(params) != 2 { + log.Errorf("Invalid set breakpoint parameters: %s", param) + return "" + } + no, e := strconv.Atoi(params[0]) + if e != nil || no > okean240.MaxBreakpoints || no < 1 { + log.Errorf("Invalid breakpoint number: %s", params[0]) + return "" + } + + regv := strings.Split(params[1], "=") + if len(regv) != 2 { + log.Errorf("Invalid breakpoint parameter: %s", params[1]) + return "" + } + addr, e := strconv.ParseUint(strings.TrimSuffix(regv[1], "h"), 16, 32) + if e != nil || addr < 0 || addr >= 65535 { + log.Errorf("Invalid breakpoint address: %s", regv[1]) + return "" + } + if regv[0] == "PC" { + computer.SetBreakpoint(uint16(no), uint16(addr)) + } else { + log.Errorf("Unsupported BP: %s", params[1]) + } + return "" +} + +func BreakpointHit(no uint16) { + if activeWriter != nil { + pc := computer.GetCPUState().PC + rep := fmt.Sprintf("Breakpoint fired: PC=%XH\n %04X NOP", pc, pc) + log.Debug(rep) + writeResponseMessage(activeWriter, rep) + } +} diff --git a/dezog/protocol.go b/dezog/protocol.go new file mode 100644 index 0000000..0dd79af --- /dev/null +++ b/dezog/protocol.go @@ -0,0 +1,74 @@ +package dezog + +// Command - DZRP protocol command +type Command struct { + length uint32 // Length of the payload data. (little endian) + sequence uint8 // Sequence number, 1-255. Increased with each command + command uint8 // Command ID + data []byte // Payload +} + +// Response - response on DZRP protocol command +type Response struct { + length uint32 // Length of the following data beginning with the sequence number. (little endian) + sequence uint8 // Sequence number, same as command. + data []byte // Payload +} + +// Notification - message from emulator to DEZOG +type Notification struct { + seqNo uint8 // Instead of Seq No. + command uint8 // NTF_PAUSE = 1 + breakReason uint8 // Break reason: 0 = no reason (e.g. a step-over), 1 = manual break, 2 = breakpoint hit, + // 3 = watchpoint hit read access, 4 = watchpoint hit write access, 255 = some other reason: + //the reason string might have useful information for the user + address uint16 // Breakpoint or watchpoint address. + bank uint8 // The bank+1 of the breakpoint or watchpoint address. + reason string // Null-terminated break reason string. Might in theory have almost 2^32 byte length. + // In practice, it will be normally less than 256. If reason string is empty it will contain at + // least a 0. +} + +const NTF_PAUSE = 1 + +// Notification, Break reasons +const ( + BR_REASON_MANUAL = 1 + BR_REASON_BP_HIT = 2 + BR_REASON_WP_HIT_R = 3 + BR_REASON_WP_HIT_W = 4 + BR_REASON_OTHER = 255 +) + +// DEZOG Commands to emulator +const ( + CMD_INIT = 1 + CMD_CLOSE = 2 + CMD_GET_REGISTERS = 3 + CMD_SET_REGISTER = 4 + CMD_WRITE_BANK = 5 + CMD_CONTINUE = 6 + CMD_PAUSE = 7 + CMD_READ_MEM = 8 + CMD_WRITE_MEM = 9 + CMD_SET_SLOT = 10 + CMD_GET_TBBLUE_REG = 11 + CMD_SET_BORDER = 12 + CMD_SET_BREAKPOINTS = 13 + CMD_RESTORE_MEM = 14 + CMD_LOOPBACK = 15 + CMD_GET_SPRITES_PALETTE = 16 + CMD_GET_SPRITES_CLIP_WINDOW_AND_CONTROL = 17 + CMD_GET_SPRITES = 18 + CMD_GET_SPRITE_PATTERNS = 19 + CMD_READ_PORT = 20 + CMD_WRITE_PORT = 21 + CMD_EXEC_ASM = 22 + CMD_INTERRUPT_ON_OFF = 23 + CMD_ADD_BREAKPOINT = 40 + CMD_REMOVE_BREAKPOINT = 41 + CMD_ADD_WATCHPOINT = 42 + CMD_REMOVE_WATCHPOINT = 43 + CMD_READ_STATE = 50 + CMD_WRITE_STATE = 51 +) diff --git a/go.mod b/go.mod index 09f0b4a..fa18e51 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,13 @@ module okemu go 1.25 require ( + fyne.io/fyne/v2 v2.7.3 + github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6 github.com/sirupsen/logrus v1.9.4 gopkg.in/yaml.v3 v3.0.1 ) require ( - fyne.io/fyne/v2 v2.7.3 // indirect fyne.io/systray v1.12.0 // indirect github.com/BurntSushi/toml v1.5.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -17,18 +18,17 @@ require ( github.com/fyne-io/gl-js v0.2.0 // indirect github.com/fyne-io/glfw-js v0.3.0 // indirect github.com/fyne-io/image v0.1.1 // indirect - github.com/fyne-io/mobile v0.1.2 // indirect github.com/fyne-io/oksvg v0.2.0 // indirect github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect github.com/go-text/render v0.2.0 // indirect github.com/go-text/typesetting v0.3.3 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff // indirect github.com/hack-pad/go-indexeddb v0.3.2 // indirect github.com/hack-pad/safejs v0.1.0 // indirect github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect + github.com/kr/text v0.2.0 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect diff --git a/go.sum b/go.sum index d159b5f..4978028 100644 --- a/go.sum +++ b/go.sum @@ -1,20 +1,16 @@ -fyne.io/fyne v1.4.3 h1:356CnXCiYrrfaLGsB7qLK3c6ktzyh8WR05v/2RBu51I= -fyne.io/fyne v1.4.3/go.mod h1:8kiPBNSDmuplxs9WnKCkaWYqbcXFy0DeAzwa6PBO9Z8= fyne.io/fyne/v2 v2.7.3 h1:xBT/iYbdnNHONWO38fZMBrVBiJG8rV/Jypmy4tVfRWE= fyne.io/fyne/v2 v2.7.3/go.mod h1:gu+dlIcZWSzKZmnrY8Fbnj2Hirabv2ek+AKsfQ2bBlw= fyne.io/systray v1.12.0 h1:CA1Kk0e2zwFlxtc02L3QFSiIbxJ/P0n582YrZHT7aTM= fyne.io/systray v1.12.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I= -github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= +github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/fredbi/uri v1.1.1 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko= github.com/fredbi/uri v1.1.1/go.mod h1:4+DZQ5zBjEwQCDmXW5JdIjz0PUA+yJbvtBv+u+adr5o= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs= @@ -23,116 +19,66 @@ github.com/fyne-io/glfw-js v0.3.0 h1:d8k2+Y7l+zy2pc7wlGRyPfTgZoqDf3AI4G+2zOWhWUk github.com/fyne-io/glfw-js v0.3.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk= github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA= github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM= -github.com/fyne-io/mobile v0.1.2 h1:0HaXDtOOwyOTn3Umi0uKVCOgJtfX73c6unC4U8i5VZU= -github.com/fyne-io/mobile v0.1.2/go.mod h1:/kOrWrZB6sasLbEy2JIvr4arEzQTXBTZGb3Y96yWbHY= github.com/fyne-io/oksvg v0.2.0 h1:mxcGU2dx6nwjJsSA9PCYZDuoAcsZ/OuJlvg/Q9Njfo8= github.com/fyne-io/oksvg v0.2.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI= -github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7 h1:SCYMcCJ89LjRGwEa0tRluNRiMjZHalQZrVrvTbPh+qw= -github.com/go-gl/gl v0.0.0-20190320180904-bf2b1f2f34d7/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk= github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA= github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3 h1:q521PfSp5/z6/sD9FZZOWj4d1MLmfQW8PkRnI9M6PCE= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200625191551-73d3c3675aa3/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc= github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU= github.com/go-text/typesetting v0.3.3 h1:ihGNJU9KzdK2QRDy1Bm7FT5RFQoYb+3n3EIhI/4eaQc= github.com/go-text/typesetting v0.3.3/go.mod h1:vIRUT25mLQaSh4C8H/lIsKppQz/Gdb8Pu/tNwpi52ts= -github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME= -github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/go-text/typesetting-utils v0.0.0-20250618110550-c820a94c77b8 h1:4KCscI9qYWMGTuz6BpJtbUSRzcBrUSSE0ENMJbNSrFs= +github.com/go-text/typesetting-utils v0.0.0-20250618110550-c820a94c77b8/go.mod h1:3/62I4La/HBRX9TcTpBj4eipLiwzf+vhI+7whTc9V7o= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8= -github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A= github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0= github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8= github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio= -github.com/jackmordaunt/icns v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc= +github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6 h1:IIVxLyDUYErC950b8kecjoqDet8P5S4lcVRUOM6rdkU= +github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6/go.mod h1:JslaLRrzGsOKJgFEPBP65Whn+rdwDQSk0I0MCRFe2Zw= github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE= github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o= -github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lucor/goinfo v0.0.0-20200401173949-526b5363a13a/go.mod h1:ORP3/rB5IsulLEBwQZCJyyV6niqmI7P4EWSmkug+1Ng= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk= github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= +github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU= github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= github.com/sirupsen/logrus v1.9.4 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w= github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 h1:HunZiaEKNGVdhTRQOVpMmj5MQnGnv+e8uZNu3xFLgyM= -github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= -github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 h1:m59mIOBO4kfcNCEzJNy71UkeF4XIx2EVmL9KLwDQdmM= -github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200328031815-3db5fc6bac03/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index ddb1fab..3b0e727 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "fmt" "image/color" "okemu/config" + "okemu/debuger" "okemu/logger" "okemu/okean240" "sync/atomic" @@ -21,11 +22,14 @@ import ( var Version = "v1.0.0" var BuildTime = "2026-03-01" -//go:embed hex/format.hex +//go:embed hex/m80.hex var serialBytes []byte -//go:embed bin/FORMAT.COM -var ramBytes []byte +//go:embed bin/main.com +var ramBytes1 []byte + +//go:embed bin/PLOT.BAS +var ramBytes2 []byte var needReset = false var fullSpeed atomic.Bool @@ -53,6 +57,8 @@ func main() { go emulator(computer) go screen(computer, raster, label) + go debuger.SetupTcpHandler(conf, computer) + (*w).ShowAndRun() } @@ -106,14 +112,22 @@ func mainWindow(computer *okean240.ComputerType) (*fyne.Window, *canvas.Raster, widget.NewButton("Save Floppy", func() { computer.SaveFloppy() }), - widget.NewButton("RUN", func() { - computer.SetRamBytes(ramBytes) + widget.NewButton("RUN1", func() { + computer.SetRamBytes(ramBytes1) + }), + widget.NewButton("RUN2", func() { + computer.SetRamBytes(ramBytes2) }), widget.NewButton("DUMP", func() { computer.Dump(0x100, 15000) }), widget.NewCheck("Full speed", func(b bool) { fullSpeed.Store(b) + if b { + computer.SetCPUFrequency(50_000_000) + } else { + computer.SetCPUFrequency(2_500_000) + } }), widget.NewSeparator(), widget.NewButton("Reset", func() { @@ -170,14 +184,22 @@ func emulator(computer *okean240.ComputerType) { // 1.5 MHz computer.TimerClk() } - if fullSpeed.Load() { - computer.Do() - } else { - if ticks >= nextClock { - nextClock = ticks + uint64(computer.Do())*ticksPerTact + if !computer.IsStepMode() || computer.IsRunMode() { + var bp uint16 = 0 + if fullSpeed.Load() { + _, bp = computer.Do() + } else { + if ticks >= nextClock { + var t uint32 + t, bp = computer.Do() + nextClock = ticks + uint64(t)*ticksPerTact + } + } + // Breakpoint hit + if bp > 0 { + debuger.BreakpointHit(bp) } } - //computer.Do() if needReset { computer.Reset() needReset = false diff --git a/okean240/computer.go b/okean240/computer.go index 14a97ea..8c6c10a 100644 --- a/okean240/computer.go +++ b/okean240/computer.go @@ -9,6 +9,7 @@ import ( "okemu/okean240/pic" "okemu/okean240/pit" "okemu/okean240/usart" + "okemu/z80" "os" //"okemu/z80" @@ -19,6 +20,13 @@ import ( log "github.com/sirupsen/logrus" ) +const DefaultCPUFrequency = 2_500_000 + +type Breakpoint struct { + addr uint16 + enabled bool +} + type ComputerType struct { cpu *c99.Z80 memory Memory @@ -38,9 +46,15 @@ type ComputerType struct { kbdBuffer []byte vShift byte hShift byte + stepMode bool + runMode bool + bpEnabled bool + breakpoints [MaxBreakpoints]Breakpoint //aOffset uint16 + cpuFrequency uint32 } +const MaxBreakpoints = 256 const VRAMBlock0 = 3 const VRAMBlock1 = 7 const VidVsuBit = 0x80 @@ -57,9 +71,69 @@ type ComputerInterface interface { PutCtrlKey(shortcut fyne.Shortcut) SaveFloppy() LoadFloppy() + CPUState() *z80.Z80CPU + SetCPUState(state *z80.Z80CPU) + StepMode() bool + SetStepMode(step bool) + ClearMemBreakpoints() + SetBreakpointsEnabled(enabled bool) + IsBreakpoint() bool //Dump(start uint16, length uint16) } +func (c *ComputerType) SetBreakpointsEnabled(enabled bool) { + c.bpEnabled = enabled +} + +func (c *ComputerType) IsBreakpointsEnabled() bool { + return c.bpEnabled +} + +func (c *ComputerType) SetBreakpoint(no uint16, addr uint16) { + if no > 0 && no <= MaxBreakpoints { + c.breakpoints[no-1].addr = addr + log.Debugf("BP[%d] SET AT PC=%04X", no, addr) + } else { + log.Warnf("Breakpoint number %d out or range!", no) + } +} + +func (c *ComputerType) SetBreakpointEnabled(no uint16, enabled bool) { + if no <= MaxBreakpoints && no > 0 { + c.breakpoints[no-1].enabled = enabled + } else { + log.Warnf("Breakpoint number %d out or range!", no) + } +} + +func (c *ComputerType) IsBreakpointEnabled(no uint16) bool { + if no <= MaxBreakpoints && no > 0 { + return c.breakpoints[no-1].enabled + } + log.Warnf("Breakpoint number %d out or range!", no) + return false +} + +func (c *ComputerType) ClearMemBreakpoints() { + log.Warnf("Clearing memory bpEnabled unimplemented!") +} + +func (c *ComputerType) SetStepMode(step bool) { + c.stepMode = step +} + +func (c *ComputerType) IsStepMode() bool { + return c.stepMode +} + +func (c *ComputerType) GetCPUState() *z80.Z80CPU { + return c.cpu.GetState() +} + +func (c *ComputerType) SetCPUState(state *z80.Z80CPU) { + c.cpu.SetState(state) +} + func (c *ComputerType) M1MemRead(addr uint16) byte { return c.memory.M1MemRead(addr) } @@ -96,7 +170,14 @@ func New(cfg *config.OkEmuConfig) *ComputerType { c.usart = usart.New() c.pic = pic.New() c.fdc = fdc.New(cfg) - + c.cpuFrequency = DefaultCPUFrequency + c.bpEnabled = false + c.breakpoints = [256]Breakpoint{} + for i := range c.breakpoints { + c.breakpoints[i] = Breakpoint{} + c.breakpoints[i].enabled = false + c.breakpoints[i].addr = 0 + } return &c } @@ -114,14 +195,32 @@ func (c *ComputerType) Reset() { } -func (c *ComputerType) Do() uint32 { +func (c *ComputerType) SetRunMode(run bool) { + c.runMode = run +} + +func (c *ComputerType) IsRunMode() bool { + return c.runMode +} + +func (c *ComputerType) Do() (uint32, uint16) { + // check breakpoints + if c.bpEnabled && c.runMode { + for no, bp := range c.breakpoints { + if bp.enabled && bp.addr == c.cpu.GetState().PC { + c.runMode = false + return 0, uint16(no + 1) + } + } + } + ticks := c.cpu.RunInstruction() c.cycles += uint64(ticks) //pc := c.cpu.GetState().PC //if pc >= 0xfea3 && pc <= 0xff25 { // c.cpu.DebugOutput() //} - return ticks + return ticks, 0 } func (c *ComputerType) GetPixel(x uint16, y uint16) color.RGBA { @@ -272,3 +371,11 @@ func (c *ComputerType) Dump(start uint16, length uint16) { log.Debug("Memory dump saved successfully") } } + +func (c *ComputerType) CPUFrequency() uint32 { + return c.cpuFrequency +} + +func (c *ComputerType) SetCPUFrequency(frequency uint32) { + c.cpuFrequency = frequency +} diff --git a/okean240/constants.go b/okean240/constants.go index bff05c7..705d627 100644 --- a/okean240/constants.go +++ b/okean240/constants.go @@ -106,7 +106,7 @@ const RstTimerNo = 4 // PicDd75a Port A (a0=0) const PicDd75a = 0x80 -// PIC_DD75B Port B (a0=1) +// PicDd75b Port B (a0=1) const PicDd75b = 0x81 /* @@ -116,7 +116,7 @@ const PicDd75b = 0x81 // UartDd72rd Serial data const UartDd72rd = 0xA0 -// UartDd72rr Serial status [RST,RQ_RX,RST_ERR,PAUSE,RX_EN,RX_RDY,TX_RDY] +// UartDd72rr Serial enabled [RST,RQ_RX,RST_ERR,PAUSE,RX_EN,RX_RDY,TX_RDY] const UartDd72rr = 0xA1 /* diff --git a/okean240/fdc/fdc.go b/okean240/fdc/fdc.go index 76cc306..3f44911 100644 --- a/okean240/fdc/fdc.go +++ b/okean240/fdc/fdc.go @@ -15,6 +15,7 @@ import ( "slices" "strconv" + "github.com/howeyc/crc16" log "github.com/sirupsen/logrus" ) @@ -38,18 +39,21 @@ const ( // 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 + CmdRestore = 0x0 + CmdSeek = 0x1 + CmdStep = 0x2 + CmdStepIn = 0x5 + CmdStepOut = 0x7 + CmdReadSector = 0x8 + CmdReadSectorMulti = 0x9 + CmdWriteSector = 0xa + CmdReadAddress = 0xc + CmdWriteTrack = 0xf + CmdNoCommand = 0xff ) +var interleave = []byte{1, 8, 6, 4, 2, 9, 7, 5, 3} + const ( StatusTR0 = 0x04 // TR0 - Head at track 0 StatusRNF = 0x10 // RNF - Record not found @@ -100,7 +104,10 @@ type FloppyDriveControllerInterface interface { Sector() byte } +//var slicer = []uint16{1, 8, 6, 4, 2, 9, 7, 5, 3} + func getSectorNo(side byte, track byte, sector byte) uint16 { + //return (uint16(track)*18 + uint16(side)*9 + slicer[sector-1] - 1) return uint16(side)*SectorsPerSide + uint16(track)*SectorPerTrack + uint16(sector) - 1 } @@ -124,6 +131,12 @@ func (f *FloppyDriveController) GetFloppy() byte { return floppy } +var crcTable *crc16.Table + +func init() { + crcTable = crc16.MakeTable(0xffff) +} + func (f *FloppyDriveController) SetCmd(value byte) { f.lastCmd = value >> 4 switch f.lastCmd { @@ -183,11 +196,21 @@ func (f *FloppyDriveController) SetCmd(value byte) { f.drq = 0 f.status = StatusRNF } + case CmdReadAddress: + log.Tracef("CMD ReadAddress %d", value) + f.trackBuffer = []byte{f.trackNo, f.sideNo, f.sectorNo, 2} + + checksum := crc16.Checksum(f.trackBuffer, crcTable) + f.trackBuffer = append(f.trackBuffer, byte(checksum)) + f.trackBuffer = append(f.trackBuffer, byte(checksum>>8)) + + f.drq = 1 + f.status = 0x0 case CmdWriteTrack: log.Tracef("CMD Write Track %x", f.trackNo) + f.drq = 1 f.status = 0x00 f.trackBuffer = []byte{} - f.drq = 1 default: log.Errorf("Unknown CMD: %x VAL: %x", f.lastCmd, value&0xf) } @@ -201,7 +224,7 @@ func (f *FloppyDriveController) SetTrackNo(value byte) { //log.Tracef("FDC Track: %d", value) if value > TracksCount { f.status |= 0x10 /// RNF - log.Error("Track not found!") + log.Errorf("Track %d not found!", value) } else { f.trackNo = value } @@ -282,7 +305,7 @@ func (f *FloppyDriveController) writeTrack() { func (f *FloppyDriveController) Data() byte { switch f.lastCmd { - case CmdReadSector, CmdReadSectorMulti: + case CmdReadSector, CmdReadSectorMulti, CmdReadAddress: if len(f.trackBuffer) > 0 { f.drq = 1 f.data = f.trackBuffer[0] diff --git a/okemu.yml b/okemu.yml index a9a416c..a48a875 100644 --- a/okemu.yml +++ b/okemu.yml @@ -1,6 +1,8 @@ logFile: "okemu.log" logLevel: "info" monitorFile: "rom/MON_r8_9c6c6546.bin" +# cpmFile: "rom/CPM_r7_b89a7e16.bin" cpmFile: "rom/CPM_r8_bc0695e4.bin" floppyB: "floppy/floppyB.okd" -floppyC: "floppy/floppyC.okd" \ No newline at end of file +floppyC: "floppy/floppyC.okd" +port: 10001 diff --git a/rom/CPM_r7.bin b/rom/CPM_r7.bin deleted file mode 100644 index ba16f6380be667ac88e3cb8fabbad93fee430360..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 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 diff --git a/z80/c99/helper.go b/z80/c99/helper.go index 044a25b..47bab45 100644 --- a/z80/c99/helper.go +++ b/z80/c99/helper.go @@ -128,7 +128,7 @@ func carry(bitNo int, a uint16, b uint16, cy bool) bool { return (carry & (1 << bitNo)) != 0 } -// returns the parity of byte: 0 if number of 1 bits in `val` is odd, else 1 +// parity returns the parity of byte: 0 if odd, else 1 func parity(val byte) bool { ones := byte(0) for i := 0; i < 8; i++ { diff --git a/z80/c99/opcodes.go b/z80/c99/opcodes.go index f7c0e98..b8ab38c 100644 --- a/z80/c99/opcodes.go +++ b/z80/c99/opcodes.go @@ -9,7 +9,7 @@ func (z *Z80) jump(addr uint16) { } // jumps to next word in memory if condition is true -func (z *Z80) cond_jump(condition bool) { +func (z *Z80) condJump(condition bool) { addr := z.nextW() if condition { z.jump(addr) @@ -25,7 +25,7 @@ func (z *Z80) call(addr uint16) { } // calls to next word in memory if condition is true -func (z *Z80) cond_call(condition bool) { +func (z *Z80) condCall(condition bool) { addr := z.nextW() if condition { z.call(addr) @@ -41,7 +41,7 @@ func (z *Z80) ret() { } // returns from subroutine if condition is true -func (z *Z80) cond_ret(condition bool) { +func (z *Z80) condRet(condition bool) { if condition { z.ret() z.cycleCount += 6 @@ -57,7 +57,7 @@ func (z *Z80) jr(offset byte) { z.memPtr = z.pc } -func (z *Z80) cond_jr(condition bool) { +func (z *Z80) condJr(condition bool) { b := z.nextB() if condition { z.jr(b) @@ -73,7 +73,7 @@ func bToByte(cond bool) byte { } // ADD Byte: adds two bytes together -func (z *Z80) addb(a byte, b byte, cy bool) byte { +func (z *Z80) addB(a byte, b byte, cy bool) byte { result := a + b + bToByte(cy) z.sf = result&0x80 != 0 z.zf = result == 0 @@ -86,8 +86,8 @@ func (z *Z80) addb(a byte, b byte, cy bool) byte { } // SUBtract Byte: subtracts two bytes (with optional carry) -func (z *Z80) subb(a byte, b byte, cy bool) byte { - val := z.addb(a, ^b, !cy) +func (z *Z80) subB(a byte, b byte, cy bool) byte { + val := z.addB(a, ^b, !cy) z.cf = !z.cf z.hf = !z.hf z.nf = true @@ -95,9 +95,9 @@ func (z *Z80) subb(a byte, b byte, cy bool) byte { } // ADD Word: adds two words together -func (z *Z80) addw(a uint16, b uint16, cy bool) uint16 { - lsb := z.addb(byte(a), byte(b), cy) - msb := z.addb(byte(a>>8), byte(b>>8), z.cf) +func (z *Z80) addW(a uint16, b uint16, cy bool) uint16 { + lsb := z.addB(byte(a), byte(b), cy) + msb := z.addB(byte(a>>8), byte(b>>8), z.cf) result := (uint16(msb) << 8) | uint16(lsb) z.zf = result == 0 z.memPtr = a + 1 @@ -105,9 +105,9 @@ func (z *Z80) addw(a uint16, b uint16, cy bool) uint16 { } // SUBtract Word: subtracts two words (with optional carry) -func (z *Z80) subw(a uint16, b uint16, cy bool) uint16 { - lsb := z.subb(byte(a), byte(b), cy) - msb := z.subb(byte(a>>8), byte(b>>8), z.cf) +func (z *Z80) subW(a uint16, b uint16, cy bool) uint16 { + lsb := z.subB(byte(a), byte(b), cy) + msb := z.subB(byte(a>>8), byte(b>>8), z.cf) result := (uint16(msb) << 8) | uint16(lsb) z.zf = result == 0 z.memPtr = a + 1 @@ -115,11 +115,11 @@ func (z *Z80) subw(a uint16, b uint16, cy bool) uint16 { } // Adds a word to HL -func (z *Z80) addhl(val uint16) { +func (z *Z80) addHL(val uint16) { sf := z.sf zf := z.zf pf := z.pf - result := z.addw(z.hl(), val, false) + result := z.addW(z.hl(), val, false) z.setHL(result) z.sf = sf z.zf = zf @@ -127,28 +127,28 @@ func (z *Z80) addhl(val uint16) { } // adds a word to IX or IY -func (z *Z80) addiz(reg *uint16, val uint16) { +func (z *Z80) addIZ(reg *uint16, val uint16) { sf := z.sf zf := z.zf pf := z.pf - result := z.addw(*reg, val, false) + result := z.addW(*reg, val, false) *reg = result z.sf = sf z.zf = zf z.pf = pf } -// adchl adds a word (+ carry) to HL -func (z *Z80) adchl(val uint16) { - result := z.addw(z.hl(), val, z.cf) +// adcHL adds a word (+ carry) to HL +func (z *Z80) adcHL(val uint16) { + result := z.addW(z.hl(), val, z.cf) z.sf = result&0x8000 != 0 z.zf = result == 0 z.setHL(result) } -// sbchl subtracts a word (+ carry) to HL -func (z *Z80) sbchl(val uint16) { - result := z.subw(z.hl(), val, z.cf) +// sbcHL subtracts a word (+ carry) to HL +func (z *Z80) sbcHL(val uint16) { + result := z.subW(z.hl(), val, z.cf) z.sf = result&0x8000 != 0 z.zf = result == 0 z.setHL(result) @@ -157,7 +157,7 @@ func (z *Z80) sbchl(val uint16) { // increments a byte value func (z *Z80) inc(a byte) byte { cf := z.cf - result := z.addb(a, 1, false) + result := z.addB(a, 1, false) z.cf = cf return result } @@ -165,14 +165,14 @@ func (z *Z80) inc(a byte) byte { // decrements a byte value func (z *Z80) dec(a byte) byte { cf := z.cf - result := z.subb(a, 1, false) + result := z.subB(a, 1, false) z.cf = cf return result } // executes a logic "and" between register A and a byte, then stores the // result in register A -func (z *Z80) land(val byte) { +func (z *Z80) lAnd(val byte) { result := z.a & val z.sf = result&0x80 != 0 z.zf = result == 0 @@ -186,7 +186,7 @@ func (z *Z80) land(val byte) { // executes a logic "xor" between register A and a byte, then stores the // result in register A -func (z *Z80) lxor(val byte) { +func (z *Z80) lXor(val byte) { result := z.a ^ val z.sf = result&0x80 != 0 z.zf = result == 0 @@ -200,7 +200,7 @@ func (z *Z80) lxor(val byte) { // executes a logic "or" between register A and a byte, then stores the // result in register A -func (z *Z80) lor(val byte) { +func (z *Z80) lOr(val byte) { result := z.a | val z.sf = result&0x80 != 0 @@ -215,7 +215,7 @@ func (z *Z80) lor(val byte) { // compares a value with register A func (z *Z80) cp(val byte) { - z.subb(z.a, val, false) + z.subB(z.a, val, false) // the only difference between cp and sub is that // the xf/yf are taken from the value to be subtracted, @@ -226,7 +226,7 @@ func (z *Z80) cp(val byte) { // 0xCB opcodes // rotate left with carry -func (z *Z80) cb_rlc(val byte) byte { +func (z *Z80) cbRlc(val byte) byte { old := val >> 7 val = (val << 1) | old z.sf = val&0x80 != 0 @@ -240,7 +240,7 @@ func (z *Z80) cb_rlc(val byte) byte { } // rotate right with carry -func (z *Z80) cb_rrc(val byte) byte { +func (z *Z80) cbRrc(val byte) byte { old := val & 1 val = (val >> 1) | (old << 7) z.sf = val&0x80 != 0 @@ -254,7 +254,7 @@ func (z *Z80) cb_rrc(val byte) byte { } // rotate left (simple) -func (z *Z80) cb_rl(val byte) byte { +func (z *Z80) cbRl(val byte) byte { cf := z.cf z.cf = val>>7 != 0 val = (val << 1) | bToByte(cf) @@ -268,7 +268,7 @@ func (z *Z80) cb_rl(val byte) byte { } // rotate right (simple) -func (z *Z80) cb_rr(val byte) byte { +func (z *Z80) cbRr(val byte) byte { c := z.cf z.cf = (val & 1) != 0 val = (val >> 1) | (bToByte(c) << 7) @@ -282,7 +282,7 @@ func (z *Z80) cb_rr(val byte) byte { } // shift left preserving sign -func (z *Z80) cb_sla(val byte) byte { +func (z *Z80) cbSla(val byte) byte { z.cf = (val >> 7) != 0 val <<= 1 z.sf = val&0x80 != 0 @@ -295,7 +295,7 @@ func (z *Z80) cb_sla(val byte) byte { } // SLL (exactly like SLA, but sets the first bit to 1) -func (z *Z80) cb_sll(val byte) byte { +func (z *Z80) cbSll(val byte) byte { z.cf = val&0x80 != 0 val <<= 1 val |= 1 @@ -309,7 +309,7 @@ func (z *Z80) cb_sll(val byte) byte { } // shift right preserving sign -func (z *Z80) cb_sra(val byte) byte { +func (z *Z80) cbSra(val byte) byte { z.cf = (val & 1) != 0 val = (val >> 1) | (val & 0x80) // 0b10000000 z.sf = val&0x80 != 0 @@ -322,7 +322,7 @@ func (z *Z80) cb_sra(val byte) byte { } // shift register right -func (z *Z80) cb_srl(val byte) byte { +func (z *Z80) cbSrl(val byte) byte { z.cf = (val & 1) != 0 val >>= 1 z.sf = val&0x80 != 0 @@ -335,7 +335,7 @@ func (z *Z80) cb_srl(val byte) byte { } // tests bit "n" from a byte -func (z *Z80) cb_bit(val byte, n byte) byte { +func (z *Z80) cbBit(val byte, n byte) byte { result := val & (1 << n) z.sf = result&0x80 != 0 z.zf = result == 0 @@ -378,7 +378,7 @@ func (z *Z80) ldd() { func (z *Z80) cpi() { cf := z.cf - result := z.subb(z.a, z.rb(z.hl()), false) + result := z.subB(z.a, z.rb(z.hl()), false) z.setHL(z.hl() + 1) z.setBC(z.bc() - 1) @@ -397,8 +397,6 @@ func (z *Z80) cpd() { z.memPtr -= 2 } -//var halfCarrySubTable = []bool{false, false, true, false, true, false, true, true} - func (z *Z80) inRC(r *byte) { *r = z.core.IORead(z.bc()) z.zf = *r == 0 @@ -496,14 +494,6 @@ func (z *Z80) outd() { } func (z *Z80) daa() { - // "When this instruction is executed, the A register is BCD corrected - // using the contents of the flags. The exact process is the following: - // if the least significant four bits of A contain a non-BCD digit - // (i. e. it is greater than 9) or the H flag is set, then $06 is - // added to the register. Then the four most significant bits are - // checked. If this more significant digit also happens to be greater - // than 9 or the C flag is set, then $60 is added." - // > http://z80-heaven.wikidot.com/instructions-set:daa correction := byte(0) if (z.a&0x0F) > 0x09 || z.hf { @@ -607,7 +597,7 @@ func (z *Z80) execOpcode(opcode byte) { switch opcode { case 0x7F: - z.a = z.a // ld a,a + //z.a = z.a // ld a,a case 0x78: z.a = z.b // ld a,b case 0x79: @@ -624,7 +614,7 @@ func (z *Z80) execOpcode(opcode byte) { case 0x47: z.b = z.a // ld b,a case 0x40: - z.b = z.b // ld b,b + //z.b = z.b // ld b,b case 0x41: z.b = z.c // ld b,c case 0x42: @@ -641,7 +631,7 @@ func (z *Z80) execOpcode(opcode byte) { case 0x48: z.c = z.b // ld c,b case 0x49: - z.c = z.c // ld c,c + //z.c = z.c // ld c,c case 0x4A: z.c = z.d // ld c,d case 0x4B: @@ -658,7 +648,7 @@ func (z *Z80) execOpcode(opcode byte) { case 0x51: z.d = z.c // ld d,c case 0x52: - z.d = z.d // ld d,d + //z.d = z.d // ld d,d case 0x53: z.d = z.e // ld d,e case 0x54: @@ -675,7 +665,7 @@ func (z *Z80) execOpcode(opcode byte) { case 0x5A: z.e = z.d // ld e,d case 0x5B: - z.e = z.e // ld e,e + //z.e = z.e // ld e,e case 0x5C: z.e = z.h // ld e,h case 0x5D: @@ -692,7 +682,7 @@ func (z *Z80) execOpcode(opcode byte) { case 0x63: z.h = z.e // ld h,e case 0x64: - z.h = z.h // ld h,h + //z.h = z.h // ld h,h case 0x65: z.h = z.l // ld h,l @@ -709,7 +699,7 @@ func (z *Z80) execOpcode(opcode byte) { case 0x6C: z.l = z.h // ld l,h case 0x6D: - z.l = z.l // ld l,l + //z.l = z.l // ld l,l case 0x7E: z.a = z.rb(z.hl()) // ld a,(hl) @@ -817,89 +807,89 @@ func (z *Z80) execOpcode(opcode byte) { z.setHL(val) z.memPtr = val case 0x87: - z.a = z.addb(z.a, z.a, false) // add a,a + z.a = z.addB(z.a, z.a, false) // add a,a case 0x80: - z.a = z.addb(z.a, z.b, false) // add a,b + z.a = z.addB(z.a, z.b, false) // add a,b case 0x81: - z.a = z.addb(z.a, z.c, false) // add a,c + z.a = z.addB(z.a, z.c, false) // add a,c case 0x82: - z.a = z.addb(z.a, z.d, false) // add a,d + z.a = z.addB(z.a, z.d, false) // add a,d case 0x83: - z.a = z.addb(z.a, z.e, false) // add a,e + z.a = z.addB(z.a, z.e, false) // add a,e case 0x84: - z.a = z.addb(z.a, z.h, false) // add a,h + z.a = z.addB(z.a, z.h, false) // add a,h case 0x85: - z.a = z.addb(z.a, z.l, false) // add a,l + z.a = z.addB(z.a, z.l, false) // add a,l case 0x86: - z.a = z.addb(z.a, z.rb(z.hl()), false) // add a,(hl) + z.a = z.addB(z.a, z.rb(z.hl()), false) // add a,(hl) case 0xC6: - z.a = z.addb(z.a, z.nextB(), false) // add a,* + z.a = z.addB(z.a, z.nextB(), false) // add a,* case 0x8F: - z.a = z.addb(z.a, z.a, z.cf) // adc a,a + z.a = z.addB(z.a, z.a, z.cf) // adc a,a case 0x88: - z.a = z.addb(z.a, z.b, z.cf) // adc a,b + z.a = z.addB(z.a, z.b, z.cf) // adc a,b case 0x89: - z.a = z.addb(z.a, z.c, z.cf) // adc a,c + z.a = z.addB(z.a, z.c, z.cf) // adc a,c case 0x8A: - z.a = z.addb(z.a, z.d, z.cf) // adc a,d + z.a = z.addB(z.a, z.d, z.cf) // adc a,d case 0x8B: - z.a = z.addb(z.a, z.e, z.cf) // adc a,e + z.a = z.addB(z.a, z.e, z.cf) // adc a,e case 0x8C: - z.a = z.addb(z.a, z.h, z.cf) // adc a,h + z.a = z.addB(z.a, z.h, z.cf) // adc a,h case 0x8D: - z.a = z.addb(z.a, z.l, z.cf) // adc a,l + z.a = z.addB(z.a, z.l, z.cf) // adc a,l case 0x8E: - z.a = z.addb(z.a, z.rb(z.hl()), z.cf) // adc a,(hl) + z.a = z.addB(z.a, z.rb(z.hl()), z.cf) // adc a,(hl) case 0xCE: - z.a = z.addb(z.a, z.nextB(), z.cf) // adc a,* + z.a = z.addB(z.a, z.nextB(), z.cf) // adc a,* case 0x97: - z.a = z.subb(z.a, z.a, false) // sub a,a + z.a = z.subB(z.a, z.a, false) // sub a,a case 0x90: - z.a = z.subb(z.a, z.b, false) // sub a,b + z.a = z.subB(z.a, z.b, false) // sub a,b case 0x91: - z.a = z.subb(z.a, z.c, false) // sub a,c + z.a = z.subB(z.a, z.c, false) // sub a,c case 0x92: - z.a = z.subb(z.a, z.d, false) // sub a,d + z.a = z.subB(z.a, z.d, false) // sub a,d case 0x93: - z.a = z.subb(z.a, z.e, false) // sub a,e + z.a = z.subB(z.a, z.e, false) // sub a,e case 0x94: - z.a = z.subb(z.a, z.h, false) // sub a,h + z.a = z.subB(z.a, z.h, false) // sub a,h case 0x95: - z.a = z.subb(z.a, z.l, false) // sub a,l + z.a = z.subB(z.a, z.l, false) // sub a,l case 0x96: - z.a = z.subb(z.a, z.rb(z.hl()), false) // sub a,(hl) + z.a = z.subB(z.a, z.rb(z.hl()), false) // sub a,(hl) case 0xD6: - z.a = z.subb(z.a, z.nextB(), false) // sub a,* + z.a = z.subB(z.a, z.nextB(), false) // sub a,* case 0x9F: - z.a = z.subb(z.a, z.a, z.cf) // sbc a,a + z.a = z.subB(z.a, z.a, z.cf) // sbc a,a case 0x98: - z.a = z.subb(z.a, z.b, z.cf) // sbc a,b + z.a = z.subB(z.a, z.b, z.cf) // sbc a,b case 0x99: - z.a = z.subb(z.a, z.c, z.cf) // sbc a,c + z.a = z.subB(z.a, z.c, z.cf) // sbc a,c case 0x9A: - z.a = z.subb(z.a, z.d, z.cf) // sbc a,d + z.a = z.subB(z.a, z.d, z.cf) // sbc a,d case 0x9B: - z.a = z.subb(z.a, z.e, z.cf) // sbc a,e + z.a = z.subB(z.a, z.e, z.cf) // sbc a,e case 0x9C: - z.a = z.subb(z.a, z.h, z.cf) // sbc a,h + z.a = z.subB(z.a, z.h, z.cf) // sbc a,h case 0x9D: - z.a = z.subb(z.a, z.l, z.cf) // sbc a,l + z.a = z.subB(z.a, z.l, z.cf) // sbc a,l case 0x9E: - z.a = z.subb(z.a, z.rb(z.hl()), z.cf) // sbc a,(hl) + z.a = z.subB(z.a, z.rb(z.hl()), z.cf) // sbc a,(hl) case 0xDE: - z.a = z.subb(z.a, z.nextB(), z.cf) // sbc a,* + z.a = z.subB(z.a, z.nextB(), z.cf) // sbc a,* case 0x09: - z.addhl(z.bc()) // add hl,bc + z.addHL(z.bc()) // add hl,bc case 0x19: - z.addhl(z.de()) // add hl,de + z.addHL(z.de()) // add hl,de case 0x29: - z.addhl(z.hl()) // add hl,hl + z.addHL(z.hl()) // add hl,hl case 0x39: - z.addhl(z.sp) // add hl,sp + z.addHL(z.sp) // add hl,sp case 0xF3: z.iff1 = false @@ -1013,61 +1003,61 @@ func (z *Z80) execOpcode(opcode byte) { z.hf = false z.updateXY(z.a) case 0xA7: - z.land(z.a) // and a + z.lAnd(z.a) // and a case 0xA0: - z.land(z.b) // and b + z.lAnd(z.b) // and b case 0xA1: - z.land(z.c) // and c + z.lAnd(z.c) // and c case 0xA2: - z.land(z.d) // and d + z.lAnd(z.d) // and d case 0xA3: - z.land(z.e) // and e + z.lAnd(z.e) // and e case 0xA4: - z.land(z.h) // and h + z.lAnd(z.h) // and h case 0xA5: - z.land(z.l) // and l + z.lAnd(z.l) // and l case 0xA6: - z.land(z.rb(z.hl())) // and (hl) + z.lAnd(z.rb(z.hl())) // and (hl) case 0xE6: - z.land(z.nextB()) // and * + z.lAnd(z.nextB()) // and * case 0xAF: - z.lxor(z.a) // xor a + z.lXor(z.a) // xor a case 0xA8: - z.lxor(z.b) // xor b + z.lXor(z.b) // xor b case 0xA9: - z.lxor(z.c) // xor c + z.lXor(z.c) // xor c case 0xAA: - z.lxor(z.d) // xor d + z.lXor(z.d) // xor d case 0xAB: - z.lxor(z.e) // xor e + z.lXor(z.e) // xor e case 0xAC: - z.lxor(z.h) // xor h + z.lXor(z.h) // xor h case 0xAD: - z.lxor(z.l) // xor l + z.lXor(z.l) // xor l case 0xAE: - z.lxor(z.rb(z.hl())) // xor (hl) + z.lXor(z.rb(z.hl())) // xor (hl) case 0xEE: - z.lxor(z.nextB()) // xor * + z.lXor(z.nextB()) // xor * case 0xB7: - z.lor(z.a) // or a + z.lOr(z.a) // or a case 0xB0: - z.lor(z.b) // or b + z.lOr(z.b) // or b case 0xB1: - z.lor(z.c) // or c + z.lOr(z.c) // or c case 0xB2: - z.lor(z.d) // or d + z.lOr(z.d) // or d case 0xB3: - z.lor(z.e) // or e + z.lOr(z.e) // or e case 0xB4: - z.lor(z.h) // or h + z.lOr(z.h) // or h case 0xB5: - z.lor(z.l) // or l + z.lOr(z.l) // or l case 0xB6: - z.lor(z.rb(z.hl())) // or (hl) + z.lOr(z.rb(z.hl())) // or (hl) case 0xF6: - z.lor(z.nextB()) // or * + z.lOr(z.nextB()) // or * case 0xBF: z.cp(z.a) // cp a @@ -1091,36 +1081,36 @@ func (z *Z80) execOpcode(opcode byte) { case 0xC3: z.jump(z.nextW()) // jm ** case 0xC2: - z.cond_jump(!z.zf) // jp nz, ** + z.condJump(!z.zf) // jp nz, ** case 0xCA: - z.cond_jump(z.zf) // jp z, ** + z.condJump(z.zf) // jp z, ** case 0xD2: - z.cond_jump(!z.cf) // jp nc, ** + z.condJump(!z.cf) // jp nc, ** case 0xDA: - z.cond_jump(z.cf) // jp c, ** + z.condJump(z.cf) // jp c, ** case 0xE2: - z.cond_jump(!z.pf) // jp po, ** + z.condJump(!z.pf) // jp po, ** case 0xEA: - z.cond_jump(z.pf) // jp pe, ** + z.condJump(z.pf) // jp pe, ** case 0xF2: - z.cond_jump(!z.sf) // jp p, ** + z.condJump(!z.sf) // jp p, ** case 0xFA: - z.cond_jump(z.sf) // jp m, ** + z.condJump(z.sf) // jp m, ** case 0x10: z.b-- - z.cond_jr(z.b != 0) // djnz * + z.condJr(z.b != 0) // djnz * case 0x18: z.pc += uint16(z.nextB()) // jr * z.memPtr = z.pc case 0x20: - z.cond_jr(!z.zf) // jr nz, * + z.condJr(!z.zf) // jr nz, * case 0x28: - z.cond_jr(z.zf) // jr z, * + z.condJr(z.zf) // jr z, * case 0x30: - z.cond_jr(!z.cf) // jr nc, * + z.condJr(!z.cf) // jr nc, * case 0x38: - z.cond_jr(z.cf) // jr c, * + z.condJr(z.cf) // jr c, * case 0xE9: z.pc = z.hl() // jp (hl) @@ -1128,40 +1118,40 @@ func (z *Z80) execOpcode(opcode byte) { z.call(z.nextW()) // call case 0xC4: - z.cond_call(!z.zf) // cnz + z.condCall(!z.zf) // cnz case 0xCC: - z.cond_call(z.zf) // cz + z.condCall(z.zf) // cz case 0xD4: - z.cond_call(!z.cf) // cnc + z.condCall(!z.cf) // cnc case 0xDC: - z.cond_call(z.cf) // cc + z.condCall(z.cf) // cc case 0xE4: - z.cond_call(!z.pf) // cpo + z.condCall(!z.pf) // cpo case 0xEC: - z.cond_call(z.pf) // cpe + z.condCall(z.pf) // cpe case 0xF4: - z.cond_call(!z.sf) // cp + z.condCall(!z.sf) // cp case 0xFC: - z.cond_call(z.sf) // cm + z.condCall(z.sf) // cm case 0xC9: z.ret() // ret case 0xC0: - z.cond_ret(!z.zf) // ret nz + z.condRet(!z.zf) // ret nz case 0xC8: - z.cond_ret(z.zf) // ret z + z.condRet(z.zf) // ret z case 0xD0: - z.cond_ret(!z.cf) // ret nc + z.condRet(!z.cf) // ret nc case 0xD8: - z.cond_ret(z.cf) // ret c + z.condRet(z.cf) // ret c case 0xE0: - z.cond_ret(!z.pf) // ret po + z.condRet(!z.pf) // ret po case 0xE8: - z.cond_ret(z.pf) // ret pe + z.condRet(z.pf) // ret pe case 0xF0: - z.cond_ret(!z.sf) // ret p + z.condRet(!z.sf) // ret p case 0xF8: - z.cond_ret(z.sf) // ret m + z.condRet(z.sf) // ret m case 0xC7: z.call(0x00) // rst 0 diff --git a/z80/c99/opcodesCB.go b/z80/c99/opcodesCB.go index c972e4f..76c20c0 100644 --- a/z80/c99/opcodesCB.go +++ b/z80/c99/opcodesCB.go @@ -40,26 +40,26 @@ func (z *Z80) execOpcodeCB(opcode byte) { // rot[y] r[z] switch y_ { case 0: - *reg = z.cb_rlc(*reg) + *reg = z.cbRlc(*reg) case 1: - *reg = z.cb_rrc(*reg) + *reg = z.cbRrc(*reg) case 2: - *reg = z.cb_rl(*reg) + *reg = z.cbRl(*reg) case 3: - *reg = z.cb_rr(*reg) + *reg = z.cbRr(*reg) case 4: - *reg = z.cb_sla(*reg) + *reg = z.cbSla(*reg) case 5: - *reg = z.cb_sra(*reg) + *reg = z.cbSra(*reg) case 6: - *reg = z.cb_sll(*reg) + *reg = z.cbSll(*reg) case 7: - *reg = z.cb_srl(*reg) + *reg = z.cbSrl(*reg) } case 1: // BIT y, r[z] - z.cb_bit(*reg, y_) + z.cbBit(*reg, y_) // in bit (hl), x/y flags are handled differently: if z_ == 6 { @@ -82,8 +82,8 @@ func (z *Z80) execOpcodeCB(opcode byte) { } } -// exec_opcode_dcb executes a displaced CB opcode (DDCB or FDCB) -func (z *Z80) exec_opcode_dcb(opcode byte, addr uint16) { +// execOpcodeDcb executes a displaced CB opcode (DDCB or FDCB) +func (z *Z80) execOpcodeDcb(opcode byte, addr uint16) { val := z.rb(addr) result := byte(0) @@ -97,26 +97,26 @@ func (z *Z80) exec_opcode_dcb(opcode byte, addr uint16) { // rot[y] (iz+d) switch y_ { case 0: - result = z.cb_rlc(val) + result = z.cbRlc(val) case 1: - result = z.cb_rrc(val) + result = z.cbRrc(val) case 2: - result = z.cb_rl(val) + result = z.cbRl(val) case 3: - result = z.cb_rr(val) + result = z.cbRr(val) case 4: - result = z.cb_sla(val) + result = z.cbSla(val) case 5: - result = z.cb_sra(val) + result = z.cbSra(val) case 6: - result = z.cb_sll(val) + result = z.cbSll(val) case 7: - result = z.cb_srl(val) + result = z.cbSrl(val) } case 1: // bit y,(iz+d) - result = z.cb_bit(val, y_) + result = z.cbBit(val, y_) z.updateXY(byte(addr >> 8)) case 2: result = val & ^(1 << y_) // res y, (iz+d) diff --git a/z80/c99/opcodesDDFD.go b/z80/c99/opcodesDDFD.go index 3c1f4ef..d487383 100644 --- a/z80/c99/opcodesDDFD.go +++ b/z80/c99/opcodesDDFD.go @@ -15,58 +15,58 @@ func (z *Z80) execOpcodeDDFD(opcode byte, iz *uint16) { z.pc = *iz //z.jump(*iz) case 0x09: - z.addiz(iz, z.bc()) // add iz,bc + z.addIZ(iz, z.bc()) // add iz,bc case 0x19: - z.addiz(iz, z.de()) // add iz,de + z.addIZ(iz, z.de()) // add iz,de case 0x29: - z.addiz(iz, *iz) // add iz,iz + z.addIZ(iz, *iz) // add iz,iz case 0x39: - z.addiz(iz, z.sp) // add iz,sp + z.addIZ(iz, z.sp) // add iz,sp case 0x84: - z.a = z.addb(z.a, byte(*iz>>8), false) // add a,izh + z.a = z.addB(z.a, byte(*iz>>8), false) // add a,izh case 0x85: - z.a = z.addb(z.a, byte(*iz), false) // add a,izl + z.a = z.addB(z.a, byte(*iz), false) // add a,izl case 0x8C: - z.a = z.addb(z.a, byte(*iz>>8), z.cf) // adc a,izh + z.a = z.addB(z.a, byte(*iz>>8), z.cf) // adc a,izh case 0x8D: - z.a = z.addb(z.a, byte(*iz), z.cf) // adc a,izl + z.a = z.addB(z.a, byte(*iz), z.cf) // adc a,izl case 0x86: - z.a = z.addb(z.a, z.rb(z.displace(*iz, z.nextB())), false) // add a,(iz+*) + z.a = z.addB(z.a, z.rb(z.displace(*iz, z.nextB())), false) // add a,(iz+*) case 0x8E: - z.a = z.addb(z.a, z.rb(z.displace(*iz, z.nextB())), z.cf) // adc a,(iz+*) + z.a = z.addB(z.a, z.rb(z.displace(*iz, z.nextB())), z.cf) // adc a,(iz+*) case 0x96: - z.a = z.subb(z.a, z.rb(z.displace(*iz, z.nextB())), false) // sub (iz+*) + z.a = z.subB(z.a, z.rb(z.displace(*iz, z.nextB())), false) // sub (iz+*) case 0x9E: - z.a = z.subb(z.a, z.rb(z.displace(*iz, z.nextB())), z.cf) // sbc (iz+*) + z.a = z.subB(z.a, z.rb(z.displace(*iz, z.nextB())), z.cf) // sbc (iz+*) case 0x94: - z.a = z.subb(z.a, byte(*iz>>8), false) // sub izh + z.a = z.subB(z.a, byte(*iz>>8), false) // sub izh case 0x95: - z.a = z.subb(z.a, byte(*iz), false) // sub izl + z.a = z.subB(z.a, byte(*iz), false) // sub izl case 0x9C: - z.a = z.subb(z.a, byte(*iz>>8), z.cf) // sbc izh + z.a = z.subB(z.a, byte(*iz>>8), z.cf) // sbc izh case 0x9D: - z.a = z.subb(z.a, byte(*iz), z.cf) // sbc izl + z.a = z.subB(z.a, byte(*iz), z.cf) // sbc izl case 0xA6: - z.land(z.rb(z.displace(*iz, z.nextB()))) // and (iz+*) + z.lAnd(z.rb(z.displace(*iz, z.nextB()))) // and (iz+*) case 0xA4: - z.land(byte(*iz >> 8)) // and izh + z.lAnd(byte(*iz >> 8)) // and izh case 0xA5: - z.land(byte(*iz)) // and izl + z.lAnd(byte(*iz)) // and izl case 0xAE: - z.lxor(z.rb(z.displace(*iz, z.nextB()))) // xor (iz+*) + z.lXor(z.rb(z.displace(*iz, z.nextB()))) // xor (iz+*) case 0xAC: - z.lxor(byte(*iz >> 8)) // xor izh + z.lXor(byte(*iz >> 8)) // xor izh case 0xAD: - z.lxor(byte(*iz)) // xor izl + z.lXor(byte(*iz)) // xor izl case 0xB6: - z.lor(z.rb(z.displace(*iz, z.nextB()))) // or (iz+*) + z.lOr(z.rb(z.displace(*iz, z.nextB()))) // or (iz+*) case 0xB4: - z.lor(byte(*iz >> 8)) // or izh + z.lOr(byte(*iz >> 8)) // or izh case 0xB5: - z.lor(byte(*iz)) // or izl + z.lOr(byte(*iz)) // or izl case 0xBE: z.cp(z.rb(z.displace(*iz, z.nextB()))) // cp (iz+*) case 0xBC: @@ -196,7 +196,7 @@ func (z *Z80) execOpcodeDDFD(opcode byte, iz *uint16) { case 0xCB: addr := z.displace(*iz, z.nextB()) op := z.nextB() - z.exec_opcode_dcb(op, addr) + z.execOpcodeDcb(op, addr) default: // any other FD/DD opcode behaves as a non-prefixed opcode: z.execOpcode(opcode) diff --git a/z80/c99/opcodesED.go b/z80/c99/opcodesED.go index 9bba34e..ef50331 100644 --- a/z80/c99/opcodesED.go +++ b/z80/c99/opcodesED.go @@ -185,21 +185,21 @@ func (z *Z80) execOpcodeED(opcode byte) { } case 0x42: - z.sbchl(z.bc()) // sbc hl,bc + z.sbcHL(z.bc()) // sbc hl,bc case 0x52: - z.sbchl(z.de()) // sbc hl,de + z.sbcHL(z.de()) // sbc hl,de case 0x62: - z.sbchl(z.hl()) // sbc hl,hl + z.sbcHL(z.hl()) // sbc hl,hl case 0x72: - z.sbchl(z.sp) // sbc hl,sp + z.sbcHL(z.sp) // sbc hl,sp case 0x4A: - z.adchl(z.bc()) // adc hl,bc + z.adcHL(z.bc()) // adc hl,bc case 0x5A: - z.adchl(z.de()) // adc hl,de + z.adcHL(z.de()) // adc hl,de case 0x6A: - z.adchl(z.hl()) // adc hl,hl + z.adcHL(z.hl()) // adc hl,hl case 0x7A: - z.adchl(z.sp) // adc hl,sp + z.adcHL(z.sp) // adc hl,sp case 0x43: // ld (**), bc addr := z.nextW() @@ -241,7 +241,7 @@ func (z *Z80) execOpcodeED(opcode byte) { z.sp = z.rw(addr) z.memPtr = addr + 1 case 0x44, 0x54, 0x64, 0x74, 0x4C, 0x5C, 0x6C, 0x7C: - z.a = z.subb(0, z.a, false) // neg + z.a = z.subB(0, z.a, false) // neg case 0x46, 0x4e, 0x66, 0x6e: z.interruptMode = 0 // im 0 case 0x56, 0x76: diff --git a/z80/cpu.go b/z80/cpu.go index 4e0e25c..b70b96f 100644 --- a/z80/cpu.go +++ b/z80/cpu.go @@ -103,6 +103,46 @@ func (f *FlagsType) GetFlags() byte { return flags } +func (f *FlagsType) GetFlagsStr() string { + flags := []byte{'-', '-', '-', '-', '-', '-', '-', '-'} + if f.S { + flags[0] = 'S' + } + if f.Z { + flags[1] = 'Z' + } + if f.Y { + flags[2] = '5' + } + if f.H { + flags[3] = 'H' + } + if f.X { + flags[4] = '3' + } + if f.P { + flags[5] = 'P' + } + if f.N { + flags[6] = 'N' + } + if f.C { + flags[7] = 'C' + } + return string(flags) +} + +func (z *Z80CPU) IIFStr() string { + flags := []byte{'-', '-'} + if z.Iff1 { + flags[0] = '1' + } + if z.Iff2 { + flags[1] = '2' + } + return string(flags) +} + func GetFlags(f byte) FlagsType { return FlagsType{ S: f&0x80 != 0, diff --git a/z80/cpu_test.go b/z80/cpu_test.go index 7d436d3..46f7ae6 100644 --- a/z80/cpu_test.go +++ b/z80/cpu_test.go @@ -68,10 +68,6 @@ type Z80TestIn struct { memorySetup []MemorySetup } -type Z80TestExpected struct { - expect Expect -} - type Expect struct { events []Event registers Registers