/** * Returns the registers. */ public static void GetRegisters() { // Get registers var cspect = Main.CSpect; var regs = cspect.GetRegs(); InitData(29 + 8); // Return registers SetWord(regs.PC); SetWord(regs.SP); SetWord(regs.AF); SetWord(regs.BC); SetWord(regs.DE); SetWord(regs.HL); SetWord(regs.IX); SetWord(regs.IY); SetWord(regs._AF); SetWord(regs._BC); SetWord(regs._DE); SetWord(regs._HL); SetByte(regs.R); SetByte(regs.I); SetByte(regs.IM); SetByte(0); // reserved // Return the slots/banks SetByte(8); for (int i = 0; i < 8; i++) { byte bank = cspect.GetNextRegister((byte)(0x50 + i)); SetByte(bank); } // Return CSpectSocket.SendResponse(Data); //Log.WriteLine("GetRegs: I={0}, R={1}", regs.I, regs.R); }
/** * Returns some sprite patterns. */ public static void GetSpritePatterns() { var cspect = Main.CSpect; var prevRegs = cspect.GetRegs(); // Start of memory ushort index = CSpectSocket.GetDataByte(); // Get size ushort count = CSpectSocket.GetDataByte(); if (Log.Enabled) { Log.WriteLine("Sprite pattern index={0}, count={1}", index, count); } // Respond int address = index * 256; int size = count * 256; InitData(size); byte[] values = cspect.PeekSprite(address, size); foreach (byte value in values) { SetByte(value); } CSpectSocket.SendResponse(Data); var afterRegs = cspect.GetRegs(); //Log.WriteLine("prevPC={0}/(0x{0:X4}), afterPC={1}/(0x{1:X4})", prevRegs.PC, afterRegs.PC); if (prevRegs.PC != afterRegs.PC) { Log.WriteLine("prevPC={0}/(0x{0:X4}), afterPC={1}/(0x{1:X4})", prevRegs.PC, afterRegs.PC); } }
/** * Writes the state. */ public static void WriteState() { // Not implemented: No CSpect interface yet. // Respond CSpectSocket.SendResponse(); }
/** * Associate a slot with a bank. */ public static void SetSlot() { // Get slot byte slot = CSpectSocket.GetDataByte(); // Get bank byte bank = CSpectSocket.GetDataByte(); // Special handling for 0xFE if (bank == 0xFE) { bank = 0xFF; } // Set slot var cspect = Main.CSpect; cspect.SetNextRegister((byte)(0x50 + slot), bank); //Console.WriteLine("slot {0} = {1}", slot, bank); // No error InitData(1); SetByte(0); // Respond CSpectSocket.SendResponse(Data); }
/** * Reads a memory area. */ public static void ReadMem() { // Skip reserved CSpectSocket.GetDataByte(); // Start of memory ushort address = CSpectSocket.GetDataWord(); // Get size ushort size = CSpectSocket.GetDataWord(); if (Log.Enabled) { Log.WriteLine("ReadMem at address={0}, size={1}", address, size); } // Respond InitData(size); var cspect = Main.CSpect; byte[] values = cspect.Peek(address, size); foreach (byte value in values) { SetByte(value); } CSpectSocket.SendResponse(Data); }
/** * Initialization. Called by CSpect. * Returns a list with the ports to be registered. */ public List <sIO> Init(iCSpect _CSpect) { string version = typeof(Main).Assembly.GetName().Version.ToString(); ProgramName = typeof(Main).Assembly.GetName().Name; ProgramName += " v" + version; string dzrpVersion = Commands.GetDzrpVersion(); Log.WriteLine("v{0} started. DZRP v{1}.", version, dzrpVersion); CSpect = _CSpect; // Read settings file (port) Settings = Settings.Load(); Log.Enabled = Settings.LogEnabled; //Server.Listen(Settings.Port); CSpectSocket.Port = Settings.Port; CSpectSocket.StartListening(); // No ports List <sIO> ports = new List <sIO>(); return(ports); }
/** * Removes a breakpoint. */ public static void RemoveBreakpoint() { // Get breakpoint ID ushort bpId = CSpectSocket.GetDataWord(); // Remove breakpoint DeleteBreakpoint(bpId); // Respond CSpectSocket.SendResponse(); }
/** * Pauses execution. */ public static void Pause() { // Pause if (Log.Enabled) { Log.WriteLine("Pause: Stop debugger."); } ManualBreak = true; Main.CSpect.Debugger(Plugin.eDebugCommand.Enter); // Respond CSpectSocket.SendResponse(); }
/** * Adds a breakpoint. */ public static void AddBreakpoint() { // Get breakpoint address int bpAddr = CSpectSocket.GetLongAddress(); // Set CSpect breakpoint ushort bpId = SetBreakpoint(bpAddr); // Respond InitData(2); SetWord(bpId); CSpectSocket.SendResponse(Data); }
/** * Sets the border color. */ public static void SetBorder() { // Get border color byte color = CSpectSocket.GetDataByte(); if (Log.Enabled) { Log.WriteLine("Bordercolor={0}", color); } // Set border Main.CSpect.OutPort(0xFE, color); // Respond CSpectSocket.SendResponse(); }
/** * Returns the configuration. */ public static void CmdInit() { // Clear breakpoints ClearAllBreakAndWatchpoints(); // Return values int length = 1 + 3 + Main.ProgramName.Length + 1; InitData(length); SetByte(0); // No error SetBuffer(DZRP_VERSION); SetByte((byte)DzrpMachineType.ZXNEXT); // machine type = ZXNext SetString(Main.ProgramName); CSpectSocket.SendResponse(Data); }
/** * Removes a watchpoint area. */ public static void RemoveWatchpoint() { // Get data ushort start = CSpectSocket.GetDataWord(); ushort size = CSpectSocket.GetDataWord(); ushort end = (ushort)(start + size); var cspect = Main.CSpect; // Remove both read and write for (ushort i = start; i != end; i++) { cspect.Debugger(Plugin.eDebugCommand.ClearReadBreakpoint, i); cspect.Debugger(Plugin.eDebugCommand.ClearWriteBreakpoint, i); } // Respond CSpectSocket.SendResponse(); }
/** * Returns the first or second sprites palette. */ public static void GetSpritesPalette() { // Which palette int paletteIndex = CSpectSocket.GetDataByte() & 0x01;; // Prepare data InitData(2 * 256); // Store current values var cspect = Main.CSpect; byte eUlaCtrlReg = cspect.GetNextRegister(0x43); byte indexReg = cspect.GetNextRegister(0x40); byte colorReg = cspect.GetNextRegister(0x41); // Bit 7: 0=first (8bit color), 1=second (9th bit color) byte machineReg = cspect.GetNextRegister(0x03); // Select sprites byte selSprites = (byte)((eUlaCtrlReg & 0x0F) | 0b0010_0000 | (paletteIndex << 6)); cspect.SetNextRegister(0x43, selSprites); // Resets also 0x44 // Read palette for (int i = 0; i < 256; i++) { // Set index cspect.SetNextRegister(0x40, (byte)i); // Read color byte colorMain = cspect.GetNextRegister(0x41); SetByte(colorMain); byte color9th = cspect.GetNextRegister(0x44); SetByte(color9th); //Log.WriteLine("Palette index={0}: 8bit={1}, 9th bit={2}", i, colorMain, color9th); } // Restore values cspect.SetNextRegister(0x43, eUlaCtrlReg); cspect.SetNextRegister(0x40, indexReg); if ((machineReg & 0x80) != 0) { // Bit 7 set, increase 0x44 index. // Write it to increase the index cspect.SetNextRegister(0x44, colorReg); } // Respond CSpectSocket.SendResponse(Data); }
/** * Writes a memory area. */ public static void WriteMem() { // Skip reserved CSpectSocket.GetDataByte(); // Start of memory ushort address = CSpectSocket.GetDataWord(); // Get size var data = CSpectSocket.GetRemainingData(); ushort size = (ushort)data.Count; // Write memory var cspect = Main.CSpect; byte[] values = data.ToArray(); cspect.Poke(address, values); // Respond CSpectSocket.SendResponse(); }
/** * Returns the value of one TBBlue register. */ public static void GetTbblueReg() { // Get register byte reg = CSpectSocket.GetDataByte(); // Get register value var cspect = Main.CSpect; cspect.GetNextRegister(reg); // Write register value InitData(1); byte value = cspect.GetNextRegister(reg); SetByte(value); // Log if (Log.Enabled) { Log.WriteLine("GetNextRegister({0:X2}): {1}", reg, value); } // Respond CSpectSocket.SendResponse(Data); }
/** * Writes one memory bank. */ public static void WriteBank() { // Get size int bankSize = CSpectSocket.GetRemainingDataCount() - 1; if (bankSize != 0x2000) { // Only supported is 0x2000 string errorString = "Bank size incorrect!"; int length = 1 + errorString.Length + 1; InitData(length); SetByte(1); // Error SetString(errorString); CSpectSocket.SendResponse(Data); } // Get bank number byte bankNumber = CSpectSocket.GetDataByte(); // Calculate physical address // Example: phys. address $1f021 = ($1f021&$1fff) for offset and ($1f021>>13) for bank. Int32 physAddress = bankNumber * bankSize; // Write memory var cspect = Main.CSpect; if (Log.Enabled) { Log.WriteLine("WriteBank: bank={0}", bankNumber); } for (int i = bankSize; i > 0; i--) { byte value = CSpectSocket.GetDataByte(); cspect.PokePhysical(physAddress++, new byte[] { value }); } // Respond InitData(2); SetByte(0); // No error SetByte(0); CSpectSocket.SendResponse(Data); }
/** * Sends the pause notification. * bpAddress is a long address. */ protected static void SendPauseNotification(BreakReason reason, int bpAddress, string reasonString) { //Log.WriteLine("SendPauseNotification: reason={0}, bpAddress=0x{1:X6}, reasonString='{2}'", reason, bpAddress, reasonString); // Convert string to byte array System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); byte[] reasonBytes = enc.GetBytes(reasonString + "\0"); int stringLen = reasonBytes.Length; // Prepare data int length = 6 + stringLen; byte[] dataWoString = { // Length (byte)(length & 0xFF), (byte)((length >> 8) & 0xFF), (byte)((length >> 16) & 0xFF), (byte)(length >> 24), // SeqNo = 0 0, // PAUSE (byte)DZRP_NTF.NTF_PAUSE, // Reason (byte)reason, // Breakpoint address (long address) (byte)(bpAddress & 0xFF), (byte)((bpAddress >> 8) & 0xFF), (byte)((bpAddress >> 16) & 0xFF), }; int firstLen = dataWoString.Length; byte[] data = new byte[firstLen + stringLen]; dataWoString.CopyTo(data, 0); reasonBytes.CopyTo(data, firstLen); // Respond CSpectSocket.Send(data); }
/** * Returns the attributes of some sprites. */ public static void GetSprites() { // Get index int index = CSpectSocket.GetDataByte(); // Get count int count = CSpectSocket.GetDataByte(); // Get sprite data InitData(5 * count); var cspect = Main.CSpect; for (int i = 0; i < count; i++) { var sprite = cspect.GetSprite(index + i); SetByte(sprite.x); SetByte(sprite.y); SetByte(sprite.paloff_mirror_flip_rotate_xmsb); SetByte(sprite.visible_name); SetByte(sprite.H_N6_0_XX_YY_Y8); } // Respond CSpectSocket.SendResponse(Data); }
/** * Returns the sprite clipping window. */ public static void GetSpritesClipWindow() { // Get index (for restoration) var cspect = Main.CSpect; int prevIndex = cspect.GetNextRegister(0x1C); prevIndex = (prevIndex >> 2) & 0x03; // Get clip window byte[] clip = new byte[5]; for (int i = 0; i < 4; i++) { byte value = cspect.GetNextRegister(0x19); // xl clip[(prevIndex + i) % 4] = value; cspect.SetNextRegister(0x19, value); // Increment index } clip[4] = cspect.GetNextRegister(0x15); // sprite control register if (Log.Enabled) { Log.WriteLine("Clip: xl={0}, xr={1}, yt={2}, yb={3}, control={4:X2}", clip[0], clip[1], clip[2], clip[3], clip[4]); } // Respond CSpectSocket.SendResponse(clip); }
/** * Adds a watchpoint area. */ public static void AddWatchpoint() { // Get data ushort start = CSpectSocket.GetDataWord(); ushort size = CSpectSocket.GetDataWord(); ushort end = (ushort)(start + size); byte access = CSpectSocket.GetDataByte(); if (Log.Enabled) { Log.WriteLine("AddWatchpoint: address={0:X4}, size={1}", start, size); } // condition is not used var cspect = Main.CSpect; // Read if ((access & 0x01) != 0) { for (ushort i = start; i != end; i++) { cspect.Debugger(Plugin.eDebugCommand.SetReadBreakpoint, i); //Log.WriteLine("Read Watchpoint {0}", i); } } // Write if ((access & 0x02) != 0) { for (ushort i = start; i != end; i++) { cspect.Debugger(Plugin.eDebugCommand.SetWriteBreakpoint, i); //Log.WriteLine("Write Watchpoint {0}", i); } } // Respond CSpectSocket.SendResponse(); }
/** * Continues execution. */ public static void Continue() { var cspect = Main.CSpect; // Breakpoint 1 bool bp1Enable = (CSpectSocket.GetDataByte() != 0); ushort bp1Address = CSpectSocket.GetDataWord(); // Breakpoint 2 bool bp2Enable = (CSpectSocket.GetDataByte() != 0); ushort bp2Address = CSpectSocket.GetDataWord(); // Alternate command? //AlternateCommand alternateCmd = (AlternateCommand)CSpectSocket.GetDataByte(); AlternateCommand alternateCmd = AlternateCommand.CONTINUE; switch (alternateCmd) { /* Note: Cspect cannot support this because of the strange step-over behavior: * CSpect step-over does not step-over a conditional jump backwards, e.g. "JP cc, -5" * case AlternateCommand.STEP_OVER: // Step over * ushort address = CSpectSocket.GetDataWord(); * ushort endAddress = CSpectSocket.GetDataWord(); * // Respond * CSpectSocket.SendResponse(); * //ManualBreak = false; * //CpuRunning = true; Need to be locked * //cspect.Debugger(Plugin.eDebugCommand.StepOver); * break; * * case AlternateCommand.STEP_OUT: // Step out * // Respond * CSpectSocket.SendResponse(); * break; */ case AlternateCommand.CONTINUE: // Continue default: // Set temporary breakpoints TmpBreakpoint1 = -1; if (bp1Enable) { TmpBreakpoint1 = bp1Address; var result = cspect.Debugger(Plugin.eDebugCommand.SetBreakpoint, TmpBreakpoint1); if (Log.Enabled) { Log.WriteLine(" Set tmp breakpoint 1 at 0x{0:X4}, result={1}", TmpBreakpoint1, result); } } TmpBreakpoint2 = -1; if (bp2Enable) { TmpBreakpoint2 = bp2Address; var result = cspect.Debugger(Plugin.eDebugCommand.SetBreakpoint, TmpBreakpoint2); if (Log.Enabled) { Log.WriteLine(" Set tmp breakpoint 2 at 0x{0:X4}, result={1}", TmpBreakpoint2, result); } } // Log if (Log.Enabled) { var regs = cspect.GetRegs(); Log.WriteLine("Continue: Run debugger. pc=0x{0:X4}/{0}, bp1=0x{1:X4}/{1}, bp2=0x{2:X4}/{2}", regs.PC, TmpBreakpoint1, TmpBreakpoint2); } // Respond CSpectSocket.SendResponse(); // Run ManualBreak = false; StartCpu(true); break; } }
/** * Sets one double or single register. */ public static void SetRegister() { // Get register number byte regNumber = CSpectSocket.GetDataByte(); // Get new value ushort value = CSpectSocket.GetDataWord(); ushort valueByte = (ushort)(value & 0xFF); // Get registers var cspect = Main.CSpect; var regs = cspect.GetRegs(); // Set a specific register switch (regNumber) { case 0: regs.PC = value; break; case 1: regs.SP = value; break; case 2: regs.AF = value; break; case 3: regs.BC = value; break; case 4: regs.DE = value; break; case 5: regs.HL = value; break; case 6: regs.IX = value; break; case 7: regs.IY = value; break; case 8: regs._AF = value; break; case 9: regs._BC = value; break; case 10: regs._DE = value; break; case 11: regs._HL = value; break; case 13: regs.IM = (byte)value; break; case 14: regs.AF = (ushort)((regs.AF & 0xFF00) + valueByte); break; // F case 15: regs.AF = (ushort)((regs.AF & 0xFF) + 256 * valueByte); break; // A case 16: regs.BC = (ushort)((regs.BC & 0xFF00) + valueByte); break; // C case 17: regs.BC = (ushort)((regs.BC & 0xFF) + 256 * valueByte); break; // B case 18: regs.DE = (ushort)((regs.DE & 0xFF00) + valueByte); break; // E case 19: regs.DE = (ushort)((regs.DE & 0xFF) + 256 * valueByte); break; // D case 20: regs.HL = (ushort)((regs.HL & 0xFF00) + valueByte); break; // L case 21: regs.HL = (ushort)((regs.HL & 0xFF) + 256 * valueByte); break; // H case 22: regs.IX = (ushort)((regs.IX & 0xFF00) + valueByte); break; // IXL case 23: regs.IX = (ushort)((regs.IX & 0xFF) + 256 * valueByte); break; // IXH case 24: regs.IY = (ushort)((regs.IY & 0xFF00) + valueByte); break; // IYL case 25: regs.IY = (ushort)((regs.IY & 0xFF) + 256 * valueByte); break; // IYH case 26: regs._AF = (ushort)((regs._AF & 0xFF00) + valueByte); break; // F' case 27: regs._AF = (ushort)((regs._AF & 0xFF) + 256 * valueByte); break; // A' case 28: regs._BC = (ushort)((regs._BC & 0xFF00) + valueByte); break; // C' case 29: regs._BC = (ushort)((regs._BC & 0xFF) + 256 * valueByte); break; // B' case 30: regs._DE = (ushort)((regs._DE & 0xFF00) + valueByte); break; // E' case 31: regs._DE = (ushort)((regs._DE & 0xFF) + 256 * valueByte); break; // D' case 32: regs._HL = (ushort)((regs._HL & 0xFF00) + valueByte); break; // L' case 33: regs._HL = (ushort)((regs._HL & 0xFF) + 256 * valueByte); break; // H' case 34: regs.R = (byte)value; break; case 35: regs.I = (byte)value; break; default: // Error Log.WriteLine("Error: Wrong register number {0} to set.", regNumber); break; } // Set register(s) cspect.SetRegs(regs); //Log.WriteLine("SetRegs: I={0}, R={1}", regs.I, regs.R); // Respond CSpectSocket.SendResponse(); }
/** * Just sends a response. */ public static void CmdClose() { CSpectSocket.SendResponse(); }