Example #1
0
        /// <summary>
        /// Gets the specified BASIC code line
        /// </summary>
        /// <param name="progStart">Code line address in the memory</param>
        /// <param name="lineVm">BASIC line view model</param>
        /// <returns></returns>
        public ushort GetBasicLine(ushort progStart, out BasicLineViewModel lineVm)
        {
            lineVm = new BasicLineViewModel
            {
                LineNo = Memory[progStart++] * 0x100 + Memory[progStart++],
                Length = Memory[progStart++] + Memory[progStart++] * 0x100
            };
            var lineEnd = progStart + lineVm.Length;

            if (lineEnd > Memory.Length - 1)
            {
                lineEnd = Memory.Length - 1;
            }

            var spaceBeforeToken = false;
            var sb = new StringBuilder(256);

            while (progStart < lineEnd)
            {
                var nextSymbol = Memory[progStart++];
                if (nextSymbol >= 0xA5)
                {
                    // --- This is a token
                    if (spaceBeforeToken)
                    {
                        sb.Append(" ");
                    }
                    var tokenCode = nextSymbol - 0xA5;
                    var token     = _tokens[tokenCode];
                    sb.Append(token);
                    if (tokenCode > 2 && char.IsLetter(token[token.Length - 1]))
                    {
                        sb.Append(" ");
                        spaceBeforeToken = false;
                    }
                    continue;
                }

                // --- Whatever we print, the next token needs a space
                spaceBeforeToken = true;

                if (nextSymbol >= 0x20 && nextSymbol <= 0x7F)
                {
                    // --- Printable character
                    sb.Append((char)nextSymbol);
                    continue;
                }

                if (nextSymbol == 0x0D)
                {
                    continue;
                }

                if (nextSymbol == 0x0E)
                {
                    // --- Skip the binary form of a floating point number
                    progStart += 5;
                    continue;
                }

                // --- Non-printable character, let's display it with an escape sequence
                sb.Append($"°{nextSymbol:X2}°");
            }

            lineVm.Text = sb.ToString();
            return(progStart);
        }
        /// <summary>
        /// Gets the specified BASIC code line
        /// </summary>
        /// <param name="progStart">Code line address in the memory</param>
        /// <param name="lineVm">BASIC line view model</param>
        /// <returns></returns>
        public ushort GetBasicLine(ushort progStart, out BasicLineViewModel lineVm)
        {
            lineVm = new BasicLineViewModel
            {
                LineNo = Memory[progStart++] * 0x100 + Memory[progStart++],
                Length = Memory[progStart++] + Memory[progStart++] * 0x100
            };
            var lineEnd = progStart + lineVm.Length;

            if (lineEnd > Memory.Length - 1)
            {
                lineEnd = Memory.Length - 1;
            }

            var spaceBeforeToken = false;
            var withinQuotes     = false;
            var sb = new StringBuilder(256);

            while (progStart < lineEnd)
            {
                var nextSymbol = Memory[progStart++];
                if (nextSymbol >= 0xA5)
                {
                    // --- This is a token
                    if (spaceBeforeToken)
                    {
                        sb.Append(" ");
                    }
                    var tokenCode = nextSymbol - 0xA5;
                    var token     = _tokens[tokenCode];
                    sb.Append(token);
                    if (tokenCode > 2 && char.IsLetter(token[token.Length - 1]))
                    {
                        sb.Append(" ");
                        spaceBeforeToken = false;
                    }
                    continue;
                }

                // --- Whatever we print, the next token needs a space
                spaceBeforeToken = true;

                // --- Skip ENTER
                if (nextSymbol == 0x0D)
                {
                    continue;
                }

                // --- Skip binary number characters
                if (nextSymbol == 0x0E)
                {
                    // --- Skip the binary form of a floating point number
                    progStart += 5;
                    continue;
                }

                if (nextSymbol == 0x22)
                {
                    // --- Printable character
                    sb.Append((char)nextSymbol);
                    withinQuotes = !withinQuotes;
                    continue;
                }

                if (MimicZxBasic && !withinQuotes && nextSymbol < 0x20)
                {
                    // --- Skip all remaining control characters in ZX BASIC mode
                    continue;
                }

                if (nextSymbol >= 0x20 && nextSymbol <= 0x7F)
                {
                    // --- Printable character
                    if (withinQuotes)
                    {
                        if (nextSymbol == (int)'\\')
                        {
                            sb.Append(MimicZxBasic ? "\\\\" : "\\");
                            continue;
                        }
                        else if (nextSymbol == 0x60)
                        {
                            sb.Append(MimicZxBasic ? "\\`" : "Ł");
                            continue;
                        }
                        else if (nextSymbol == 0x7f)
                        {
                            sb.Append(MimicZxBasic ? "\\*" : "©");
                            continue;
                        }
                    }
                    else
                    {
                        if (nextSymbol == (int)'\\')
                        {
                            sb.Append("\\");
                            continue;
                        }
                        else if (nextSymbol == 0x60)
                        {
                            sb.Append("Ł");
                            continue;
                        }
                        else if (nextSymbol == 0x7f)
                        {
                            sb.Append("©");
                            continue;
                        }
                    }
                    sb.Append((char)nextSymbol);
                    continue;
                }

                // --- Non-printable character, let's display it with an escape sequence
                if (MimicZxBasic && withinQuotes)
                {
                    if (nextSymbol >= 0x90 && nextSymbol <= 0xA4)
                    {
                        // --- Handle UDG chars in ZX BASIC
                        sb.Append($"\\{(char)(nextSymbol - 0x90 + 'A')}");
                        continue;
                    }

                    var lookahead = progStart < Memory.Length ? Memory[progStart] : -1;
                    switch (nextSymbol)
                    {
                    case 0x10:
                        if (lookahead >= 0)
                        {
                            sb.Append("\\{i" + lookahead + "}");
                            progStart++;
                        }
                        break;

                    case 0x11:
                        if (lookahead >= 0)
                        {
                            sb.Append("\\{p" + lookahead + "}");
                            progStart++;
                        }
                        break;

                    case 0x12:
                        if (lookahead >= 0)
                        {
                            sb.Append("\\{f" + lookahead + "}");
                            progStart++;
                        }
                        break;

                    case 0x13:
                        if (lookahead >= 0)
                        {
                            sb.Append("\\{b" + lookahead + "}");
                            progStart++;
                        }
                        break;

                    case 0x80:
                        sb.Append("\\  ");
                        break;

                    case 0x81:
                        sb.Append("\\ '");
                        break;

                    case 0x82:
                        sb.Append("\\' ");
                        break;

                    case 0x83:
                        sb.Append("\\''");
                        break;

                    case 0x84:
                        sb.Append("\\ .");
                        break;

                    case 0x85:
                        sb.Append("\\ :");
                        break;

                    case 0x86:
                        sb.Append("\\'.");
                        break;

                    case 0x87:
                        sb.Append("\\':");
                        break;

                    case 0x88:
                        sb.Append("\\. ");
                        break;

                    case 0x89:
                        sb.Append("\\.'");
                        break;

                    case 0x8a:
                        sb.Append("\\: ");
                        break;

                    case 0x8b:
                        sb.Append("\\:'");
                        break;

                    case 0x8c:
                        sb.Append("\\..");
                        break;

                    case 0x8d:
                        sb.Append("\\.:");
                        break;

                    case 0x8e:
                        sb.Append("\\:.");
                        break;

                    case 0x8f:
                        sb.Append("\\::");
                        break;

                    default:
                        sb.Append($"#{nextSymbol & 0xff}");
                        break;
                    }
                }
                else
                {
                    sb.Append($"°{nextSymbol:X2}°");
                }
            }

            lineVm.Text = sb.ToString();
            return(progStart);
        }