mirror of
https://github.com/romychs/Ocean-240.2-Emulator.git
synced 2026-04-21 11:03:21 +03:00
ZEsarUX ZRCP Partial debug protocol implementation
This commit is contained in:
parent
b70b02a4be
commit
b200f269a0
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
const defaultMonitorFile = "rom/MON_v5.bin"
|
const defaultMonitorFile = "rom/MON_v5.bin"
|
||||||
const defaultCPMFile = "rom/CPM_v5.bin"
|
const defaultCPMFile = "rom/CPM_v5.bin"
|
||||||
|
const DefaultDebufPort = 10000
|
||||||
|
|
||||||
type OkEmuConfig struct {
|
type OkEmuConfig struct {
|
||||||
LogFile string `yaml:"logFile"`
|
LogFile string `yaml:"logFile"`
|
||||||
@ -17,6 +18,8 @@ type OkEmuConfig struct {
|
|||||||
CPMFile string `yaml:"cpmFile"`
|
CPMFile string `yaml:"cpmFile"`
|
||||||
FloppyB string `yaml:"floppyB"`
|
FloppyB string `yaml:"floppyB"`
|
||||||
FloppyC string `yaml:"floppyC"`
|
FloppyC string `yaml:"floppyC"`
|
||||||
|
Host string `yaml:"host"`
|
||||||
|
Port int `yaml:"port"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var config *OkEmuConfig
|
var config *OkEmuConfig
|
||||||
@ -59,7 +62,9 @@ func LoadConfig() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkConfig(conf *OkEmuConfig) {
|
func checkConfig(conf *OkEmuConfig) {
|
||||||
|
if conf.Host == "" {
|
||||||
|
conf.Host = "localhost"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setDefaultConf(conf *OkEmuConfig) {
|
func setDefaultConf(conf *OkEmuConfig) {
|
||||||
@ -75,4 +80,8 @@ func setDefaultConf(conf *OkEmuConfig) {
|
|||||||
if conf.CPMFile == "" {
|
if conf.CPMFile == "" {
|
||||||
conf.CPMFile = defaultCPMFile
|
conf.CPMFile = defaultCPMFile
|
||||||
}
|
}
|
||||||
|
if conf.Port < 80 || conf.Port > 65535 {
|
||||||
|
log.Infof("Port %d incorrect, using default: %d", conf.Port, DefaultDebufPort)
|
||||||
|
conf.Port = DefaultDebufPort
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
469
debuger/listener.go
Normal file
469
debuger/listener.go
Normal file
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
74
dezog/protocol.go
Normal file
74
dezog/protocol.go
Normal file
@ -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
|
||||||
|
)
|
||||||
6
go.mod
6
go.mod
@ -3,12 +3,13 @@ module okemu
|
|||||||
go 1.25
|
go 1.25
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
fyne.io/fyne/v2 v2.7.3
|
||||||
|
github.com/howeyc/crc16 v0.0.0-20171223171357-2b2a61e366a6
|
||||||
github.com/sirupsen/logrus v1.9.4
|
github.com/sirupsen/logrus v1.9.4
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
fyne.io/fyne/v2 v2.7.3 // indirect
|
|
||||||
fyne.io/systray v1.12.0 // indirect
|
fyne.io/systray v1.12.0 // indirect
|
||||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // 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/gl-js v0.2.0 // indirect
|
||||||
github.com/fyne-io/glfw-js v0.3.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/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/fyne-io/oksvg v0.2.0 // indirect
|
||||||
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // 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-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect
|
||||||
github.com/go-text/render v0.2.0 // indirect
|
github.com/go-text/render v0.2.0 // indirect
|
||||||
github.com/go-text/typesetting v0.3.3 // indirect
|
github.com/go-text/typesetting v0.3.3 // indirect
|
||||||
github.com/godbus/dbus/v5 v5.1.0 // 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/go-indexeddb v0.3.2 // indirect
|
||||||
github.com/hack-pad/safejs v0.1.0 // indirect
|
github.com/hack-pad/safejs v0.1.0 // indirect
|
||||||
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect
|
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect
|
||||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // 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/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect
|
github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
|
|||||||
82
go.sum
82
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 h1:xBT/iYbdnNHONWO38fZMBrVBiJG8rV/Jypmy4tVfRWE=
|
||||||
fyne.io/fyne/v2 v2.7.3/go.mod h1:gu+dlIcZWSzKZmnrY8Fbnj2Hirabv2ek+AKsfQ2bBlw=
|
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 h1:CA1Kk0e2zwFlxtc02L3QFSiIbxJ/P0n582YrZHT7aTM=
|
||||||
fyne.io/systray v1.12.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs=
|
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 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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/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 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko=
|
||||||
github.com/fredbi/uri v1.1.1/go.mod h1:4+DZQ5zBjEwQCDmXW5JdIjz0PUA+yJbvtBv+u+adr5o=
|
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 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs=
|
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/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 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA=
|
||||||
github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM=
|
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 h1:mxcGU2dx6nwjJsSA9PCYZDuoAcsZ/OuJlvg/Q9Njfo8=
|
||||||
github.com/fyne-io/oksvg v0.2.0/go.mod h1:dJ9oEkPiWhnTFNCmRgEze+YNprJF7YRbpjgpWS4kzoI=
|
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 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA=
|
||||||
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
|
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 h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
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 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc=
|
||||||
github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU=
|
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 h1:ihGNJU9KzdK2QRDy1Bm7FT5RFQoYb+3n3EIhI/4eaQc=
|
||||||
github.com/go-text/typesetting v0.3.3/go.mod h1:vIRUT25mLQaSh4C8H/lIsKppQz/Gdb8Pu/tNwpi52ts=
|
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/go-text/typesetting-utils v0.0.0-20250618110550-c820a94c77b8 h1:4KCscI9qYWMGTuz6BpJtbUSRzcBrUSSE0ENMJbNSrFs=
|
||||||
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
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 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
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/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y=
|
||||||
github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw=
|
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 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A=
|
||||||
github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0=
|
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 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8=
|
||||||
github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
|
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 h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE=
|
||||||
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
|
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 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M=
|
||||||
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
|
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.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/lucor/goinfo v0.0.0-20200401173949-526b5363a13a/go.mod h1:ORP3/rB5IsulLEBwQZCJyyV6niqmI7P4EWSmkug+1Ng=
|
|
||||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
|
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/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 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk=
|
||||||
github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ=
|
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/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/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU=
|
||||||
github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
|
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 h1:TsZE7l11zFCLZnZ+teH4Umoq5BhEIfIzfRDZ1Uzql2w=
|
||||||
github.com/sirupsen/logrus v1.9.4/go.mod h1:ftWc9WdOfJ0a92nsE2jF5u5ZwH8Bv2zdeOC42RjbV2g=
|
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 h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE=
|
||||||
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
|
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 h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
|
||||||
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
|
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 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
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 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
|
||||||
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
|
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 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
|
||||||
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
|
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 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
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 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
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 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
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 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 h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
38
main.go
38
main.go
@ -5,6 +5,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"image/color"
|
"image/color"
|
||||||
"okemu/config"
|
"okemu/config"
|
||||||
|
"okemu/debuger"
|
||||||
"okemu/logger"
|
"okemu/logger"
|
||||||
"okemu/okean240"
|
"okemu/okean240"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@ -21,11 +22,14 @@ import (
|
|||||||
var Version = "v1.0.0"
|
var Version = "v1.0.0"
|
||||||
var BuildTime = "2026-03-01"
|
var BuildTime = "2026-03-01"
|
||||||
|
|
||||||
//go:embed hex/format.hex
|
//go:embed hex/m80.hex
|
||||||
var serialBytes []byte
|
var serialBytes []byte
|
||||||
|
|
||||||
//go:embed bin/FORMAT.COM
|
//go:embed bin/main.com
|
||||||
var ramBytes []byte
|
var ramBytes1 []byte
|
||||||
|
|
||||||
|
//go:embed bin/PLOT.BAS
|
||||||
|
var ramBytes2 []byte
|
||||||
|
|
||||||
var needReset = false
|
var needReset = false
|
||||||
var fullSpeed atomic.Bool
|
var fullSpeed atomic.Bool
|
||||||
@ -53,6 +57,8 @@ func main() {
|
|||||||
|
|
||||||
go emulator(computer)
|
go emulator(computer)
|
||||||
go screen(computer, raster, label)
|
go screen(computer, raster, label)
|
||||||
|
go debuger.SetupTcpHandler(conf, computer)
|
||||||
|
|
||||||
(*w).ShowAndRun()
|
(*w).ShowAndRun()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,14 +112,22 @@ func mainWindow(computer *okean240.ComputerType) (*fyne.Window, *canvas.Raster,
|
|||||||
widget.NewButton("Save Floppy", func() {
|
widget.NewButton("Save Floppy", func() {
|
||||||
computer.SaveFloppy()
|
computer.SaveFloppy()
|
||||||
}),
|
}),
|
||||||
widget.NewButton("RUN", func() {
|
widget.NewButton("RUN1", func() {
|
||||||
computer.SetRamBytes(ramBytes)
|
computer.SetRamBytes(ramBytes1)
|
||||||
|
}),
|
||||||
|
widget.NewButton("RUN2", func() {
|
||||||
|
computer.SetRamBytes(ramBytes2)
|
||||||
}),
|
}),
|
||||||
widget.NewButton("DUMP", func() {
|
widget.NewButton("DUMP", func() {
|
||||||
computer.Dump(0x100, 15000)
|
computer.Dump(0x100, 15000)
|
||||||
}),
|
}),
|
||||||
widget.NewCheck("Full speed", func(b bool) {
|
widget.NewCheck("Full speed", func(b bool) {
|
||||||
fullSpeed.Store(b)
|
fullSpeed.Store(b)
|
||||||
|
if b {
|
||||||
|
computer.SetCPUFrequency(50_000_000)
|
||||||
|
} else {
|
||||||
|
computer.SetCPUFrequency(2_500_000)
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
widget.NewSeparator(),
|
widget.NewSeparator(),
|
||||||
widget.NewButton("Reset", func() {
|
widget.NewButton("Reset", func() {
|
||||||
@ -170,14 +184,22 @@ func emulator(computer *okean240.ComputerType) {
|
|||||||
// 1.5 MHz
|
// 1.5 MHz
|
||||||
computer.TimerClk()
|
computer.TimerClk()
|
||||||
}
|
}
|
||||||
|
if !computer.IsStepMode() || computer.IsRunMode() {
|
||||||
|
var bp uint16 = 0
|
||||||
if fullSpeed.Load() {
|
if fullSpeed.Load() {
|
||||||
computer.Do()
|
_, bp = computer.Do()
|
||||||
} else {
|
} else {
|
||||||
if ticks >= nextClock {
|
if ticks >= nextClock {
|
||||||
nextClock = ticks + uint64(computer.Do())*ticksPerTact
|
var t uint32
|
||||||
|
t, bp = computer.Do()
|
||||||
|
nextClock = ticks + uint64(t)*ticksPerTact
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Breakpoint hit
|
||||||
|
if bp > 0 {
|
||||||
|
debuger.BreakpointHit(bp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//computer.Do()
|
|
||||||
if needReset {
|
if needReset {
|
||||||
computer.Reset()
|
computer.Reset()
|
||||||
needReset = false
|
needReset = false
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import (
|
|||||||
"okemu/okean240/pic"
|
"okemu/okean240/pic"
|
||||||
"okemu/okean240/pit"
|
"okemu/okean240/pit"
|
||||||
"okemu/okean240/usart"
|
"okemu/okean240/usart"
|
||||||
|
"okemu/z80"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
//"okemu/z80"
|
//"okemu/z80"
|
||||||
@ -19,6 +20,13 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const DefaultCPUFrequency = 2_500_000
|
||||||
|
|
||||||
|
type Breakpoint struct {
|
||||||
|
addr uint16
|
||||||
|
enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
type ComputerType struct {
|
type ComputerType struct {
|
||||||
cpu *c99.Z80
|
cpu *c99.Z80
|
||||||
memory Memory
|
memory Memory
|
||||||
@ -38,9 +46,15 @@ type ComputerType struct {
|
|||||||
kbdBuffer []byte
|
kbdBuffer []byte
|
||||||
vShift byte
|
vShift byte
|
||||||
hShift byte
|
hShift byte
|
||||||
|
stepMode bool
|
||||||
|
runMode bool
|
||||||
|
bpEnabled bool
|
||||||
|
breakpoints [MaxBreakpoints]Breakpoint
|
||||||
//aOffset uint16
|
//aOffset uint16
|
||||||
|
cpuFrequency uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MaxBreakpoints = 256
|
||||||
const VRAMBlock0 = 3
|
const VRAMBlock0 = 3
|
||||||
const VRAMBlock1 = 7
|
const VRAMBlock1 = 7
|
||||||
const VidVsuBit = 0x80
|
const VidVsuBit = 0x80
|
||||||
@ -57,9 +71,69 @@ type ComputerInterface interface {
|
|||||||
PutCtrlKey(shortcut fyne.Shortcut)
|
PutCtrlKey(shortcut fyne.Shortcut)
|
||||||
SaveFloppy()
|
SaveFloppy()
|
||||||
LoadFloppy()
|
LoadFloppy()
|
||||||
|
CPUState() *z80.Z80CPU
|
||||||
|
SetCPUState(state *z80.Z80CPU)
|
||||||
|
StepMode() bool
|
||||||
|
SetStepMode(step bool)
|
||||||
|
ClearMemBreakpoints()
|
||||||
|
SetBreakpointsEnabled(enabled bool)
|
||||||
|
IsBreakpoint() bool
|
||||||
//Dump(start uint16, length uint16)
|
//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 {
|
func (c *ComputerType) M1MemRead(addr uint16) byte {
|
||||||
return c.memory.M1MemRead(addr)
|
return c.memory.M1MemRead(addr)
|
||||||
}
|
}
|
||||||
@ -96,7 +170,14 @@ func New(cfg *config.OkEmuConfig) *ComputerType {
|
|||||||
c.usart = usart.New()
|
c.usart = usart.New()
|
||||||
c.pic = pic.New()
|
c.pic = pic.New()
|
||||||
c.fdc = fdc.New(cfg)
|
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
|
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()
|
ticks := c.cpu.RunInstruction()
|
||||||
c.cycles += uint64(ticks)
|
c.cycles += uint64(ticks)
|
||||||
//pc := c.cpu.GetState().PC
|
//pc := c.cpu.GetState().PC
|
||||||
//if pc >= 0xfea3 && pc <= 0xff25 {
|
//if pc >= 0xfea3 && pc <= 0xff25 {
|
||||||
// c.cpu.DebugOutput()
|
// c.cpu.DebugOutput()
|
||||||
//}
|
//}
|
||||||
return ticks
|
return ticks, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ComputerType) GetPixel(x uint16, y uint16) color.RGBA {
|
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")
|
log.Debug("Memory dump saved successfully")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ComputerType) CPUFrequency() uint32 {
|
||||||
|
return c.cpuFrequency
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ComputerType) SetCPUFrequency(frequency uint32) {
|
||||||
|
c.cpuFrequency = frequency
|
||||||
|
}
|
||||||
|
|||||||
@ -106,7 +106,7 @@ const RstTimerNo = 4
|
|||||||
// PicDd75a Port A (a0=0)
|
// PicDd75a Port A (a0=0)
|
||||||
const PicDd75a = 0x80
|
const PicDd75a = 0x80
|
||||||
|
|
||||||
// PIC_DD75B Port B (a0=1)
|
// PicDd75b Port B (a0=1)
|
||||||
const PicDd75b = 0x81
|
const PicDd75b = 0x81
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -116,7 +116,7 @@ const PicDd75b = 0x81
|
|||||||
// UartDd72rd Serial data
|
// UartDd72rd Serial data
|
||||||
const UartDd72rd = 0xA0
|
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
|
const UartDd72rr = 0xA1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/howeyc/crc16"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -38,18 +39,21 @@ const (
|
|||||||
|
|
||||||
// FDC Commands
|
// FDC Commands
|
||||||
const (
|
const (
|
||||||
CmdRestore byte = 0x0
|
CmdRestore = 0x0
|
||||||
CmdSeek byte = 0x1
|
CmdSeek = 0x1
|
||||||
CmdStep byte = 0x2
|
CmdStep = 0x2
|
||||||
CmdStepIn byte = 0x5
|
CmdStepIn = 0x5
|
||||||
CmdStepOut byte = 0x7
|
CmdStepOut = 0x7
|
||||||
CmdReadSector byte = 0x8
|
CmdReadSector = 0x8
|
||||||
CmdReadSectorMulti byte = 0x9
|
CmdReadSectorMulti = 0x9
|
||||||
CmdWriteSector byte = 0xa
|
CmdWriteSector = 0xa
|
||||||
CmdWriteTrack byte = 0xf
|
CmdReadAddress = 0xc
|
||||||
CmdNoCommand byte = 0xff
|
CmdWriteTrack = 0xf
|
||||||
|
CmdNoCommand = 0xff
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var interleave = []byte{1, 8, 6, 4, 2, 9, 7, 5, 3}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
StatusTR0 = 0x04 // TR0 - Head at track 0
|
StatusTR0 = 0x04 // TR0 - Head at track 0
|
||||||
StatusRNF = 0x10 // RNF - Record not found
|
StatusRNF = 0x10 // RNF - Record not found
|
||||||
@ -100,7 +104,10 @@ type FloppyDriveControllerInterface interface {
|
|||||||
Sector() byte
|
Sector() byte
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//var slicer = []uint16{1, 8, 6, 4, 2, 9, 7, 5, 3}
|
||||||
|
|
||||||
func getSectorNo(side byte, track byte, sector byte) uint16 {
|
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
|
return uint16(side)*SectorsPerSide + uint16(track)*SectorPerTrack + uint16(sector) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,6 +131,12 @@ func (f *FloppyDriveController) GetFloppy() byte {
|
|||||||
return floppy
|
return floppy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var crcTable *crc16.Table
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
crcTable = crc16.MakeTable(0xffff)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *FloppyDriveController) SetCmd(value byte) {
|
func (f *FloppyDriveController) SetCmd(value byte) {
|
||||||
f.lastCmd = value >> 4
|
f.lastCmd = value >> 4
|
||||||
switch f.lastCmd {
|
switch f.lastCmd {
|
||||||
@ -183,11 +196,21 @@ func (f *FloppyDriveController) SetCmd(value byte) {
|
|||||||
f.drq = 0
|
f.drq = 0
|
||||||
f.status = StatusRNF
|
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:
|
case CmdWriteTrack:
|
||||||
log.Tracef("CMD Write Track %x", f.trackNo)
|
log.Tracef("CMD Write Track %x", f.trackNo)
|
||||||
|
f.drq = 1
|
||||||
f.status = 0x00
|
f.status = 0x00
|
||||||
f.trackBuffer = []byte{}
|
f.trackBuffer = []byte{}
|
||||||
f.drq = 1
|
|
||||||
default:
|
default:
|
||||||
log.Errorf("Unknown CMD: %x VAL: %x", f.lastCmd, value&0xf)
|
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)
|
//log.Tracef("FDC Track: %d", value)
|
||||||
if value > TracksCount {
|
if value > TracksCount {
|
||||||
f.status |= 0x10 /// RNF
|
f.status |= 0x10 /// RNF
|
||||||
log.Error("Track not found!")
|
log.Errorf("Track %d not found!", value)
|
||||||
} else {
|
} else {
|
||||||
f.trackNo = value
|
f.trackNo = value
|
||||||
}
|
}
|
||||||
@ -282,7 +305,7 @@ func (f *FloppyDriveController) writeTrack() {
|
|||||||
|
|
||||||
func (f *FloppyDriveController) Data() byte {
|
func (f *FloppyDriveController) Data() byte {
|
||||||
switch f.lastCmd {
|
switch f.lastCmd {
|
||||||
case CmdReadSector, CmdReadSectorMulti:
|
case CmdReadSector, CmdReadSectorMulti, CmdReadAddress:
|
||||||
if len(f.trackBuffer) > 0 {
|
if len(f.trackBuffer) > 0 {
|
||||||
f.drq = 1
|
f.drq = 1
|
||||||
f.data = f.trackBuffer[0]
|
f.data = f.trackBuffer[0]
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
logFile: "okemu.log"
|
logFile: "okemu.log"
|
||||||
logLevel: "info"
|
logLevel: "info"
|
||||||
monitorFile: "rom/MON_r8_9c6c6546.bin"
|
monitorFile: "rom/MON_r8_9c6c6546.bin"
|
||||||
|
# cpmFile: "rom/CPM_r7_b89a7e16.bin"
|
||||||
cpmFile: "rom/CPM_r8_bc0695e4.bin"
|
cpmFile: "rom/CPM_r8_bc0695e4.bin"
|
||||||
floppyB: "floppy/floppyB.okd"
|
floppyB: "floppy/floppyB.okd"
|
||||||
floppyC: "floppy/floppyC.okd"
|
floppyC: "floppy/floppyC.okd"
|
||||||
|
port: 10001
|
||||||
|
|||||||
BIN
rom/CPM_r7.bin
BIN
rom/CPM_r7.bin
Binary file not shown.
@ -128,7 +128,7 @@ func carry(bitNo int, a uint16, b uint16, cy bool) bool {
|
|||||||
return (carry & (1 << bitNo)) != 0
|
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 {
|
func parity(val byte) bool {
|
||||||
ones := byte(0)
|
ones := byte(0)
|
||||||
for i := 0; i < 8; i++ {
|
for i := 0; i < 8; i++ {
|
||||||
|
|||||||
@ -9,7 +9,7 @@ func (z *Z80) jump(addr uint16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// jumps to next word in memory if condition is true
|
// 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()
|
addr := z.nextW()
|
||||||
if condition {
|
if condition {
|
||||||
z.jump(addr)
|
z.jump(addr)
|
||||||
@ -25,7 +25,7 @@ func (z *Z80) call(addr uint16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calls to next word in memory if condition is true
|
// 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()
|
addr := z.nextW()
|
||||||
if condition {
|
if condition {
|
||||||
z.call(addr)
|
z.call(addr)
|
||||||
@ -41,7 +41,7 @@ func (z *Z80) ret() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns from subroutine if condition is true
|
// returns from subroutine if condition is true
|
||||||
func (z *Z80) cond_ret(condition bool) {
|
func (z *Z80) condRet(condition bool) {
|
||||||
if condition {
|
if condition {
|
||||||
z.ret()
|
z.ret()
|
||||||
z.cycleCount += 6
|
z.cycleCount += 6
|
||||||
@ -57,7 +57,7 @@ func (z *Z80) jr(offset byte) {
|
|||||||
z.memPtr = z.pc
|
z.memPtr = z.pc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *Z80) cond_jr(condition bool) {
|
func (z *Z80) condJr(condition bool) {
|
||||||
b := z.nextB()
|
b := z.nextB()
|
||||||
if condition {
|
if condition {
|
||||||
z.jr(b)
|
z.jr(b)
|
||||||
@ -73,7 +73,7 @@ func bToByte(cond bool) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ADD Byte: adds two bytes together
|
// 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)
|
result := a + b + bToByte(cy)
|
||||||
z.sf = result&0x80 != 0
|
z.sf = result&0x80 != 0
|
||||||
z.zf = result == 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)
|
// SUBtract Byte: subtracts two bytes (with optional carry)
|
||||||
func (z *Z80) subb(a byte, b byte, cy bool) byte {
|
func (z *Z80) subB(a byte, b byte, cy bool) byte {
|
||||||
val := z.addb(a, ^b, !cy)
|
val := z.addB(a, ^b, !cy)
|
||||||
z.cf = !z.cf
|
z.cf = !z.cf
|
||||||
z.hf = !z.hf
|
z.hf = !z.hf
|
||||||
z.nf = true
|
z.nf = true
|
||||||
@ -95,9 +95,9 @@ func (z *Z80) subb(a byte, b byte, cy bool) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ADD Word: adds two words together
|
// ADD Word: adds two words together
|
||||||
func (z *Z80) addw(a uint16, b uint16, cy bool) uint16 {
|
func (z *Z80) addW(a uint16, b uint16, cy bool) uint16 {
|
||||||
lsb := z.addb(byte(a), byte(b), cy)
|
lsb := z.addB(byte(a), byte(b), cy)
|
||||||
msb := z.addb(byte(a>>8), byte(b>>8), z.cf)
|
msb := z.addB(byte(a>>8), byte(b>>8), z.cf)
|
||||||
result := (uint16(msb) << 8) | uint16(lsb)
|
result := (uint16(msb) << 8) | uint16(lsb)
|
||||||
z.zf = result == 0
|
z.zf = result == 0
|
||||||
z.memPtr = a + 1
|
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)
|
// SUBtract Word: subtracts two words (with optional carry)
|
||||||
func (z *Z80) subw(a uint16, b uint16, cy bool) uint16 {
|
func (z *Z80) subW(a uint16, b uint16, cy bool) uint16 {
|
||||||
lsb := z.subb(byte(a), byte(b), cy)
|
lsb := z.subB(byte(a), byte(b), cy)
|
||||||
msb := z.subb(byte(a>>8), byte(b>>8), z.cf)
|
msb := z.subB(byte(a>>8), byte(b>>8), z.cf)
|
||||||
result := (uint16(msb) << 8) | uint16(lsb)
|
result := (uint16(msb) << 8) | uint16(lsb)
|
||||||
z.zf = result == 0
|
z.zf = result == 0
|
||||||
z.memPtr = a + 1
|
z.memPtr = a + 1
|
||||||
@ -115,11 +115,11 @@ func (z *Z80) subw(a uint16, b uint16, cy bool) uint16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Adds a word to HL
|
// Adds a word to HL
|
||||||
func (z *Z80) addhl(val uint16) {
|
func (z *Z80) addHL(val uint16) {
|
||||||
sf := z.sf
|
sf := z.sf
|
||||||
zf := z.zf
|
zf := z.zf
|
||||||
pf := z.pf
|
pf := z.pf
|
||||||
result := z.addw(z.hl(), val, false)
|
result := z.addW(z.hl(), val, false)
|
||||||
z.setHL(result)
|
z.setHL(result)
|
||||||
z.sf = sf
|
z.sf = sf
|
||||||
z.zf = zf
|
z.zf = zf
|
||||||
@ -127,28 +127,28 @@ func (z *Z80) addhl(val uint16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// adds a word to IX or IY
|
// 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
|
sf := z.sf
|
||||||
zf := z.zf
|
zf := z.zf
|
||||||
pf := z.pf
|
pf := z.pf
|
||||||
result := z.addw(*reg, val, false)
|
result := z.addW(*reg, val, false)
|
||||||
*reg = result
|
*reg = result
|
||||||
z.sf = sf
|
z.sf = sf
|
||||||
z.zf = zf
|
z.zf = zf
|
||||||
z.pf = pf
|
z.pf = pf
|
||||||
}
|
}
|
||||||
|
|
||||||
// adchl adds a word (+ carry) to HL
|
// adcHL adds a word (+ carry) to HL
|
||||||
func (z *Z80) adchl(val uint16) {
|
func (z *Z80) adcHL(val uint16) {
|
||||||
result := z.addw(z.hl(), val, z.cf)
|
result := z.addW(z.hl(), val, z.cf)
|
||||||
z.sf = result&0x8000 != 0
|
z.sf = result&0x8000 != 0
|
||||||
z.zf = result == 0
|
z.zf = result == 0
|
||||||
z.setHL(result)
|
z.setHL(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// sbchl subtracts a word (+ carry) to HL
|
// sbcHL subtracts a word (+ carry) to HL
|
||||||
func (z *Z80) sbchl(val uint16) {
|
func (z *Z80) sbcHL(val uint16) {
|
||||||
result := z.subw(z.hl(), val, z.cf)
|
result := z.subW(z.hl(), val, z.cf)
|
||||||
z.sf = result&0x8000 != 0
|
z.sf = result&0x8000 != 0
|
||||||
z.zf = result == 0
|
z.zf = result == 0
|
||||||
z.setHL(result)
|
z.setHL(result)
|
||||||
@ -157,7 +157,7 @@ func (z *Z80) sbchl(val uint16) {
|
|||||||
// increments a byte value
|
// increments a byte value
|
||||||
func (z *Z80) inc(a byte) byte {
|
func (z *Z80) inc(a byte) byte {
|
||||||
cf := z.cf
|
cf := z.cf
|
||||||
result := z.addb(a, 1, false)
|
result := z.addB(a, 1, false)
|
||||||
z.cf = cf
|
z.cf = cf
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@ -165,14 +165,14 @@ func (z *Z80) inc(a byte) byte {
|
|||||||
// decrements a byte value
|
// decrements a byte value
|
||||||
func (z *Z80) dec(a byte) byte {
|
func (z *Z80) dec(a byte) byte {
|
||||||
cf := z.cf
|
cf := z.cf
|
||||||
result := z.subb(a, 1, false)
|
result := z.subB(a, 1, false)
|
||||||
z.cf = cf
|
z.cf = cf
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// executes a logic "and" between register A and a byte, then stores the
|
// executes a logic "and" between register A and a byte, then stores the
|
||||||
// result in register A
|
// result in register A
|
||||||
func (z *Z80) land(val byte) {
|
func (z *Z80) lAnd(val byte) {
|
||||||
result := z.a & val
|
result := z.a & val
|
||||||
z.sf = result&0x80 != 0
|
z.sf = result&0x80 != 0
|
||||||
z.zf = result == 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
|
// executes a logic "xor" between register A and a byte, then stores the
|
||||||
// result in register A
|
// result in register A
|
||||||
func (z *Z80) lxor(val byte) {
|
func (z *Z80) lXor(val byte) {
|
||||||
result := z.a ^ val
|
result := z.a ^ val
|
||||||
z.sf = result&0x80 != 0
|
z.sf = result&0x80 != 0
|
||||||
z.zf = result == 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
|
// executes a logic "or" between register A and a byte, then stores the
|
||||||
// result in register A
|
// result in register A
|
||||||
func (z *Z80) lor(val byte) {
|
func (z *Z80) lOr(val byte) {
|
||||||
result := z.a | val
|
result := z.a | val
|
||||||
|
|
||||||
z.sf = result&0x80 != 0
|
z.sf = result&0x80 != 0
|
||||||
@ -215,7 +215,7 @@ func (z *Z80) lor(val byte) {
|
|||||||
|
|
||||||
// compares a value with register A
|
// compares a value with register A
|
||||||
func (z *Z80) cp(val byte) {
|
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 only difference between cp and sub is that
|
||||||
// the xf/yf are taken from the value to be subtracted,
|
// the xf/yf are taken from the value to be subtracted,
|
||||||
@ -226,7 +226,7 @@ func (z *Z80) cp(val byte) {
|
|||||||
|
|
||||||
// 0xCB opcodes
|
// 0xCB opcodes
|
||||||
// rotate left with carry
|
// rotate left with carry
|
||||||
func (z *Z80) cb_rlc(val byte) byte {
|
func (z *Z80) cbRlc(val byte) byte {
|
||||||
old := val >> 7
|
old := val >> 7
|
||||||
val = (val << 1) | old
|
val = (val << 1) | old
|
||||||
z.sf = val&0x80 != 0
|
z.sf = val&0x80 != 0
|
||||||
@ -240,7 +240,7 @@ func (z *Z80) cb_rlc(val byte) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rotate right with carry
|
// rotate right with carry
|
||||||
func (z *Z80) cb_rrc(val byte) byte {
|
func (z *Z80) cbRrc(val byte) byte {
|
||||||
old := val & 1
|
old := val & 1
|
||||||
val = (val >> 1) | (old << 7)
|
val = (val >> 1) | (old << 7)
|
||||||
z.sf = val&0x80 != 0
|
z.sf = val&0x80 != 0
|
||||||
@ -254,7 +254,7 @@ func (z *Z80) cb_rrc(val byte) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rotate left (simple)
|
// rotate left (simple)
|
||||||
func (z *Z80) cb_rl(val byte) byte {
|
func (z *Z80) cbRl(val byte) byte {
|
||||||
cf := z.cf
|
cf := z.cf
|
||||||
z.cf = val>>7 != 0
|
z.cf = val>>7 != 0
|
||||||
val = (val << 1) | bToByte(cf)
|
val = (val << 1) | bToByte(cf)
|
||||||
@ -268,7 +268,7 @@ func (z *Z80) cb_rl(val byte) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// rotate right (simple)
|
// rotate right (simple)
|
||||||
func (z *Z80) cb_rr(val byte) byte {
|
func (z *Z80) cbRr(val byte) byte {
|
||||||
c := z.cf
|
c := z.cf
|
||||||
z.cf = (val & 1) != 0
|
z.cf = (val & 1) != 0
|
||||||
val = (val >> 1) | (bToByte(c) << 7)
|
val = (val >> 1) | (bToByte(c) << 7)
|
||||||
@ -282,7 +282,7 @@ func (z *Z80) cb_rr(val byte) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shift left preserving sign
|
// shift left preserving sign
|
||||||
func (z *Z80) cb_sla(val byte) byte {
|
func (z *Z80) cbSla(val byte) byte {
|
||||||
z.cf = (val >> 7) != 0
|
z.cf = (val >> 7) != 0
|
||||||
val <<= 1
|
val <<= 1
|
||||||
z.sf = val&0x80 != 0
|
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)
|
// 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
|
z.cf = val&0x80 != 0
|
||||||
val <<= 1
|
val <<= 1
|
||||||
val |= 1
|
val |= 1
|
||||||
@ -309,7 +309,7 @@ func (z *Z80) cb_sll(val byte) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shift right preserving sign
|
// shift right preserving sign
|
||||||
func (z *Z80) cb_sra(val byte) byte {
|
func (z *Z80) cbSra(val byte) byte {
|
||||||
z.cf = (val & 1) != 0
|
z.cf = (val & 1) != 0
|
||||||
val = (val >> 1) | (val & 0x80) // 0b10000000
|
val = (val >> 1) | (val & 0x80) // 0b10000000
|
||||||
z.sf = val&0x80 != 0
|
z.sf = val&0x80 != 0
|
||||||
@ -322,7 +322,7 @@ func (z *Z80) cb_sra(val byte) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// shift register right
|
// shift register right
|
||||||
func (z *Z80) cb_srl(val byte) byte {
|
func (z *Z80) cbSrl(val byte) byte {
|
||||||
z.cf = (val & 1) != 0
|
z.cf = (val & 1) != 0
|
||||||
val >>= 1
|
val >>= 1
|
||||||
z.sf = val&0x80 != 0
|
z.sf = val&0x80 != 0
|
||||||
@ -335,7 +335,7 @@ func (z *Z80) cb_srl(val byte) byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// tests bit "n" from a 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)
|
result := val & (1 << n)
|
||||||
z.sf = result&0x80 != 0
|
z.sf = result&0x80 != 0
|
||||||
z.zf = result == 0
|
z.zf = result == 0
|
||||||
@ -378,7 +378,7 @@ func (z *Z80) ldd() {
|
|||||||
|
|
||||||
func (z *Z80) cpi() {
|
func (z *Z80) cpi() {
|
||||||
cf := z.cf
|
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.setHL(z.hl() + 1)
|
||||||
z.setBC(z.bc() - 1)
|
z.setBC(z.bc() - 1)
|
||||||
|
|
||||||
@ -397,8 +397,6 @@ func (z *Z80) cpd() {
|
|||||||
z.memPtr -= 2
|
z.memPtr -= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
//var halfCarrySubTable = []bool{false, false, true, false, true, false, true, true}
|
|
||||||
|
|
||||||
func (z *Z80) inRC(r *byte) {
|
func (z *Z80) inRC(r *byte) {
|
||||||
*r = z.core.IORead(z.bc())
|
*r = z.core.IORead(z.bc())
|
||||||
z.zf = *r == 0
|
z.zf = *r == 0
|
||||||
@ -496,14 +494,6 @@ func (z *Z80) outd() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (z *Z80) daa() {
|
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)
|
correction := byte(0)
|
||||||
|
|
||||||
if (z.a&0x0F) > 0x09 || z.hf {
|
if (z.a&0x0F) > 0x09 || z.hf {
|
||||||
@ -607,7 +597,7 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
|
|
||||||
switch opcode {
|
switch opcode {
|
||||||
case 0x7F:
|
case 0x7F:
|
||||||
z.a = z.a // ld a,a
|
//z.a = z.a // ld a,a
|
||||||
case 0x78:
|
case 0x78:
|
||||||
z.a = z.b // ld a,b
|
z.a = z.b // ld a,b
|
||||||
case 0x79:
|
case 0x79:
|
||||||
@ -624,7 +614,7 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
case 0x47:
|
case 0x47:
|
||||||
z.b = z.a // ld b,a
|
z.b = z.a // ld b,a
|
||||||
case 0x40:
|
case 0x40:
|
||||||
z.b = z.b // ld b,b
|
//z.b = z.b // ld b,b
|
||||||
case 0x41:
|
case 0x41:
|
||||||
z.b = z.c // ld b,c
|
z.b = z.c // ld b,c
|
||||||
case 0x42:
|
case 0x42:
|
||||||
@ -641,7 +631,7 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
case 0x48:
|
case 0x48:
|
||||||
z.c = z.b // ld c,b
|
z.c = z.b // ld c,b
|
||||||
case 0x49:
|
case 0x49:
|
||||||
z.c = z.c // ld c,c
|
//z.c = z.c // ld c,c
|
||||||
case 0x4A:
|
case 0x4A:
|
||||||
z.c = z.d // ld c,d
|
z.c = z.d // ld c,d
|
||||||
case 0x4B:
|
case 0x4B:
|
||||||
@ -658,7 +648,7 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
case 0x51:
|
case 0x51:
|
||||||
z.d = z.c // ld d,c
|
z.d = z.c // ld d,c
|
||||||
case 0x52:
|
case 0x52:
|
||||||
z.d = z.d // ld d,d
|
//z.d = z.d // ld d,d
|
||||||
case 0x53:
|
case 0x53:
|
||||||
z.d = z.e // ld d,e
|
z.d = z.e // ld d,e
|
||||||
case 0x54:
|
case 0x54:
|
||||||
@ -675,7 +665,7 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
case 0x5A:
|
case 0x5A:
|
||||||
z.e = z.d // ld e,d
|
z.e = z.d // ld e,d
|
||||||
case 0x5B:
|
case 0x5B:
|
||||||
z.e = z.e // ld e,e
|
//z.e = z.e // ld e,e
|
||||||
case 0x5C:
|
case 0x5C:
|
||||||
z.e = z.h // ld e,h
|
z.e = z.h // ld e,h
|
||||||
case 0x5D:
|
case 0x5D:
|
||||||
@ -692,7 +682,7 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
case 0x63:
|
case 0x63:
|
||||||
z.h = z.e // ld h,e
|
z.h = z.e // ld h,e
|
||||||
case 0x64:
|
case 0x64:
|
||||||
z.h = z.h // ld h,h
|
//z.h = z.h // ld h,h
|
||||||
case 0x65:
|
case 0x65:
|
||||||
z.h = z.l // ld h,l
|
z.h = z.l // ld h,l
|
||||||
|
|
||||||
@ -709,7 +699,7 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
case 0x6C:
|
case 0x6C:
|
||||||
z.l = z.h // ld l,h
|
z.l = z.h // ld l,h
|
||||||
case 0x6D:
|
case 0x6D:
|
||||||
z.l = z.l // ld l,l
|
//z.l = z.l // ld l,l
|
||||||
|
|
||||||
case 0x7E:
|
case 0x7E:
|
||||||
z.a = z.rb(z.hl()) // ld a,(hl)
|
z.a = z.rb(z.hl()) // ld a,(hl)
|
||||||
@ -817,89 +807,89 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
z.setHL(val)
|
z.setHL(val)
|
||||||
z.memPtr = val
|
z.memPtr = val
|
||||||
case 0x87:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
case 0x09:
|
||||||
z.addhl(z.bc()) // add hl,bc
|
z.addHL(z.bc()) // add hl,bc
|
||||||
case 0x19:
|
case 0x19:
|
||||||
z.addhl(z.de()) // add hl,de
|
z.addHL(z.de()) // add hl,de
|
||||||
case 0x29:
|
case 0x29:
|
||||||
z.addhl(z.hl()) // add hl,hl
|
z.addHL(z.hl()) // add hl,hl
|
||||||
case 0x39:
|
case 0x39:
|
||||||
z.addhl(z.sp) // add hl,sp
|
z.addHL(z.sp) // add hl,sp
|
||||||
|
|
||||||
case 0xF3:
|
case 0xF3:
|
||||||
z.iff1 = false
|
z.iff1 = false
|
||||||
@ -1013,61 +1003,61 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
z.hf = false
|
z.hf = false
|
||||||
z.updateXY(z.a)
|
z.updateXY(z.a)
|
||||||
case 0xA7:
|
case 0xA7:
|
||||||
z.land(z.a) // and a
|
z.lAnd(z.a) // and a
|
||||||
case 0xA0:
|
case 0xA0:
|
||||||
z.land(z.b) // and b
|
z.lAnd(z.b) // and b
|
||||||
case 0xA1:
|
case 0xA1:
|
||||||
z.land(z.c) // and c
|
z.lAnd(z.c) // and c
|
||||||
case 0xA2:
|
case 0xA2:
|
||||||
z.land(z.d) // and d
|
z.lAnd(z.d) // and d
|
||||||
case 0xA3:
|
case 0xA3:
|
||||||
z.land(z.e) // and e
|
z.lAnd(z.e) // and e
|
||||||
case 0xA4:
|
case 0xA4:
|
||||||
z.land(z.h) // and h
|
z.lAnd(z.h) // and h
|
||||||
case 0xA5:
|
case 0xA5:
|
||||||
z.land(z.l) // and l
|
z.lAnd(z.l) // and l
|
||||||
case 0xA6:
|
case 0xA6:
|
||||||
z.land(z.rb(z.hl())) // and (hl)
|
z.lAnd(z.rb(z.hl())) // and (hl)
|
||||||
case 0xE6:
|
case 0xE6:
|
||||||
z.land(z.nextB()) // and *
|
z.lAnd(z.nextB()) // and *
|
||||||
|
|
||||||
case 0xAF:
|
case 0xAF:
|
||||||
z.lxor(z.a) // xor a
|
z.lXor(z.a) // xor a
|
||||||
case 0xA8:
|
case 0xA8:
|
||||||
z.lxor(z.b) // xor b
|
z.lXor(z.b) // xor b
|
||||||
case 0xA9:
|
case 0xA9:
|
||||||
z.lxor(z.c) // xor c
|
z.lXor(z.c) // xor c
|
||||||
case 0xAA:
|
case 0xAA:
|
||||||
z.lxor(z.d) // xor d
|
z.lXor(z.d) // xor d
|
||||||
case 0xAB:
|
case 0xAB:
|
||||||
z.lxor(z.e) // xor e
|
z.lXor(z.e) // xor e
|
||||||
case 0xAC:
|
case 0xAC:
|
||||||
z.lxor(z.h) // xor h
|
z.lXor(z.h) // xor h
|
||||||
case 0xAD:
|
case 0xAD:
|
||||||
z.lxor(z.l) // xor l
|
z.lXor(z.l) // xor l
|
||||||
case 0xAE:
|
case 0xAE:
|
||||||
z.lxor(z.rb(z.hl())) // xor (hl)
|
z.lXor(z.rb(z.hl())) // xor (hl)
|
||||||
case 0xEE:
|
case 0xEE:
|
||||||
z.lxor(z.nextB()) // xor *
|
z.lXor(z.nextB()) // xor *
|
||||||
|
|
||||||
case 0xB7:
|
case 0xB7:
|
||||||
z.lor(z.a) // or a
|
z.lOr(z.a) // or a
|
||||||
case 0xB0:
|
case 0xB0:
|
||||||
z.lor(z.b) // or b
|
z.lOr(z.b) // or b
|
||||||
case 0xB1:
|
case 0xB1:
|
||||||
z.lor(z.c) // or c
|
z.lOr(z.c) // or c
|
||||||
case 0xB2:
|
case 0xB2:
|
||||||
z.lor(z.d) // or d
|
z.lOr(z.d) // or d
|
||||||
case 0xB3:
|
case 0xB3:
|
||||||
z.lor(z.e) // or e
|
z.lOr(z.e) // or e
|
||||||
case 0xB4:
|
case 0xB4:
|
||||||
z.lor(z.h) // or h
|
z.lOr(z.h) // or h
|
||||||
case 0xB5:
|
case 0xB5:
|
||||||
z.lor(z.l) // or l
|
z.lOr(z.l) // or l
|
||||||
case 0xB6:
|
case 0xB6:
|
||||||
z.lor(z.rb(z.hl())) // or (hl)
|
z.lOr(z.rb(z.hl())) // or (hl)
|
||||||
case 0xF6:
|
case 0xF6:
|
||||||
z.lor(z.nextB()) // or *
|
z.lOr(z.nextB()) // or *
|
||||||
|
|
||||||
case 0xBF:
|
case 0xBF:
|
||||||
z.cp(z.a) // cp a
|
z.cp(z.a) // cp a
|
||||||
@ -1091,36 +1081,36 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
case 0xC3:
|
case 0xC3:
|
||||||
z.jump(z.nextW()) // jm **
|
z.jump(z.nextW()) // jm **
|
||||||
case 0xC2:
|
case 0xC2:
|
||||||
z.cond_jump(!z.zf) // jp nz, **
|
z.condJump(!z.zf) // jp nz, **
|
||||||
case 0xCA:
|
case 0xCA:
|
||||||
z.cond_jump(z.zf) // jp z, **
|
z.condJump(z.zf) // jp z, **
|
||||||
case 0xD2:
|
case 0xD2:
|
||||||
z.cond_jump(!z.cf) // jp nc, **
|
z.condJump(!z.cf) // jp nc, **
|
||||||
case 0xDA:
|
case 0xDA:
|
||||||
z.cond_jump(z.cf) // jp c, **
|
z.condJump(z.cf) // jp c, **
|
||||||
case 0xE2:
|
case 0xE2:
|
||||||
z.cond_jump(!z.pf) // jp po, **
|
z.condJump(!z.pf) // jp po, **
|
||||||
case 0xEA:
|
case 0xEA:
|
||||||
z.cond_jump(z.pf) // jp pe, **
|
z.condJump(z.pf) // jp pe, **
|
||||||
case 0xF2:
|
case 0xF2:
|
||||||
z.cond_jump(!z.sf) // jp p, **
|
z.condJump(!z.sf) // jp p, **
|
||||||
case 0xFA:
|
case 0xFA:
|
||||||
z.cond_jump(z.sf) // jp m, **
|
z.condJump(z.sf) // jp m, **
|
||||||
|
|
||||||
case 0x10:
|
case 0x10:
|
||||||
z.b--
|
z.b--
|
||||||
z.cond_jr(z.b != 0) // djnz *
|
z.condJr(z.b != 0) // djnz *
|
||||||
case 0x18:
|
case 0x18:
|
||||||
z.pc += uint16(z.nextB()) // jr *
|
z.pc += uint16(z.nextB()) // jr *
|
||||||
z.memPtr = z.pc
|
z.memPtr = z.pc
|
||||||
case 0x20:
|
case 0x20:
|
||||||
z.cond_jr(!z.zf) // jr nz, *
|
z.condJr(!z.zf) // jr nz, *
|
||||||
case 0x28:
|
case 0x28:
|
||||||
z.cond_jr(z.zf) // jr z, *
|
z.condJr(z.zf) // jr z, *
|
||||||
case 0x30:
|
case 0x30:
|
||||||
z.cond_jr(!z.cf) // jr nc, *
|
z.condJr(!z.cf) // jr nc, *
|
||||||
case 0x38:
|
case 0x38:
|
||||||
z.cond_jr(z.cf) // jr c, *
|
z.condJr(z.cf) // jr c, *
|
||||||
|
|
||||||
case 0xE9:
|
case 0xE9:
|
||||||
z.pc = z.hl() // jp (hl)
|
z.pc = z.hl() // jp (hl)
|
||||||
@ -1128,40 +1118,40 @@ func (z *Z80) execOpcode(opcode byte) {
|
|||||||
z.call(z.nextW()) // call
|
z.call(z.nextW()) // call
|
||||||
|
|
||||||
case 0xC4:
|
case 0xC4:
|
||||||
z.cond_call(!z.zf) // cnz
|
z.condCall(!z.zf) // cnz
|
||||||
case 0xCC:
|
case 0xCC:
|
||||||
z.cond_call(z.zf) // cz
|
z.condCall(z.zf) // cz
|
||||||
case 0xD4:
|
case 0xD4:
|
||||||
z.cond_call(!z.cf) // cnc
|
z.condCall(!z.cf) // cnc
|
||||||
case 0xDC:
|
case 0xDC:
|
||||||
z.cond_call(z.cf) // cc
|
z.condCall(z.cf) // cc
|
||||||
case 0xE4:
|
case 0xE4:
|
||||||
z.cond_call(!z.pf) // cpo
|
z.condCall(!z.pf) // cpo
|
||||||
case 0xEC:
|
case 0xEC:
|
||||||
z.cond_call(z.pf) // cpe
|
z.condCall(z.pf) // cpe
|
||||||
case 0xF4:
|
case 0xF4:
|
||||||
z.cond_call(!z.sf) // cp
|
z.condCall(!z.sf) // cp
|
||||||
case 0xFC:
|
case 0xFC:
|
||||||
z.cond_call(z.sf) // cm
|
z.condCall(z.sf) // cm
|
||||||
|
|
||||||
case 0xC9:
|
case 0xC9:
|
||||||
z.ret() // ret
|
z.ret() // ret
|
||||||
case 0xC0:
|
case 0xC0:
|
||||||
z.cond_ret(!z.zf) // ret nz
|
z.condRet(!z.zf) // ret nz
|
||||||
case 0xC8:
|
case 0xC8:
|
||||||
z.cond_ret(z.zf) // ret z
|
z.condRet(z.zf) // ret z
|
||||||
case 0xD0:
|
case 0xD0:
|
||||||
z.cond_ret(!z.cf) // ret nc
|
z.condRet(!z.cf) // ret nc
|
||||||
case 0xD8:
|
case 0xD8:
|
||||||
z.cond_ret(z.cf) // ret c
|
z.condRet(z.cf) // ret c
|
||||||
case 0xE0:
|
case 0xE0:
|
||||||
z.cond_ret(!z.pf) // ret po
|
z.condRet(!z.pf) // ret po
|
||||||
case 0xE8:
|
case 0xE8:
|
||||||
z.cond_ret(z.pf) // ret pe
|
z.condRet(z.pf) // ret pe
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
z.cond_ret(!z.sf) // ret p
|
z.condRet(!z.sf) // ret p
|
||||||
case 0xF8:
|
case 0xF8:
|
||||||
z.cond_ret(z.sf) // ret m
|
z.condRet(z.sf) // ret m
|
||||||
|
|
||||||
case 0xC7:
|
case 0xC7:
|
||||||
z.call(0x00) // rst 0
|
z.call(0x00) // rst 0
|
||||||
|
|||||||
@ -40,26 +40,26 @@ func (z *Z80) execOpcodeCB(opcode byte) {
|
|||||||
// rot[y] r[z]
|
// rot[y] r[z]
|
||||||
switch y_ {
|
switch y_ {
|
||||||
case 0:
|
case 0:
|
||||||
*reg = z.cb_rlc(*reg)
|
*reg = z.cbRlc(*reg)
|
||||||
case 1:
|
case 1:
|
||||||
*reg = z.cb_rrc(*reg)
|
*reg = z.cbRrc(*reg)
|
||||||
case 2:
|
case 2:
|
||||||
*reg = z.cb_rl(*reg)
|
*reg = z.cbRl(*reg)
|
||||||
case 3:
|
case 3:
|
||||||
*reg = z.cb_rr(*reg)
|
*reg = z.cbRr(*reg)
|
||||||
case 4:
|
case 4:
|
||||||
*reg = z.cb_sla(*reg)
|
*reg = z.cbSla(*reg)
|
||||||
case 5:
|
case 5:
|
||||||
*reg = z.cb_sra(*reg)
|
*reg = z.cbSra(*reg)
|
||||||
case 6:
|
case 6:
|
||||||
*reg = z.cb_sll(*reg)
|
*reg = z.cbSll(*reg)
|
||||||
case 7:
|
case 7:
|
||||||
*reg = z.cb_srl(*reg)
|
*reg = z.cbSrl(*reg)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
// BIT y, r[z]
|
// BIT y, r[z]
|
||||||
z.cb_bit(*reg, y_)
|
z.cbBit(*reg, y_)
|
||||||
|
|
||||||
// in bit (hl), x/y flags are handled differently:
|
// in bit (hl), x/y flags are handled differently:
|
||||||
if z_ == 6 {
|
if z_ == 6 {
|
||||||
@ -82,8 +82,8 @@ func (z *Z80) execOpcodeCB(opcode byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// exec_opcode_dcb executes a displaced CB opcode (DDCB or FDCB)
|
// execOpcodeDcb executes a displaced CB opcode (DDCB or FDCB)
|
||||||
func (z *Z80) exec_opcode_dcb(opcode byte, addr uint16) {
|
func (z *Z80) execOpcodeDcb(opcode byte, addr uint16) {
|
||||||
val := z.rb(addr)
|
val := z.rb(addr)
|
||||||
result := byte(0)
|
result := byte(0)
|
||||||
|
|
||||||
@ -97,26 +97,26 @@ func (z *Z80) exec_opcode_dcb(opcode byte, addr uint16) {
|
|||||||
// rot[y] (iz+d)
|
// rot[y] (iz+d)
|
||||||
switch y_ {
|
switch y_ {
|
||||||
case 0:
|
case 0:
|
||||||
result = z.cb_rlc(val)
|
result = z.cbRlc(val)
|
||||||
case 1:
|
case 1:
|
||||||
result = z.cb_rrc(val)
|
result = z.cbRrc(val)
|
||||||
case 2:
|
case 2:
|
||||||
result = z.cb_rl(val)
|
result = z.cbRl(val)
|
||||||
case 3:
|
case 3:
|
||||||
result = z.cb_rr(val)
|
result = z.cbRr(val)
|
||||||
case 4:
|
case 4:
|
||||||
result = z.cb_sla(val)
|
result = z.cbSla(val)
|
||||||
case 5:
|
case 5:
|
||||||
result = z.cb_sra(val)
|
result = z.cbSra(val)
|
||||||
case 6:
|
case 6:
|
||||||
result = z.cb_sll(val)
|
result = z.cbSll(val)
|
||||||
case 7:
|
case 7:
|
||||||
result = z.cb_srl(val)
|
result = z.cbSrl(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
// bit y,(iz+d)
|
// bit y,(iz+d)
|
||||||
result = z.cb_bit(val, y_)
|
result = z.cbBit(val, y_)
|
||||||
z.updateXY(byte(addr >> 8))
|
z.updateXY(byte(addr >> 8))
|
||||||
case 2:
|
case 2:
|
||||||
result = val & ^(1 << y_) // res y, (iz+d)
|
result = val & ^(1 << y_) // res y, (iz+d)
|
||||||
|
|||||||
@ -15,58 +15,58 @@ func (z *Z80) execOpcodeDDFD(opcode byte, iz *uint16) {
|
|||||||
z.pc = *iz
|
z.pc = *iz
|
||||||
//z.jump(*iz)
|
//z.jump(*iz)
|
||||||
case 0x09:
|
case 0x09:
|
||||||
z.addiz(iz, z.bc()) // add iz,bc
|
z.addIZ(iz, z.bc()) // add iz,bc
|
||||||
case 0x19:
|
case 0x19:
|
||||||
z.addiz(iz, z.de()) // add iz,de
|
z.addIZ(iz, z.de()) // add iz,de
|
||||||
case 0x29:
|
case 0x29:
|
||||||
z.addiz(iz, *iz) // add iz,iz
|
z.addIZ(iz, *iz) // add iz,iz
|
||||||
case 0x39:
|
case 0x39:
|
||||||
z.addiz(iz, z.sp) // add iz,sp
|
z.addIZ(iz, z.sp) // add iz,sp
|
||||||
|
|
||||||
case 0x84:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
case 0xA4:
|
||||||
z.land(byte(*iz >> 8)) // and izh
|
z.lAnd(byte(*iz >> 8)) // and izh
|
||||||
case 0xA5:
|
case 0xA5:
|
||||||
z.land(byte(*iz)) // and izl
|
z.lAnd(byte(*iz)) // and izl
|
||||||
|
|
||||||
case 0xAE:
|
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:
|
case 0xAC:
|
||||||
z.lxor(byte(*iz >> 8)) // xor izh
|
z.lXor(byte(*iz >> 8)) // xor izh
|
||||||
case 0xAD:
|
case 0xAD:
|
||||||
z.lxor(byte(*iz)) // xor izl
|
z.lXor(byte(*iz)) // xor izl
|
||||||
case 0xB6:
|
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:
|
case 0xB4:
|
||||||
z.lor(byte(*iz >> 8)) // or izh
|
z.lOr(byte(*iz >> 8)) // or izh
|
||||||
case 0xB5:
|
case 0xB5:
|
||||||
z.lor(byte(*iz)) // or izl
|
z.lOr(byte(*iz)) // or izl
|
||||||
case 0xBE:
|
case 0xBE:
|
||||||
z.cp(z.rb(z.displace(*iz, z.nextB()))) // cp (iz+*)
|
z.cp(z.rb(z.displace(*iz, z.nextB()))) // cp (iz+*)
|
||||||
case 0xBC:
|
case 0xBC:
|
||||||
@ -196,7 +196,7 @@ func (z *Z80) execOpcodeDDFD(opcode byte, iz *uint16) {
|
|||||||
case 0xCB:
|
case 0xCB:
|
||||||
addr := z.displace(*iz, z.nextB())
|
addr := z.displace(*iz, z.nextB())
|
||||||
op := z.nextB()
|
op := z.nextB()
|
||||||
z.exec_opcode_dcb(op, addr)
|
z.execOpcodeDcb(op, addr)
|
||||||
default:
|
default:
|
||||||
// any other FD/DD opcode behaves as a non-prefixed opcode:
|
// any other FD/DD opcode behaves as a non-prefixed opcode:
|
||||||
z.execOpcode(opcode)
|
z.execOpcode(opcode)
|
||||||
|
|||||||
@ -185,21 +185,21 @@ func (z *Z80) execOpcodeED(opcode byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 0x42:
|
case 0x42:
|
||||||
z.sbchl(z.bc()) // sbc hl,bc
|
z.sbcHL(z.bc()) // sbc hl,bc
|
||||||
case 0x52:
|
case 0x52:
|
||||||
z.sbchl(z.de()) // sbc hl,de
|
z.sbcHL(z.de()) // sbc hl,de
|
||||||
case 0x62:
|
case 0x62:
|
||||||
z.sbchl(z.hl()) // sbc hl,hl
|
z.sbcHL(z.hl()) // sbc hl,hl
|
||||||
case 0x72:
|
case 0x72:
|
||||||
z.sbchl(z.sp) // sbc hl,sp
|
z.sbcHL(z.sp) // sbc hl,sp
|
||||||
case 0x4A:
|
case 0x4A:
|
||||||
z.adchl(z.bc()) // adc hl,bc
|
z.adcHL(z.bc()) // adc hl,bc
|
||||||
case 0x5A:
|
case 0x5A:
|
||||||
z.adchl(z.de()) // adc hl,de
|
z.adcHL(z.de()) // adc hl,de
|
||||||
case 0x6A:
|
case 0x6A:
|
||||||
z.adchl(z.hl()) // adc hl,hl
|
z.adcHL(z.hl()) // adc hl,hl
|
||||||
case 0x7A:
|
case 0x7A:
|
||||||
z.adchl(z.sp) // adc hl,sp
|
z.adcHL(z.sp) // adc hl,sp
|
||||||
case 0x43:
|
case 0x43:
|
||||||
// ld (**), bc
|
// ld (**), bc
|
||||||
addr := z.nextW()
|
addr := z.nextW()
|
||||||
@ -241,7 +241,7 @@ func (z *Z80) execOpcodeED(opcode byte) {
|
|||||||
z.sp = z.rw(addr)
|
z.sp = z.rw(addr)
|
||||||
z.memPtr = addr + 1
|
z.memPtr = addr + 1
|
||||||
case 0x44, 0x54, 0x64, 0x74, 0x4C, 0x5C, 0x6C, 0x7C:
|
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:
|
case 0x46, 0x4e, 0x66, 0x6e:
|
||||||
z.interruptMode = 0 // im 0
|
z.interruptMode = 0 // im 0
|
||||||
case 0x56, 0x76:
|
case 0x56, 0x76:
|
||||||
|
|||||||
40
z80/cpu.go
40
z80/cpu.go
@ -103,6 +103,46 @@ func (f *FlagsType) GetFlags() byte {
|
|||||||
return flags
|
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 {
|
func GetFlags(f byte) FlagsType {
|
||||||
return FlagsType{
|
return FlagsType{
|
||||||
S: f&0x80 != 0,
|
S: f&0x80 != 0,
|
||||||
|
|||||||
@ -68,10 +68,6 @@ type Z80TestIn struct {
|
|||||||
memorySetup []MemorySetup
|
memorySetup []MemorySetup
|
||||||
}
|
}
|
||||||
|
|
||||||
type Z80TestExpected struct {
|
|
||||||
expect Expect
|
|
||||||
}
|
|
||||||
|
|
||||||
type Expect struct {
|
type Expect struct {
|
||||||
events []Event
|
events []Event
|
||||||
registers Registers
|
registers Registers
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user