private static string PString(ushort address) { var len = Memory.ReadByte(address, 0); StringBuilder sb = new(len + 2); sb.Append('\''); for (short i = 1; i <= len; i++) { sb.Append(Memory.ReadByte(address, i)); } sb.Append('\''); return(sb.ToString()); }
/// <summary> /// The DisasmP function is used to disassemble a p-code opcode from /// memory, into the given buffer. /// </summary> /// <param name="buffer">The buffer to print the opcode into.</param> /// <param name="segNo">The segment number the code is within</param> /// <param name="ipcBase">The procedure base address (enter_ic).</param> /// <param name="ipc"> /// The instruction counter (address within segment) of the /// instruction to disassemble. /// </param> /// <param name="jTab"> /// The jump table (procedure attributes) of the procedure being /// executed, or disassembled. /// </param> /// <param name="sp">Stack pointer (?)</param> /// <returns></returns> public static ushort DisasmP(StringBuilder buffer, ushort segNo, ushort ipcBase, ushort ipc, ushort jTab, ushort sp) { var opCode = Memory.ReadByte(ipcBase, (short)ipc++); var s = PTrace.instructions[opCode]; int val; foreach (var ch in s) { switch (ch) { case 'A': // CXP Arguments { int seg = Memory.ReadByte(ipcBase, (short)ipc++); int proc = Memory.ReadByte(ipcBase, (short)ipc++); buffer.AppendFormat("{0},{1} ", seg, proc); buffer.Append(PTrace.ProcName(seg, proc, sp)); } break; case 'B': val = Memory.ReadByte(ipcBase, (short)ipc++); if ((val & 0x80) != 0) { val = ((val & 0x7f) << 8) + Memory.ReadByte(ipcBase, (short)ipc++); } buffer.Append(val); break; case 'C': val = Memory.ReadByte(ipcBase, (short)ipc++); buffer.AppendFormat("{0} ", val); buffer.Append(PTrace.ProcName(segNo, val, sp)); break; case 'D': case 'U': val = Memory.ReadByte(ipcBase, (short)ipc++); buffer.Append(val); break; case 'P': if (sp != 0) { buffer.Append(PTrace.PString(PTrace.ReadStack(sp, 0))); } break; case 'S': val = Memory.ReadByte(ipcBase, (short)ipc++); if ((val & 0x80) != 0) { val = -(0x100 - val); } buffer.Append(val); break; case 'T': val = Memory.ReadByte(ipcBase, (short)ipc++); switch (val) { case 2: buffer.Append("real"); break; case 4: buffer.Append("string"); break; case 6: buffer.Append("boolean"); break; case 8: buffer.Append("set"); break; case 10: val = Memory.ReadByte(ipcBase, (short)ipc++); if ((val & 0x80) != 0) { val = ((val & 0x7f) << 8) + Memory.ReadByte(ipcBase, (short)ipc++); } buffer.AppendFormat("byte array, {0} bytes", val); break; case 12: val = Memory.ReadByte(ipcBase, (short)ipc++); if ((val & 0x80) != 0) { val = ((val & 0x7f) << 8) + Memory.ReadByte(ipcBase, (short)ipc++); } buffer.AppendFormat("{0} words", val); break; default: buffer.Append(val); break; } break; case 'W': val = Memory.ReadByte(ipcBase, (short)ipc++); val |= Memory.ReadByte(ipcBase, (short)ipc++) << 8; buffer.Append(val); break; case 'R': // case arguments { ipc = (ushort)(ipc + 1 & ~1); int min = Memory.ReadByte(ipcBase, (short)ipc++); min |= Memory.ReadByte(ipcBase, (short)ipc++) << 8; int max = Memory.ReadByte(ipcBase, (short)ipc++); max |= Memory.ReadByte(ipcBase, (short)ipc++) << 8; ipc++; int defaultVal = Memory.ReadByte(ipcBase, (short)ipc++); if ((defaultVal & 0x80) != 0) // less than zero? { defaultVal = -(0x100 - defaultVal); defaultVal = -defaultVal; defaultVal = Memory.ReadByte(jTab, -2) + (Memory.ReadByte(jTab, -1) << 8) + 2 - (Memory.ReadByte(jTab, (short)-defaultVal) + (Memory.ReadByte(jTab, (short)(-defaultVal + 1)) << 8) + defaultVal); } else { defaultVal = ipc + defaultVal; } buffer.AppendFormat("{0},{1},{2} ", min, max, defaultVal); while (min < max + 1) { val = Memory.ReadByte(ipcBase, (short)ipc++); val |= Memory.ReadByte(ipcBase, (short)ipc++) << 8; buffer.AppendFormat(",{0}", ipc - 2 - val); min++; } } break; case 'Q': val = Memory.ReadByte(ipcBase, (short)ipc++); switch (val) { case 1: buffer.Append("new"); break; case 2: buffer.Append("Moveleft"); break; case 3: buffer.Append("Moveright"); break; case 4: buffer.Append("exit"); break; case 5: buffer.Append("unitread"); break; case 6: buffer.Append("unitwrite"); break; case 7: buffer.Append("idsearch"); break; case 8: buffer.Append("treesearch"); break; case 9: buffer.Append("time"); break; case 10: buffer.Append("fillchar"); break; case 11: buffer.AppendFormat("scan"); break; case 12: buffer.Append("unitstat"); break; case 21: buffer.Append("load_segment"); break; case 22: buffer.Append("unload_segment"); break; case 32: buffer.Append("mark"); break; case 33: buffer.Append("release"); break; case 34: buffer.Append("ioresult"); break; case 35: buffer.Append("unitbusy"); break; case 37: buffer.Append("unitwait"); break; case 38: buffer.Append("unitclear"); break; case 39: buffer.Append("halt"); break; case 40: buffer.Append("memavail"); break; default: buffer.Append(val); break; } break; case 'J': val = Memory.ReadByte(ipcBase, (short)ipc++); if ((val & 0x80) != 0) /* less than zero? */ { val = -(0x100 - val); val = -val; val = Memory.ReadByte(jTab, -2) + (Memory.ReadByte(jTab, -1) << 8) + 2 - (Memory.ReadByte(jTab, (short)-val) + (Memory.ReadByte(jTab, (short)(-val + 1)) << 8) + val); } else { val = ipc + val; } buffer.Append(val); break; case 'V': break; case 'X': val = Memory.ReadByte(ipcBase, (short)ipc++); buffer.Append(val); ipc = (ushort)(ipc + 1 & ~1); while (val-- != 0) { var w = Memory.ReadByte(ipcBase, (short)ipc) + (Memory.ReadByte(ipcBase, (short)(ipc + 1)) << 8); ipc += 2; buffer.AppendFormat(",{0:X4}", w); } break; case 'Y': val = Memory.ReadByte(ipcBase, (short)ipc++); buffer.AppendFormat("{0},'", val); while (val-- != 0) { buffer.Append((char)Memory.ReadByte(ipcBase, (short)ipc++)); } buffer.Append('\''); break; case 'Z': val = Memory.ReadByte(ipcBase, (short)ipc++); buffer.Append(val); ipc = (ushort)(ipc + 1 & ~1); while (val-- != 0) { buffer.AppendFormat(",{0:X2}", Memory.ReadByte(ipcBase, (short)ipc)); ipc++; } break; default: buffer.Append(ch); break; } } return(ipc); }
private static ushort ReadStack(ushort stackPointer, int topOfStackOffset) => (ushort)( Memory.ReadByte(stackPointer, (short)(2 * topOfStackOffset)) + (Memory.ReadByte(stackPointer, (short)(2 * topOfStackOffset + 1)) << 8));
public static void Write(ushort unit, ushort address, short addressOffset, ushort len, ushort blockNo) { var offset = blockNo * 512u; var track = blockNo / 8; var sector = (blockNo & 7) * 2; Debug.Assert(unit < DiskIO.MaxUnits); var u = DiskIO.unitTable[unit]; if (u == null || u.Fd == null && u.Data == null) { PSystem.IOError(9); return; } if (u.ReadOnly) { PSystem.IOError(16); return; } if (offset + len > u.Size) { PSystem.IOError(64); return; } while (len != 0) { var size = 256; var sec = sector; if (len < size) { size = len; } //if (u.Translate != null) // sec = u.Translate[sector]; int i; if (u.Data != null) { for (i = 0; i < size; i++) { u.Data[(track * 16 + sec) * 256 + i] = Memory.ReadByte(address, (short)(addressOffset + i)); } } else if (u.Fd != null) { var buf = new byte[256]; for (i = 0; i < size; i++) { buf[i] = Memory.ReadByte(address, (short)(addressOffset + i)); } try { u.Fd.Seek((track * 16 + sec) * 256, SeekOrigin.Begin); u.Fd.Write(buf, 0, size); } catch { PSystem.IOError(64); return; } } addressOffset += (short)size; len -= (ushort)size; sector++; if (sector < 16) { continue; } track++; sector = 0; } PSystem.IOError(0); }