From 23ba6d457ede4536d54fcf3696c6b656261261db Mon Sep 17 00:00:00 2001 From: Adrian Conlon Date: Sun, 28 Apr 2019 21:00:30 +0100 Subject: [PATCH] Add emulation of Grant Searle MC6809 SBC as a test container (untested!) Signed-off-by: Adrian Conlon --- EightBit.sln | 14 + MC6809/MC6809.Test/App.config | 6 + MC6809/MC6809.Test/Board.cs | 239 + MC6809/MC6809.Test/Configuration.cs | 15 + MC6809/MC6809.Test/MC6809.Test.csproj | 72 + MC6809/MC6809.Test/Program.cs | 23 + MC6809/MC6809.Test/Properties/AssemblyInfo.cs | 36 + MC6809/MC6809.Test/TestHarness.cs | 56 + MC6809/MC6809.Test/roms/coco2h/bas12.rom | Bin 0 -> 8192 bytes MC6809/MC6809.Test/roms/coco2h/disk11.rom | Bin 0 -> 8192 bytes MC6809/MC6809.Test/roms/coco2h/extbas11.rom | Bin 0 -> 8192 bytes MC6809/MC6809.Test/roms/searle/ExBasROM.LST | 5406 +++++++++++++++++ MC6809/MC6809.Test/roms/searle/ExBasROM.asm | 5398 ++++++++++++++++ MC6809/MC6809.Test/roms/searle/ExBasROM.hex | 513 ++ MC6809/MC6809.Test/roms/searle/ExBasRom.zip | Bin 0 -> 180465 bytes 15 files changed, 11778 insertions(+) create mode 100644 MC6809/MC6809.Test/App.config create mode 100644 MC6809/MC6809.Test/Board.cs create mode 100644 MC6809/MC6809.Test/Configuration.cs create mode 100644 MC6809/MC6809.Test/MC6809.Test.csproj create mode 100644 MC6809/MC6809.Test/Program.cs create mode 100644 MC6809/MC6809.Test/Properties/AssemblyInfo.cs create mode 100644 MC6809/MC6809.Test/TestHarness.cs create mode 100644 MC6809/MC6809.Test/roms/coco2h/bas12.rom create mode 100644 MC6809/MC6809.Test/roms/coco2h/disk11.rom create mode 100644 MC6809/MC6809.Test/roms/coco2h/extbas11.rom create mode 100644 MC6809/MC6809.Test/roms/searle/ExBasROM.LST create mode 100644 MC6809/MC6809.Test/roms/searle/ExBasROM.asm create mode 100644 MC6809/MC6809.Test/roms/searle/ExBasROM.hex create mode 100644 MC6809/MC6809.Test/roms/searle/ExBasRom.zip diff --git a/EightBit.sln b/EightBit.sln index 107f639..dad215d 100644 --- a/EightBit.sln +++ b/EightBit.sln @@ -25,6 +25,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MC6809.UnitTest", "MC6809\M EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MC6850", "MC6850\MC6850.csproj", "{A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MC6809.Test", "MC6809\MC6809.Test\MC6809.Test.csproj", "{5ADB4727-2F5F-4A41-979B-6734501E34BC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -167,6 +169,18 @@ Global {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Release|x64.Build.0 = Release|Any CPU {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Release|x86.ActiveCfg = Release|Any CPU {A9760EFD-79F2-4EC3-8647-D2A1587E3E7E}.Release|x86.Build.0 = Release|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Debug|x64.ActiveCfg = Debug|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Debug|x64.Build.0 = Debug|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Debug|x86.ActiveCfg = Debug|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Debug|x86.Build.0 = Debug|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|Any CPU.Build.0 = Release|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|x64.ActiveCfg = Release|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|x64.Build.0 = Release|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|x86.ActiveCfg = Release|Any CPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MC6809/MC6809.Test/App.config b/MC6809/MC6809.Test/App.config new file mode 100644 index 0000000..56efbc7 --- /dev/null +++ b/MC6809/MC6809.Test/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/MC6809/MC6809.Test/Board.cs b/MC6809/MC6809.Test/Board.cs new file mode 100644 index 0000000..d67c350 --- /dev/null +++ b/MC6809/MC6809.Test/Board.cs @@ -0,0 +1,239 @@ +namespace EightBit +{ + using System; + + public sealed class Board : Bus + { + private readonly Configuration configuration; + private readonly Ram ram = new Ram(0x8000); // 0000 - 7FFF, 32K RAM + private readonly UnusedMemory unused2000 = new UnusedMemory(0x2000, 0xff); // 8000 - 9FFF, 8K unused + private readonly Ram io = new Ram(0x2000); // A000 - BFFF, 8K serial interface, minimally decoded + private readonly Rom rom = new Rom(0x4000); // C000 - FFFF, 16K ROM + + private readonly Disassembler disassembler; + + private ulong totalCycleCount = 0UL; + private long frameCycleCount = 0L; + + // The m_disassembleAt and m_ignoreDisassembly are used to skip pin events + private ushort disassembleAt = 0x0000; + private bool ignoreDisassembly = false; + + public Board(Configuration configuration) + { + this.configuration = configuration; + this.CPU = new MC6809(this); + this.disassembler = new Disassembler(this, this.CPU); + } + + public MC6809 CPU { get; } + public MC6850 ACIA { get; } = new MC6850(); + + public override void RaisePOWER() + { + base.RaisePOWER(); + + // Get the CPU ready for action + this.CPU.RaisePOWER(); + this.CPU.LowerRESET(); + this.CPU.RaiseINT(); + this.CPU.RaiseNMI(); + this.CPU.RaiseFIRQ(); + this.CPU.RaiseHALT(); + + // Get the ACIA ready for action + this.Address.Word = 0b1010000000000000; + this.ACIA.DATA = (byte)(MC6850.ControlRegister.CR0 | MC6850.ControlRegister.CR1); // Master reset + this.UpdateAciaPinsWrite(); + this.ACIA.CTS.Lower(); + this.ACIA.RaisePOWER(); + this.AccessAcia(); + } + + public override void LowerPOWER() + { + this.ACIA.LowerPOWER(); + this.CPU.LowerPOWER(); + base.LowerPOWER(); + } + + public override void Initialize() + { + // Load our BASIC interpreter + var directory = this.configuration.RomDirectory + "\\"; + this.LoadHexFile(directory + "ExBasROM.hex"); + + // Catch a byte being transmitted + this.ACIA.Transmitting += this.ACIA_Transmitting; + + // Marshal data from memory -> ACIA + this.WrittenByte += this.Board_WrittenByte; + + // Marshal data from ACIA -> memory + this.ReadingByte += this.Board_ReadingByte; + + // Keyboard wiring, check for input once per frame + this.CPU.ExecutedInstruction += this.CPU_ExecutedInstruction; + + if (this.configuration.DebugMode) + { + // MC6809 disassembly wiring + this.CPU.ExecutingInstruction += this.CPU_ExecutingInstruction; + this.CPU.ExecutedInstruction += this.CPU_ExecutedInstruction_Debug; + } + + if (this.configuration.TerminatesEarly) + { + // Early termination condition for CPU timing code + this.CPU.ExecutedInstruction += this.CPU_ExecutedInstruction_Termination; + } + } + + private void CPU_ExecutedInstruction_Termination(object sender, EventArgs e) + { + this.totalCycleCount += (ulong)this.CPU.Cycles; + if (this.totalCycleCount > Configuration.TerminationCycles) + { + this.LowerPOWER(); + } + } + + private void CPU_ExecutedInstruction_Debug(object sender, EventArgs e) + { + if (this.ignoreDisassembly) + { + var disassembled = $"{this.disassembler.Trace(this.disassembleAt)}\t{this.ACIA.DumpStatus()}"; + System.Console.Out.WriteLine(disassembled); + } + } + + private void CPU_ExecutingInstruction(object sender, EventArgs e) + { + this.disassembleAt = this.CPU.PC.Word; + this.ignoreDisassembly = this.disassembler.Ignore; + } + + private void CPU_ExecutedInstruction(object sender, EventArgs e) + { + this.frameCycleCount -= this.CPU.Cycles; + if (this.frameCycleCount < 0) + { + if (System.Console.KeyAvailable) + { + var key = System.Console.ReadKey(); + this.ACIA.RDR = System.Convert.ToByte(key.KeyChar); + this.ACIA.MarkReceiveStarting(); + } + + this.frameCycleCount = (long)Configuration.FrameCycleInterval; + } + } + + private void Board_ReadingByte(object sender, EventArgs e) + { + this.UpdateAciaPinsRead(); + if (this.AccessAcia()) + { + this.Poke(this.ACIA.DATA); + } + } + + private void Board_WrittenByte(object sender, EventArgs e) + { + this.UpdateAciaPinsWrite(); + if (this.ACIA.Selected) + { + this.ACIA.DATA = this.Data; + this.AccessAcia(); + } + } + + private void ACIA_Transmitting(object sender, EventArgs e) + { + System.Console.Out.Write(Convert.ToChar(this.ACIA.TDR)); + this.ACIA.MarkTransmitComplete(); + } + + public override MemoryMapping Mapping(ushort absolute) + { + if (absolute < 0x8000) + { + return new MemoryMapping(this.ram, 0x0000, Mask.Mask16, AccessLevel.ReadWrite); + } + + if (absolute < 0xa000) + { + return new MemoryMapping(this.unused2000, 0x8000, Mask.Mask16, AccessLevel.ReadOnly); + } + + if (absolute < 0xc000) + { + return new MemoryMapping(this.io, 0xa000, Mask.Mask16, AccessLevel.ReadWrite); + } + + return new MemoryMapping(this.rom, 0xc000, Mask.Mask16, AccessLevel.ReadOnly); + } + + // Use the bus data to update the ACIA access/address pins + private void UpdateAciaPinsRead() + { + this.ACIA.RW.Raise(); + this.UpdateAciaPins(); + } + + private void UpdateAciaPinsWrite() + { + this.ACIA.RW.Lower(); + this.UpdateAciaPins(); + } + + private void UpdateAciaPins() + { + this.ACIA.DATA = this.Data; + + if ((this.Address.Word & (ushort)Bits.Bit0) != 0) + { + this.ACIA.RS.Raise(); + } + else + { + this.ACIA.RS.Lower(); + } + + if ((this.Address.Word & (ushort)Bits.Bit15) != 0) + { + this.ACIA.CS0.Raise(); + } + else + { + this.ACIA.CS0.Lower(); + } + + if ((this.Address.Word & (ushort)Bits.Bit13) != 0) + { + this.ACIA.CS1.Raise(); + } + else + { + this.ACIA.CS1.Lower(); + } + + if ((this.Address.Word & (ushort)Bits.Bit14) != 0) + { + this.ACIA.CS2.Raise(); + } + else + { + this.ACIA.CS2.Lower(); + } + } + + private bool AccessAcia() + { + this.ACIA.E.Raise(); + this.ACIA.Tick(); + this.ACIA.E.Lower(); + return this.ACIA.Activated; + } + } +} \ No newline at end of file diff --git a/MC6809/MC6809.Test/Configuration.cs b/MC6809/MC6809.Test/Configuration.cs new file mode 100644 index 0000000..69f8714 --- /dev/null +++ b/MC6809/MC6809.Test/Configuration.cs @@ -0,0 +1,15 @@ +namespace EightBit +{ + public class Configuration + { + public static readonly ulong CyclesPerSecond = 2 * 1024 * 1024; + public static readonly ulong FrameCycleInterval = CyclesPerSecond / 60; + public static readonly ulong TerminationCycles = CyclesPerSecond* 10 * 10; + + public bool DebugMode { get; } = false; + + public bool TerminatesEarly { get; } = false; + + public string RomDirectory { get; } = "roms\\searle"; + } +} \ No newline at end of file diff --git a/MC6809/MC6809.Test/MC6809.Test.csproj b/MC6809/MC6809.Test/MC6809.Test.csproj new file mode 100644 index 0000000..b6f478f --- /dev/null +++ b/MC6809/MC6809.Test/MC6809.Test.csproj @@ -0,0 +1,72 @@ + + + + + Debug + AnyCPU + {5ADB4727-2F5F-4A41-979B-6734501E34BC} + Exe + EightBit + MC6809.Test + v4.7.2 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + latest + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + latest + + + + + + + + + + + + + + + + + + + + + + + + {6ebf8857-62a3-4ef4-af21-c1844031d7e4} + EightBit + + + {a9760efd-79f2-4ec3-8647-d2a1587e3e7e} + MC6850 + + + {3a63972b-ab50-4a01-8a10-0d2165580fad} + MC6809 + + + + \ No newline at end of file diff --git a/MC6809/MC6809.Test/Program.cs b/MC6809/MC6809.Test/Program.cs new file mode 100644 index 0000000..5d6c992 --- /dev/null +++ b/MC6809/MC6809.Test/Program.cs @@ -0,0 +1,23 @@ +// +// Copyright (c) Adrian Conlon. All rights reserved. +// + +namespace EightBit +{ + public static class Program + { + public static void Main(string[] args) + { + var configuration = new Configuration(); + +#if DEBUG + configuration.DebugMode = true; +#endif + + using (var harness = new TestHarness(configuration)) + { + harness.Run(); + } + } + } +} diff --git a/MC6809/MC6809.Test/Properties/AssemblyInfo.cs b/MC6809/MC6809.Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..792e99e --- /dev/null +++ b/MC6809/MC6809.Test/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MC6809.Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MC6809.Test")] +[assembly: AssemblyCopyright("Copyright © 2019")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("5adb4727-2f5f-4a41-979b-6734501e34bc")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MC6809/MC6809.Test/TestHarness.cs b/MC6809/MC6809.Test/TestHarness.cs new file mode 100644 index 0000000..86fc582 --- /dev/null +++ b/MC6809/MC6809.Test/TestHarness.cs @@ -0,0 +1,56 @@ +// +// Copyright (c) Adrian Conlon. All rights reserved. +// + +namespace EightBit +{ + using System; + using System.Diagnostics; + + internal class TestHarness : IDisposable + { + private readonly Stopwatch timer = new Stopwatch(); + private readonly Board board; + private long totalCycles = 0; + + private bool disposed = false; + + public TestHarness(Configuration configuration) => this.board = new Board(configuration); + + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + public void Run() + { + this.board.Initialize(); + this.board.RaisePOWER(); + + var cpu = this.board.CPU; + + this.timer.Start(); + while (cpu.Powered) + { + this.totalCycles += cpu.Step(); + } + + this.timer.Stop(); + } + + protected virtual void Dispose(bool disposing) + { + if (!this.disposed) + { + if (disposing) + { + System.Console.Out.WriteLine($"\n\nGuest cycles = {this.totalCycles}"); + System.Console.Out.WriteLine($"Seconds = {this.timer.ElapsedMilliseconds / 1000.0}"); + } + + this.disposed = true; + } + } + } +} diff --git a/MC6809/MC6809.Test/roms/coco2h/bas12.rom b/MC6809/MC6809.Test/roms/coco2h/bas12.rom new file mode 100644 index 0000000000000000000000000000000000000000..46ed63de4cb53a01ec030a097cb47682bf430130 GIT binary patch literal 8192 zcmXwd3tSUt)^}zm2_X;@QSsgkkj$e{HEOapx?Kqn5CtYCk)j1rpsjVQwC{HJ(^g{! z)6@%-*6Jp;$_!peR0OJ3d{IWB#o4Y}>TMHiL9|lPR&Bes)mqzpC-(cqUuNdHoaa2} z`afsa+1)jvHKByikNdBMu4uZ6hybnY8AT~%;<03xj>5g`Yno#E=>epk@e`|M$($G_1<49Q@ z`^Bd(4wbFk>yu*D>kSz7NZ3E2+Rcv+;@Kg57f#6ySS3dOz`xETKFzQ(`V60<9q!wu z>Xy7CjuRR_=*AMor{LK8roR|BrV;;59NKNnI^8O&`|+N4gIFZEZ9y1Dhp;F2Mh(wS=oaUHzJ?Ly|N~DRC!A zN+g)(RgdJz+{6%tCk9(364!w-uKgdm>VI|}nd_$iWnUPTE_NOMKc)jOHoi2xam;~< z*>nMIC$lV${A_aS~^5;#ITpb?%Lz+lcdTC}BVdnoK_{w^2jHgvd5-L(sEXv+13X#|LMIE*Xcj{p@h` zNL(_=OE#Fct&8HVQAze3wA$$Gj!Jx(ot|q<3T3^VrOSS03A-?~bf0IhXJF}|yAXXl zkTqB#K0K?)(f#`E5;UiCOlt0#Om^aNYz&2;AqSV7#Ky8a#3-9mK*-pLMUlm1w5+9u);q9iNf{#nZf zVuDTPHZTe*p;jtEx!xtA8WJ%oY6!Oh-rZWwX)X0LIf5be>4h1IOr~DWEYV9neH$`? z!wt2vXj+m_D!H?Pyvx+euIqmmmk9eOnfwA)WlUDD^jD+!0yL7_-m`;@4{z+!`ZO9Z z$uEz*5?EpK6Dxg~gf1t)1LG918ui;gyjR48U9YKLr7~32R2q|r`hm5$Md-RgOB$IG zlyVXJk5?h=t|5PBh%p$F0jnz7hzV^a)gB+-V`6|)fq7Hc*7-eBfW7LkE}-K4tI+Ma=$;u35gHm;OV_h=zl8rw&^j#bgz zCLvg^UX{2;2wmYu^DdZJ+cS2n3#l~gB~cw7Su2EoBnKsH)N5U#LG>!85G|QjAvBy8 zf^*hl{b+nEb`y;UKaWvNTm??zI=Du_-V*js0*`LRzCuLoCQYM-(3%+i9#?^IaE1^{ zpoaO^Aa(j(ek@zyYrF$-!FBL9taAlN*YWH>fIPPe_?83T!m($85M1r(W9;kcoBQhE zU~2zkY|yZocLCiPwNH7MY7P20{k|)78_8e?U$>H%)Ct%+5FxU;n!Xi2>R*pVHK{}H zd?JhXZZP}b2A|$_R{eIsp`nJ33lzIrclfXi)ow2ta@S&4sbApuk;0*3q1D-qT^Q^@ z%34tobcZ??QNNghEhde^>v-XiMfm9M!i^H@<>CnFVkwfRmv{a?>3K7I2nhTF0ZG6% z_^XXL8xi*0EeBQ0AiiJ@6CS7@?>h1$8(~X?-~~zt@n`XqZDPYm|iPRs15kntTgnT^T+2k&q-@v|nbq!^Nsc!6|sHpxb=+N^hfhx!*$w}aP_a>a8< z&MK)m@`N{+ok*Kw8jA;2u?AK_K4M80Cm&IA|C-E<;d2AbvIv<8+WT$z+QEz7=~oo&JPjJu5WUOVv=D?Xjt%H!h6{}=mGawE?{-Sv4qaqsc}Xr(CXBt zzGjpND|Vn#w4^=AME>`#$e z_MTVzY%kjyB{pHlqJ&z(X0l1F*84jeA`eLx=&W%Os=giDZosuCbdT>4_( z=XUF7A!~u-biSBladz75`9+uM?))O#g3H#Tt|Dv6<(&M_>{d&ceL=U~>TuHb({`(K zfxR1E&)evEr?csz%LVz4%h?51%f%vVB)fpNbY(j%#iwbTwHv-1rwd~94(nyuZ-sT2 z3TY>O(LpaL>ar}z$^YD1V*SK1FW)9QEm`}VpF0+O?3`omE}}0xoYwPnuGrXgpyisS zsEfXMQfPPN0dtovS(g?#F4~K_9QoZgtMzPw75K65Ew-GqI6ldqW8Z6~#kurChZAOU zoqO&1d2^h53-fdK+GyCFUo_9UaBrdYv!=XeZ}ZLAU(4|3>;LS3SNOqX2Jej=HvS7`c1YPOEl-xCuB%qL)5AdCw8Uk8{CQM#>EXlwB` zw#;OoWoP*suS3>_AP;asI1O{Y#=9^e?0L648tq%A|5^2_hI%-i57zPM8~sqx0HEif z@V_aprjDT7)pkf|d5Oz7gsc!trlSwP}kh4JU{}VV9%Zu62KL+FT%+#;k=xR3da_!v z(&Kdp6hg~Jq4Ae#6_k`yPkT#@7Yx%wXnHdke?ECqc~eCXm`GzI!deAb3>n`CDwzfBy1h4 zkLyd}k*f&+MUH@NdvYp}sTZ0ka`cl#2GFrHNLfV!1a~dSE%OGAc9w88adiz~0BoiK z>&eh;U6zW2N}6Q)k#MP?nfeXj;4F~4b~rX#+?CHa>!O7g$Nz*;lvc=9XZqv!Zp;zzLq<)HXO#U?ygI5bCt z65rwMJt<(Gx}iJA>Qw_C;i!r$6k4-=l42g7f4^49&6+`lJen5VJlk%~p;Zzw6^cs& zGN{=>R6|DOatefz7mhw99L^V7_L6czND|to z$6z`0w1$dK2BIb|1Bf)B6yTHmCm#goGGK+2Qk36gkmU~3I~BSWUTT2c#+kzL8tS(M z(6Ze3;UMH`^K5I0({3U2^NMH?kxBwix``y7@C(L+q@sk((+)Qf;Elm$0Vg+0X!{r# zFuW|Z`>!uUiOnndWzDxVd=Tt$+N~t8kEf|0LB9e!Y~1f_$6zYCo=D$bo8cEnf!NuV zbgfYuLrk$Ca5zmpyRN}~SU-#*bZQ36e}DFt+4`!$Y|#7d@N8lrhGFvStzuonYCzyGom!v1EqXfU%5#dS$f48sR+|hENoWG>v$dE0-b!cTW4b?qaT@rD3fVK zH^E?(Tu?YVimL*{V)jug?;_#QA}Ca{9Z+%6k7Hj6EhC$~EC| znJjQV6K<6I*zG3iNo>N*rfsf6*q2&<}pkB&O z*DGV84(fr4x`&L8k`wZ??m9m5%m)hh1W@eX)e3HG&y1bpQIcj4gZ^TWk@p#kUh00{ z-C*`fHr?wVy8iInXhM&+H~SMwT(5;2&*wp|g9NALto(Q`uV=LSyxIJ& zTOyG>Ni2S6Mj5EvPc!f86~2%9;L=oq(Ee$U-P|KH%9F~u8PHm~Y%=mQK(I?nV-}9S zjS#}&mrU|r88?2X7Nzve(Ch)9x`P`wli!I+ei@YzCT>X4LQw-1E2#9GMAlmcJb1#y zpcHJMw}=U}N`_=6`6m+Wu8b|~tuo+Bg1W`4FR3;92cKxcMP{s*n0mFeK^v0oRL9b_ zU%Sp|>AoNVD@DW$Y z1ip|hyo$F2dkJQB9Bq{Mr0uz`*_xtP_NH-ZaDd+A z5yud5=nN}0Ny%$5r~wzA$EEOjfHZa{z;&mQ54o{m6jC;oe8^ik3+Tdh2ft+LwFI&B z?+2tMXJs>YTF@;hc^?Kb1D-y7z=Je*aLv}V)OgL-yfi64uQ$&iGjsFMuTVWLx|G+O z&86{xlSpn}kM%CjSq)m((XBmpBlJPiV*aJ!D+WBA{acStCXRy}#nKLpuo|wAO=T0g z3U-`uw7_*}Su=i3UrI`YfAlN*^k&%2*c<%{x_8 z9G_qq%d2QJWO%4k&Z*^PW~gEyU>;rJcL+y^hCI_MTt^E4-Sn~7(c%H9{N~U%JZZ#$ z2ZSgbRRbG4OwySqDM+6D51Uc%$t3&4Xv6`QI}sW)(AAj4jzGHdxeygU({8-(v0ZSa zb%h;d2iWwz{^l3>!eG@v)wGwiCaB*2Uw`FxA@$!O4MM9|gNSk0f_!jh&||b$djNw7 zNhW*9(-$t z@p3P+nr2?|VmIC!>_F#*wnO9t0Sg+W8fY1Ujn2;)!OWxpBXoMu_nqs}omy`SYaqYw z#*&#R1uB|u^{ksdcSRQ(tnW(yxv}e>Wp0LiMMwH$@u&U@(@i}yt-_RfHOp_IbdOv{w%5 z$p+;L*lIL~*^9~`3R;+1XeH#G7%-y%nS3D}O=e#J!;7I8=spbt{Cu&Dg2)exhqEP+ z0Zw~WZVHverA>wY$c5vV)8lPD~-3L`P8zFh=-?gD{5shixy*4GfbHmyeJq%PVQ} zKju4FVCg1zZ&~;WIJ!ghmIpn7QUFPXD0v5+n?FIb*&U!!qQ3%!<9BA0__PYBoG!YK zzbCYpBh_YH|D(D>X!{H#@~zoJ0^cz1JF&JrQUTDjmgUgjBs6;nrqB5#!$in_&~>wI zDT5~V{4I+qmEXRl9QyQ*ElVgYTf1+ePC4jS5*bD`S;VxP^g|R&;>+U~$Cv4EW_(Ka z`Io%w2rTiJzh@7W`xn1AKd{(e_MRMyp0>d+s#HC zuIYqp+SHW;o@Ro#M`%-xPhutIK1pURH_K0lJbowOCtC>f&kq3-`;IXC!QQx1o>o`- zV}|79%7Ii5-CN4d=NEGheo3J@Oe00uxloMiF&i``BR2JXaf9FHc1P%*O}+L&Wx(k= zK1%I0L-x8ffL(EBTnIzVr^XLpv8wq7Mhy$kzkyS#u>A%>#f2T$r4(i^zTzYsf%LN- z^?ql%jCfu+{w5fH=flZz;drz9d9(U?zcXKMbAboYo%Oo$?8Qi>-x+bb-QIfe6Gs4p zQzN#>{D?i`Fhi;4(d^fn&=@C3$6O@Q|*0K!9< zNl;ifA_bFyq@}P_+*Eq-~_AHB`nrxxn3n{g2XE$-xONO24xOY;hqpvF9^cuo6KunSDbf+qO zLWgktjQ2sn>Jv@~?e&w@KA|=C91>&9O8yXI)CyH;+Y!iXV1m}o%8Ym>K_{E5-RQ;V z&JE;6tdmvOs=Sj!9c4)BHH12RCr^uRzoU_eg_QkxETrtmVj*R}CtxcrUO3^Vj_63R zotNGnvAtmwPk9d1zcZ;hkg)WqGY3i+4&v zhf??J*_n54!IaKdTkt3a@k3UFE#lzw3B$_0QKh4vL0DQE<% ziR~H!d)PCvmQCBouJ(H;v1HzM5*x+aPo8?6FFSeaAAGrR{CrQ-CogRN4I9;K?`iz^ zhZ|+TVaeb~PUsNP{tLWn-)zEeVYsc>Q=ys{svEBp{fgtm6ysgH%WHowz| zgSE6B0em4Nl)}l|PsTqs;f3kMldpfdPJX{WUww7=x|jrHo`Erw#(F2j{rd3j?aMY| qZ>O31Zg?BY1}8jOv&)(L&aijv*&9C#GMEG-Fg2El$+7r)^nU@BmXI|7 literal 0 HcmV?d00001 diff --git a/MC6809/MC6809.Test/roms/coco2h/disk11.rom b/MC6809/MC6809.Test/roms/coco2h/disk11.rom new file mode 100644 index 0000000000000000000000000000000000000000..58d197f74fe14151570858a187333a566f29e240 GIT binary patch literal 8192 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 A`~Uy| literal 0 HcmV?d00001 diff --git a/MC6809/MC6809.Test/roms/coco2h/extbas11.rom b/MC6809/MC6809.Test/roms/coco2h/extbas11.rom new file mode 100644 index 0000000000000000000000000000000000000000..e716d7f0075a1d32b1551310927029dd9006dce9 GIT binary patch literal 8192 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 +0033 000a RELFLG RMB 1 *TV RELATIONAL OPERATOR FLAG +0034 000b TEMPPT RMB 2 *PV TEMPORARY STRING STACK POINTER +0035 000d LASTPT RMB 2 *PV ADDR OF LAST USED STRING STACK ADDRESS +0036 000f TEMPTR RMB 2 TEMPORARY POINTER +0037 0011 TMPTR1 RMB 2 TEMPORARY DESCRIPTOR STORAGE (STACK SEARCH) +0038 0013 FPA2 RMB 4 FLOATING POINT ACCUMULATOR #2 MANTISSA +0039 0017 BOTSTK RMB 2 BOTTOM OF STACK AT LAST CHECK +0040 0019 TXTTAB RMB 2 *PV BEGINNING OF BASIC PROGRAM +0041 001b VARTAB RMB 2 *PV START OF VARIABLES +0042 001d ARYTAB RMB 2 *PV START OF ARRAYS +0043 001f ARYEND RMB 2 *PV END OF ARRAYS (+1) +0044 0021 FRETOP RMB 2 *PV START OF STRING STORAGE (TOP OF FREE RAM) +0045 0023 STRTAB RMB 2 *PV START OF STRING VARIABLES +0046 0025 FRESPC RMB 2 UTILITY STRING POINTER +0047 0027 MEMSIZ RMB 2 *PV TOP OF STRING SPACE +0048 0029 OLDTXT RMB 2 SAVED LINE NUMBER DURING A "STOP" +0049 002b BINVAL RMB 2 BINARY VALUE OF A CONVERTED LINE NUMBER +0050 002d OLDPTR RMB 2 SAVED INPUT PTR DURING A "STOP" +0051 002f TINPTR RMB 2 TEMPORARY INPUT POINTER STORAGE +0052 0031 DATTXT RMB 2 *PV 'DATA' STATEMENT LINE NUMBER POINTER +0053 0033 DATPTR RMB 2 *PV 'DATA' STATEMENT ADDRESS POINTER +0054 0035 DATTMP RMB 2 DATA POINTER FOR 'INPUT' & 'READ' +0055 0037 VARNAM RMB 2 *TV TEMP STORAGE FOR A VARIABLE NAME +0056 0039 VARPTR RMB 2 *TV POINTER TO A VARIABLE DESCRIPTOR +0057 003b VARDES RMB 2 TEMP POINTER TO A VARIABLE DESCRIPTOR +0058 003d RELPTR RMB 2 POINTER TO RELATIONAL OPERATOR PROCESSING ROUTINE +0059 003f TRELFL RMB 1 TEMPORARY RELATIONAL OPERATOR FLAG BYTE +0060 * FLOATING POINT ACCUMULATORS #3,4 & 5 ARE MOSTLY +0061 * USED AS SCRATCH PAD VARIABLES. +0062 ** FLOATING POINT ACCUMULATOR #3 :PACKED: ($40-$44) +0063 0040 V40 RMB 1 +0064 0041 V41 RMB 1 +0065 0042 V42 RMB 1 +0066 0043 V43 RMB 1 +0067 0044 V44 RMB 1 +0068 ** FLOATING POINT ACCUMULATOR #4 :PACKED: ($45-$49) +0069 0045 V45 RMB 1 +0070 0046 V46 RMB 1 +0071 0047 V47 RMB 1 +0072 0048 V48 RMB 2 +0073 ** FLOATING POINT ACCUMULATOR #5 :PACKED: ($4A—$4E) +0074 004a V4A RMB 1 +0075 004b V4B RMB 2 +0076 004d V4D RMB 2 +0077 ** FLOATING POINT ACCUMULATOR #0 +0078 004f FP0EXP RMB 1 *PV FLOATING POINT ACCUMULATOR #0 EXPONENT +0079 0050 FPA0 RMB 4 *PV FLOATING POINT ACCUMULATOR #0 MANTISSA +0080 0054 FP0SGN RMB 1 *PV FLOATING POINT ACCUMULATOR #0 SIGN +0081 0055 COEFCT RMB 1 POLYNOMIAL COEFFICIENT COUNTER +0082 0056 STRDES RMB 5 TEMPORARY STRING DESCRIPTOR +0083 005b FPCARY RMB 1 FLOATING POINT CARRY BYTE +0084 ** FLOATING POINT ACCUMULATOR #1 +0085 005c FP1EXP RMB 1 *PV FLOATING POINT ACCUMULATOR #1 EXPONENT +0086 005d FPA1 RMB 4 *PV FLOATING POINT ACCUMULATOR #1 MANTISSA +0087 0061 FP1SGN RMB 1 *PV FLOATING POINT ACCUMULATOR #1 SIGN +0088 0062 RESSGN RMB 1 SIGN OF RESULT OF FLOATING POINT OPERATION +0089 0063 FPSBYT RMB 1 FLOATING POINT SUB BYTE (FIFTH BYTE) +0090 0064 COEFPT RMB 2 POLYNOMIAL COEFFICIENT POINTER +0091 0066 LSTTXT RMB 2 CURRENT LINE POINTER DURING LIST +0092 0068 CURLIN RMB 2 *PV CURRENT LINE # OF BASIC PROGRAM, $FFFF = DIRECT +0093 006a DEVCFW RMB 1 *TV TAB FIELD WIDTH +0094 006b DEVLCF RMB 1 *TV TAB ZONE +0095 006c DEVPOS RMB 1 *TV PRINT POSITION +0096 006d DEVWID RMB 1 *TV PRINT WIDTH +0097 006e RSTFLG RMB 1 *PV WARM START FLAG: $55=WARM, OTHER=COLD +0098 006f RSTVEC RMB 2 *PV WARM START VECTOR - JUMP ADDRESS FOR WARM START +0099 0071 TOPRAM RMB 2 *PV TOP OF RAM +0100 0073 IKEYIM RMB 1 *TV INKEY$ RAM IMAGE +0101 0074 ZERO RMB 2 *PV DUMMY - THESE TWO BYTES ARE ALWAYS ZERO +0102 * THE FOLLOWING BYTES ARE MOVED DOWN FROM ROM +0103 0076 LPTCFW RMB 1 16 +0104 0077 LPTLCF RMB 1 112 +0105 0078 LPTWID RMB 1 132 +0106 0079 LPTPOS RMB 1 0 +0107 007a EXECJP RMB 2 LB4AA +0108 +0109 * THIS ROUTINE PICKS UP THE NEXT INPUT CHARACTER FROM +0110 * BASIC. THE ADDRESS OF THE NEXT BASIC BYTE TO BE +0111 * INTERPRETED IS STORED AT CHARAD. +0112 007c 0c 84 GETNCH INC 7372800 / 4 / 16 = 115200 +0287 dbb2 b7 a0 00 STA UCTRL +0288 dbb5 8e dc 03 LDX #LA147-1 POINT X TO COLOR BASIC COPYRIGHT MESSAGE +0289 dbb8 bd eb e5 JSR LB99C PRINT ‘COLOR BASIC’ +0290 dbbb 8e db c6 LDX #BAWMST WARM START ADDRESS +0291 dbbe 9f 6f STX RSTVEC SAVE IT +0292 dbc0 86 55 LDA #$55 WARM START FLAG +0293 dbc2 97 6e STA RSTFLG SAVE IT +0294 dbc4 20 04 BRA LA0F3 GO TO BASIC’S MAIN LOOP +0295 dbc6 12 BAWMST NOP NOP REQ’D FOR WARM START +0296 dbc7 bd df d4 JSR LAD33 DO PART OF A NEW +0297 dbca 7e df 22 LA0F3 JMP LAC73 GO TO MAIN LOOP OF BASIC +0298 * +0299 * FIRQ SERVICE ROUTINE +0300 BFRQSV +0301 dbcd 3b RTI +0302 * +0303 * THESE BYTES ARE MOVED TO ADDRESSES $76 - $85 THE DIRECT PAGE +0304 dbce 10 LA10D FCB 16 TAB FIELD WIDTH +0305 dbcf 40 FCB 64 LAST TAB ZONE +0306 dbd0 50 FCB 80 PRINTER WIDTH +0307 dbd1 00 FCB 0 LINE PRINTER POSITION +0308 dbd2 e6 ce FDB LB44A ARGUMENT OF EXEC COMMAND - SET TO ‘FC’ ERROR +0309 * LINE INPUT ROUTINE +0310 dbd4 0c 84 INC CHARAD+1 +0311 dbd6 26 02 BNE LA123 +0312 dbd8 0c 83 INC CHARAD +0313 dbda b6 00 00 LA123 LDA >0000 +0314 dbdd 7e dc bf JMP BROMHK +0315 * +0316 * THESE BYTES ARE MOVED TO ADDRESSES $A7-$B1 +0317 dbe0 7e dc be JMP BIRQSV IRQ SERVICE +0318 dbe3 7e db cd JMP BFRQSV FIRQ SERVICE +0319 dbe6 7e e6 ce JMP LB44A USR ADDRESS FOR 8K BASIC (INITIALIZED TO ‘FC’ ERROR) +0320 dbe9 80 FCB $80 *RANDOM SEED +0321 dbea 4f c7 FDB $4FC7 *RANDON SEED OF MANTISSA +0322 dbec 52 59 FDB $5259 *.811635157 +0323 * BASIC COMMAND INTERPRETATION TABLE ROM IMAGE +0324 dbee 32 COMVEC FCB 50 50 BASIC COMMANDS +0325 dbef dd 1d FDB LAA66 POINTS TO RESERVED WORDS +0326 dbf1 de 2a FDB LAB67 POINTS TO JUMP TABLE FOR COMMANDS +0327 dbf3 1d FCB 29 29 BASIC SECONDARY COMMANDS +0328 dbf4 dd bd FDB LAB1A POINTS TO SECONDARY FUNCTION RESERVED WORDS +0329 dbf6 dc ce FDB LAA29 POINTS TO SECONDARY FUNCTION JUMP TABLE +0330 dbf8 00 00 FDB 0 NO MORE TABLES (RES WORDS=0) +0331 dbfa 00 00 FDB 0 NO MORE TABLES +0332 dbfc 00 00 FDB 0 NO MORE TABLES +0333 dbfe 00 00 FDB 0 NO MORE TABLES +0334 dc00 00 00 FDB 0 NO MORE TABLES +0335 dc02 00 00 FDB 0 NO MORE TABLES (SECONDARY FNS =0) +0336 +0337 * COPYRIGHT MESSAGES +0338 dc04 36 38 30 39 20 45 LA147 FCC "6809 EXTENDED BASIC" + 58 54 45 4e 44 45 + 44 20 42 41 53 49 + 43 +0339 dc17 0d FCB CR +0340 dc18 28 43 29 20 31 39 FCC "(C) 1982 BY MICROSOFT" + 38 32 20 42 59 20 + 4d 49 43 52 4f 53 + 4f 46 54 +0341 dc2d 0d 0d LA156 FCB CR,CR +0342 dc2f 00 LA165 FCB $00 +0343 +0344 +0345 dc30 34 16 LA35F PSHS X,B,A SAVE REGISTERS +0346 dc32 9e 76 LDX LPTCFW TAB FIELD WIDTH AND TAB ZONE +0347 dc34 dc 78 LDD LPTWID PRINTER WIDTH AND POSITION +0348 dc36 9f 6a LA37C STX DEVCFW SAVE TAB FIELD WIDTH AND ZONE +0349 dc38 d7 6c STB DEVPOS SAVE PRINT POSITION +0350 dc3a 97 6d STA DEVWID SAVE PRINT WIDTH +0351 dc3c 35 96 PULS A,B,X,PC RESTORE REGISTERS +0352 +0353 * THIS IS THE ROUTINE THAT GETS AN INPUT LINE FOR BASIC +0354 * EXIT WITH BREAK KEY: CARRY = 1 +0355 * EXIT WITH ENTER KEY: CARRY = 0 +0356 LA38D +0357 dc3e 0f 73 LA390 CLR IKEYIM RESET BREAK CHECK KEY TEMP KEY STORAGE +0358 dc40 8e 00 f4 LDX #LINBUF+1 INPUT LINE BUFFER +0359 dc43 c6 01 LDB #1 ACCB CHAR COUNTER: SET TO 1 TO ALLOW A +0360 * BACKSPACE AS FIRST CHARACTER +0361 dc45 bd db 00 LA39A JSR LA171 GO GET A CHARACTER FROM CONSOLE IN +0362 dc48 81 08 CMPA #BS BACKSPACE +0363 dc4a 26 07 BNE LA3B4 NO +0364 dc4c 5a DECB YES - DECREMENT CHAR COUNTER +0365 dc4d 27 ef BEQ LA390 BRANCH IF BACK AT START OF LINE AGAIN +0366 dc4f 30 1f LEAX -1,X DECREMENT BUFFER POINTER +0367 dc51 20 34 BRA LA3E8 ECHO CHAR TO SCREEN +0368 dc53 81 15 LA3B4 CMPA #$15 SHIFT RIGHT ARROW? +0369 dc55 26 0a BNE LA3C2 NO +0370 * YES, RESET BUFFER TO BEGINNING AND ERASE CURRENT LINE +0371 dc57 5a LA3B8 DECB DEC CHAR CTR +0372 dc58 27 e4 BEQ LA390 GO BACK TO START IF CHAR CTR = 0 +0373 dc5a 86 08 LDA #BS BACKSPACE? +0374 dc5c bd db 14 JSR PUTCHR SEND TO CONSOLE OUT (SCREEN) +0375 dc5f 20 f6 BRA LA3B8 KEEP GOING +0376 dc61 81 03 LA3C2 CMPA #3 BREAK KEY? +0377 dc63 1a 01 ORCC #1 SET CARRY FLAG +0378 dc65 27 05 BEQ LA3CD BRANCH IF BREAK KEY DOWN +0379 dc67 81 0d LA3C8 CMPA #CR ENTER KEY? +0380 dc69 26 0d BNE LA3D9 NO +0381 dc6b 4f LA3CC CLRA CLEAR CARRY FLAG IF ENTER KEY - END LINE ENTRY +0382 dc6c 34 01 LA3CD PSHS CC SAVE CARRY FLAG +0383 dc6e bd eb a5 JSR LB958 SEND CR TO SCREEN +0384 dc71 6f 84 CLR ,X MAKE LAST BYTE IN INPUT BUFFER = 0 +0385 dc73 8e 00 f3 LDX #LINBUF RESET INPUT BUFFER POINTER +0386 dc76 35 81 PULS CC,PC RESTORE CARRY FLAG +0387 +0388 * INSERT A CHARACTER INTO THE BASIC LINE INPUT BUFFER +0389 dc78 81 20 LA3D9 CMPA #$20 IS IT CONTROL CHAR? +0390 dc7a 25 c9 BLO LA39A BRANCH IF CONTROL CHARACTER +0391 dc7c 81 7b CMPA #'z+1 * +0392 dc7e 24 c5 BCC LA39A * IGNORE IF > LOWER CASE Z +0393 dc80 c1 fa CMPB #LBUFMX HAVE 250 OR MORE CHARACTERS BEEN ENTERED? +0394 dc82 24 c1 BCC LA39A YES, IGNORE ANY MORE +0395 dc84 a7 80 STA ,X+ PUT IT IN INPUT BUFFER +0396 dc86 5c INCB INCREMENT CHARACTER COUNTER +0397 dc87 bd db 14 LA3E8 JSR PUTCHR ECHO IT TO SCREEN +0398 dc8a 20 b9 BRA LA39A GO SET SOME MORE +0399 +0400 +0401 * EXEC +0402 dc8c 27 05 EXEC BEQ LA545 BRANCH IF NO ARGUMENT +0403 dc8e bd e9 c1 JSR LB73D EVALUATE ARGUMENT - ARGUMENT RETURNED IN X +0404 dc91 9f 7a STX EXECJP STORE X TO EXEC JUMP ADDRESS +0405 dc93 6e 9f 00 7a LA545 JMP [EXECJP] GO DO IT +0406 +0407 * BREAK CHECK +0408 dc97 7e e0 a3 LA549 JMP LADEB GO DO BREAK KEY CHECK +0409 +0410 * INKEY$ +0411 dc9a 96 73 INKEY LDA IKEYIM WAS A KEY DOWN IN THE BREAK CHECK? +0412 dc9c 26 03 BNE LA56B YES +0413 dc9e bd db 05 JSR KEYIN GO GET A KEY +0414 dca1 0f 73 LA56B CLR IKEYIM CLEAR INKEY RAM IMAGE +0415 dca3 97 53 STA FPA0+3 STORE THE KEY IN FPA0 +0416 dca5 10 26 0c 6a LBNE LB68F CONVERT FPA0+3 TO A STRING +0417 dca9 97 56 STA STRDES SET LENGTH OF STRING = 0 IF NO KEY DOWN +0418 dcab 7e e9 1f JMP LB69B PUT A NULL STRING ONTO THE STRING STACK +0419 +0420 * MOVE ACCB BYTES FROM (X) TO (U) +0421 dcae a6 80 LA59A LDA ,X+ GET BYTE FROM X +0422 dcb0 a7 c0 STA ,U+ STORE IT AT U +0423 dcb2 5a DECB MOVED ALL BYTES? +0424 dcb3 26 f9 BNE LA59A NO +0425 dcb5 39 LA5A1 RTS +0426 +0427 dcb6 39 LA5C4 RTS +0428 +0429 ** THIS ROUTINE WILL SCAN OFF THE FILE NAME FROM A BASIC LINE +0430 ** AND RETURN A SYNTAX ERROR IF THERE ARE ANY CHARACTERS +0431 ** FOLLOWING THE END OF THE NAME +0432 dcb7 9d 82 LA5C7 JSR GETCCH GET CURRENT INPUT CHAR FROM BASIC LINE +0433 dcb9 27 fb LA5C9 BEQ LA5C4 RETURN IF END OF LINE +0434 dcbb 7e e5 00 JMP LB277 SYNTAX ERROR IF ANY MORE CHARACTERS +0435 * IRQ SERVICE +0436 BIRQSV +0437 dcbe 3b LA9C5 RTI RETURN FROM INTERRUPT +0438 +0439 * SET CARRY IF NUMERIC - RETURN WITH +0440 * ZERO FLAG SET IF ACCA = 0 OR 3A(:) - END +0441 * OF BASIC LINE OR SUB LINE +0442 dcbf 81 3a BROMHK CMPA #'9+1 IS THIS CHARACTER >=(ASCII 9)+1? +0443 dcc1 24 0a BHS LAA28 BRANCH IF > 9; Z SET IF = COLON +0444 dcc3 81 20 CMPA #SPACE SPACE? +0445 dcc5 26 02 BNE LAA24 NO - SET CARRY IF NUMERIC +0446 dcc7 0e 7c JMP GETNCH IF SPACE, GET NECT CHAR (IGNORE SPACES) +0447 dcc9 80 30 LAA24 SUBA #'0 * SET CARRY IF +0448 dccb 80 d0 SUBA #-'0 * CHARACTER > ASCII 0 +0449 dccd 39 LAA28 RTS +0450 +0451 * DISPATCH TABLE FOR SECONDARY FUNCTIONS +0452 * TOKENS ARE PRECEEDED BY $FF +0453 * FIRST SET ALWAYS HAS ONE PARAMETER +0454 FUNC_TAB +0455 dcce ee c3 LAA29 FDB SGN SGN +0456 dcd0 ef 37 FDB INT INT +0457 dcd2 ee dc FDB ABS ABS +0458 dcd4 00 ad FDB USRJMP USR +0459 0083 TOK_USR EQU *-FUNC_TAB/2+$7F +0460 ff83 TOK_FF_USR EQU *-FUNC_TAB/2+$FF7F +0461 dcd6 f1 68 FDB RND RND +0462 dcd8 f1 bd FDB SIN SIN +0463 dcda e9 d4 FDB PEEK PEEK +0464 dcdc e9 05 FDB LEN LEN +0465 dcde e7 81 FDB STR STR$ +0466 dce0 e9 9a FDB VAL VAL +0467 dce2 e9 24 FDB ASC ASC +0468 dce4 e9 10 FDB CHR CHR$ +0469 dce6 f2 6d FDB ATN ATN +0470 dce8 f2 35 FDB COS COS +0471 dcea f2 3e FDB TAN TAN +0472 dcec f3 af FDB EXP EXP +0473 dcee f3 e1 FDB FIX FIX +0474 dcf0 f3 03 FDB LOG LOG +0475 dcf2 f5 69 FDB POS POS +0476 dcf4 f3 3d FDB SQR SQR +0477 dcf6 fa 3b FDB HEXDOL HEX$ +0478 * LEFT, RIGHT AND MID ARE TREATED SEPARATELY +0479 dcf8 e9 2f FDB LEFT LEFT$ +0480 0095 TOK_LEFT EQU *-FUNC_TAB/2+$7F +0481 dcfa e9 4c FDB RIGHT RIGHT$ +0482 dcfc e9 53 FDB MID MID$ +0483 0097 TOK_MID EQU *-FUNC_TAB/2+$7F +0484 * REMAINING FUNCTIONS +0485 dcfe dc 9a FDB INKEY INKEY$ +0486 0098 TOK_INKEY EQU *-FUNC_TAB/2+$7F +0487 dd00 e7 72 FDB MEM MEM +0488 dd02 f5 71 FDB VARPT VARPTR +0489 dd04 f6 31 FDB INSTR INSTR +0490 dd06 f6 01 FDB STRING STRING$ +0491 001d NUM_SEC_FNS EQU *-FUNC_TAB/2 +0492 +0493 * THIS TABLE CONTAINS PRECEDENCES AND DISPATCH ADDRESSES FOR ARITHMETIC +0494 * AND LOGICAL OPERATORS - THE NEGATION OPERATORS DO NOT ACT ON TWO OPERANDS +0495 * S0 THEY ARE NOT LISTED IN THIS TABLE. THEY ARE TREATED SEPARATELY IN THE +0496 * EXPRESSION EVALUATION ROUTINE. THEY ARE: +0497 * UNARY NEGATION (-), PRECEDENCE &7D AND LOGICAL NEGATION (NOT), PRECEDENCE $5A +0498 * THE RELATIONAL OPERATORS < > = ARE ALSO NOT LISTED, PRECEDENCE $64. +0499 * A PRECEDENCE VALUE OF ZERO INDICATES END OF EXPRESSION OR PARENTHESES +0500 * +0501 dd08 79 LAA51 FCB $79 +0502 dd09 ec 0e FDB LB9C5 + +0503 dd0b 79 FCB $79 +0504 dd0c ec 05 FDB LB9BC - +0505 dd0e 7b FCB $7B +0506 dd0f ed 15 FDB LBACC * +0507 dd11 7b FCB $7B +0508 dd12 ed da FDB LBB91 / +0509 dd14 7f FCB $7F +0510 dd15 f3 46 FDB L8489 EXPONENTIATION +0511 dd17 50 FCB $50 +0512 dd18 e5 59 FDB LB2D5 AND +0513 dd1a 46 FCB $46 +0514 dd1b e5 58 FDB LB2D4 OR +0515 +0516 * THIS IS THE RESERVED WORD TABLE +0517 * FIRST PART OF THE TABLE CONTAINS EXECUTABLE COMMANDS +0518 dd1d 46 4f LAA66 FCC "FO" 80 +0519 dd1f d2 FCB $80+'R' +0520 dd20 47 FCC "G" 81 +0521 dd21 cf FCB $80+'O' +0522 0081 TOK_GO EQU $81 +0523 dd22 52 45 FCC "RE" 82 +0524 dd24 cd FCB $80+'M' +0525 dd25 a7 FCB ''+$80 83 +0526 dd26 45 4c 53 FCC "ELS" 84 +0527 dd29 c5 FCB $80+'E' +0528 dd2a 49 FCC "I" 85 +0529 dd2b c6 FCB $80+'F' +0530 dd2c 44 41 54 FCC "DAT" 86 +0531 dd2f c1 FCB $80+'A' +0532 dd30 50 52 49 4e FCC "PRIN" 87 +0533 dd34 d4 FCB $80+'T' +0534 dd35 4f FCC "O" 88 +0535 dd36 ce FCB $80+'N' +0536 dd37 49 4e 50 55 FCC "INPU" 89 +0537 dd3b d4 FCB $80+'T' +0538 dd3c 45 4e FCC "EN" 8A +0539 dd3e c4 FCB $80+'D' +0540 dd3f 4e 45 58 FCC "NEX" 8B +0541 dd42 d4 FCB $80+'T' +0542 dd43 44 49 FCC "DI" 8C +0543 dd45 cd FCB $80+'M' +0544 dd46 52 45 41 FCC "REA" 8D +0545 dd49 c4 FCB $80+'D' +0546 dd4a 52 55 FCC "RU" 8E +0547 dd4c ce FCB $80+'N' +0548 dd4d 52 45 53 54 4f 52 FCC "RESTOR" 8F +0549 dd53 c5 FCB $80+'E' +0550 dd54 52 45 54 55 52 FCC "RETUR" 90 +0551 dd59 ce FCB $80+'N' +0552 dd5a 53 54 4f FCC "STO" 91 +0553 dd5d d0 FCB $80+'P' +0554 dd5e 50 4f 4b FCC "POK" 92 +0555 dd61 c5 FCB $80+'E' +0556 dd62 43 4f 4e FCC "CON" 93 +0557 dd65 d4 FCB $80+'T' +0558 dd66 4c 49 53 FCC "LIS" 94 +0559 dd69 d4 FCB $80+'T' +0560 dd6a 43 4c 45 41 FCC "CLEA" 95 +0561 dd6e d2 FCB $80+'R' +0562 dd6f 4e 45 FCC "NE" 96 +0563 dd71 d7 FCB $80+'W' +0564 dd72 45 58 45 FCC "EXE" 97 +0565 dd75 c3 FCB $80+'C' +0566 dd76 54 52 4f FCC "TRO" 98 +0567 dd79 ce FCB $80+'N' +0568 dd7a 54 52 4f 46 FCC "TROF" 99 +0569 dd7e c6 FCB $80+'F' +0570 dd7f 44 45 FCC "DE" 9A +0571 dd81 cc FCB $80+'L' +0572 dd82 44 45 FCC "DE" 9B +0573 dd84 c6 FCB $80+'F' +0574 dd85 4c 49 4e FCC "LIN" 9C +0575 dd88 c5 FCB $80+'E' +0576 dd89 52 45 4e 55 FCC "RENU" 9D +0577 dd8d cd FCB $80+'M' +0578 dd8e 45 44 49 FCC "EDI" 9E +0579 dd91 d4 FCB $80+'T' +0580 * END OF EXECUTABLE COMMANDS. THE REMAINDER OF THE TABLE ARE NON-EXECUTABLE TOKENS +0581 dd92 54 41 42 FCC "TAB" 9F +0582 dd95 a8 FCB $80+'(' +0583 009f TOK_TAB EQU $9F +0584 dd96 54 FCC "T" A0 +0585 dd97 cf FCB $80+'O' +0586 00a0 TOK_TO EQU $A0 +0587 dd98 53 55 FCC "SU" A1 +0588 dd9a c2 FCB $80+'B' +0589 00a1 TOK_SUB EQU $A1 +0590 dd9b 54 48 45 FCC "THE" A2 +0591 dd9e ce FCB $80+'N' +0592 00a2 TOK_THEN EQU $A2 +0593 dd9f 4e 4f FCC "NO" A3 +0594 dda1 d4 FCB $80+'T' +0595 00a3 TOK_NOT EQU $A3 +0596 dda2 53 54 45 FCC "STE" A4 +0597 dda5 d0 FCB $80+'P' +0598 00a4 TOK_STEP EQU $A4 +0599 dda6 4f 46 FCC "OF" A5 +0600 dda8 c6 FCB $80+'F' +0601 dda9 ab FCB '++$80 A6 +0602 00a6 TOK_PLUS EQU $A6 +0603 ddaa ad FCB '-+$80 A7 +0604 00a7 TOK_MINUS EQU $A7 +0605 ddab aa FCB '*+$80 A8 +0606 ddac af FCB '/+$80 A9 +0607 ddad de FCB '^+$80 AA +0608 ddae 41 4e FCC "AN" AB +0609 ddb0 c4 FCB $80+'D' +0610 ddb1 4f FCC "O" AC +0611 ddb2 d2 FCB $80+'R' +0612 ddb3 be FCB '>+$80 AD +0613 00ad TOK_GREATER EQU $AD +0614 ddb4 bd FCB '=+$80 AE +0615 00ae TOK_EQUALS EQU $AE +0616 ddb5 bc FCB '<+$80 AF +0617 ddb6 46 FCC "F" B0 +0618 ddb7 ce FCB $80+'N' +0619 00b0 TOK_FN EQU $B0 +0620 ddb8 55 53 49 4e FCC "USIN" B1 +0621 ddbc c7 FCB $80+'G' +0622 00b1 TOK_USING EQU $B1 +0623 * +0624 +0625 * FIRST SET ALWAYS HAS ONE PARAMETER +0626 ddbd 53 47 LAB1A FCC "SG" 80 +0627 ddbf ce FCB $80+'N' +0628 ddc0 49 4e FCC "IN" 81 +0629 ddc2 d4 FCB $80+'T' +0630 ddc3 41 42 FCC "AB" 82 +0631 ddc5 d3 FCB $80+'S' +0632 ddc6 55 53 FCC "US" 83 +0633 ddc8 d2 FCB $80+'R' +0634 ddc9 52 4e FCC "RN" 84 +0635 ddcb c4 FCB $80+'D' +0636 ddcc 53 49 FCC "SI" 85 +0637 ddce ce FCB $80+'N' +0638 ddcf 50 45 45 FCC "PEE" 86 +0639 ddd2 cb FCB $80+'K' +0640 ddd3 4c 45 FCC "LE" 87 +0641 ddd5 ce FCB $80+'N' +0642 ddd6 53 54 52 FCC "STR" 88 +0643 ddd9 a4 FCB $80+'$' +0644 ddda 56 41 FCC "VA" 89 +0645 dddc cc FCB $80+'L' +0646 dddd 41 53 FCC "AS" 8A +0647 dddf c3 FCB $80+'C' +0648 dde0 43 48 52 FCC "CHR" 8B +0649 dde3 a4 FCB $80+'$' +0650 dde4 41 54 FCC "AT" 8C +0651 dde6 ce FCB $80+'N' +0652 dde7 43 4f FCC "CO" 8D +0653 dde9 d3 FCB $80+'S' +0654 ddea 54 41 FCC "TA" 8E +0655 ddec ce FCB $80+'N' +0656 dded 45 58 FCC "EX" 8F +0657 ddef d0 FCB $80+'P' +0658 ddf0 46 49 FCC "FI" 90 +0659 ddf2 d8 FCB $80+'X' +0660 ddf3 4c 4f FCC "LO" 91 +0661 ddf5 c7 FCB $80+'G' +0662 ddf6 50 4f FCC "PO" 92 +0663 ddf8 d3 FCB $80+'S' +0664 ddf9 53 51 FCC "SQ" 93 +0665 ddfb d2 FCB $80+'R' +0666 ddfc 48 45 58 FCC "HEX" 94 +0667 ddff a4 FCB $80+'$' +0668 * LEFT, RIGHT AND MID ARE TREATED SEPARATELY +0669 de00 4c 45 46 54 FCC "LEFT" 95 +0670 de04 a4 FCB $80+'$' +0671 de05 52 49 47 48 54 FCC "RIGHT" 96 +0672 de0a a4 FCB $80+'$' +0673 de0b 4d 49 44 FCC "MID" 97 +0674 de0e a4 FCB $80+'$' +0675 * REMAINING FUNCTIONS +0676 de0f 49 4e 4b 45 59 FCC "INKEY" 98 +0677 de14 a4 FCB $80+'$' +0678 de15 4d 45 FCC "ME" 99 +0679 de17 cd FCB $80+'M' +0680 de18 56 41 52 50 54 FCC "VARPT" 9A +0681 de1d d2 FCB $80+'R' +0682 de1e 49 4e 53 54 FCC "INST" 9B +0683 de22 d2 FCB $80+'R' +0684 de23 53 54 52 49 4e 47 FCC "STRING" 9C +0685 de29 a4 FCB $80+'$' +0686 +0687 * +0688 * DISPATCH TABLE FOR COMMANDS TOKEN # +0689 CMD_TAB +0690 de2a df e8 LAB67 FDB FOR 80 +0691 de2c e1 33 FDB GO 81 +0692 de2e e1 90 FDB REM 82 +0693 0082 TOK_REM EQU *-CMD_TAB/2+$7F +0694 de30 e1 90 FDB REM 83 (') +0695 0083 TOK_SNGL_Q EQU *-CMD_TAB/2+$7F +0696 de32 e1 90 FDB REM 84 (ELSE) +0697 0084 TOK_ELSE EQU *-CMD_TAB/2+$7F +0698 de34 e1 c1 FDB IF 85 +0699 0085 TOK_IF EQU *-CMD_TAB/2+$7F +0700 de36 e1 8d FDB DATA 86 +0701 0086 TOK_DATA EQU *-CMD_TAB/2+$7F +0702 de38 eb 6a FDB PRINT 87 +0703 0087 TOK_PRINT EQU *-CMD_TAB/2+$7F +0704 de3a e1 ef FDB ON 88 +0705 de3c e2 9c FDB INPUT 89 +0706 0089 TOK_INPUT EQU *-CMD_TAB/2+$7F +0707 de3e e0 ba FDB END 8A +0708 de40 e3 81 FDB NEXT 8B +0709 de42 e5 d2 FDB DIM 8C +0710 de44 e2 d6 FDB READ 8D +0711 de46 e1 28 FDB RUN 8E +0712 de48 e0 9c FDB RESTOR 8F +0713 de4a e1 6d FDB RETURN 90 +0714 de4c e0 be FDB STOP 91 +0715 de4e e9 db FDB POKE 92 +0716 de50 e0 e3 FDB CONT 93 +0717 de52 e9 e2 FDB LIST 94 +0718 de54 e0 f4 FDB CLEAR 95 +0719 de56 df b8 FDB NEW 96 +0720 de58 dc 8c FDB EXEC 97 +0721 de5a f5 64 FDB TRON 98 +0722 de5c f5 65 FDB TROFF 99 +0723 de5e f7 e0 FDB DEL 9A +0724 de60 f7 24 FDB DEF 9B +0725 de62 fe ce FDB LINE 9C +0726 de64 f8 6a FDB RENUM 9D +0727 de66 f3 f0 FDB EDIT 9E +0728 009e TOK_HIGH_EXEC EQU *-CMD_TAB/2+$7F +0729 +0730 * ERROR MESSAGES AND THEIR NUMBERS AS USED INTERNALLY +0731 de68 4e 46 LABAF FCC "NF" 0 NEXT WITHOUT FOR +0732 de6a 53 4e FCC "SN" 1 SYNTAX ERROR +0733 de6c 52 47 FCC "RG" 2 RETURN WITHOUT GOSUB +0734 de6e 4f 44 FCC "OD" 3 OUT OF DATA +0735 de70 46 43 FCC "FC" 4 ILLEGAL FUNCTION CALL +0736 de72 4f 56 FCC "OV" 5 OVERFLOW +0737 de74 4f 4d FCC "OM" 6 OUT OF MEMORY +0738 de76 55 4c FCC "UL" 7 UNDEFINED LINE NUMBER +0739 de78 42 53 FCC "BS" 8 BAD SUBSCRIPT +0740 de7a 44 44 FCC "DD" 9 REDIMENSIONED ARRAY +0741 de7c 2f 30 FCC "/0" 10 DIVISION BY ZERO +0742 de7e 49 44 FCC "ID" 11 ILLEGAL DIRECT STATEMENT +0743 de80 54 4d FCC "TM" 12 TYPE MISMATCH +0744 de82 4f 53 FCC "OS" 13 OUT OF STRING SPACE +0745 de84 4c 53 FCC "LS" 14 STRING TOO LONG +0746 de86 53 54 FCC "ST" 15 STRING FORMULA TOO COMPLEX +0747 de88 43 4e FCC "CN" 16 CAN'T CONTINUE +0748 de8a 46 44 FCC "FD" 17 BAD FILE DATA +0749 de8c 41 4f FCC "AO" 18 FILE ALREADY OPEN +0750 de8e 44 4e FCC "DN" 19 DEVICE NUMBER ERROR +0751 de90 49 4f FCC "IO" 20 I/O ERROR +0752 de92 46 4d FCC "FM" 21 BAD FILE MODE +0753 de94 4e 4f FCC "NO" 22 FILE NOT OPEN +0754 de96 49 45 FCC "IE" 23 INPUT PAST END OF FILE +0755 de98 44 53 FCC "DS" 24 DIRECT STATEMENT IN FILE +0756 * ADDITIONAL ERROR MESSAGES ADDED BY EXTENDED BASIC +0757 de9a 55 46 L890B FCC "UF" 25 UNDEFINED FUNCTION (FN) CALL +0758 de9c 4e 45 L890D FCC "NE" 26 FILE NOT FOUND +0759 +0760 de9e 20 45 52 52 4f 52 LABE1 FCC " ERROR" +0761 dea4 00 FCB $00 +0762 dea5 20 49 4e 20 LABE8 FCC " IN " +0763 dea9 00 FCB $00 +0764 deaa 0d LABED FCB CR +0765 deab 4f 4b LABEE FCC "OK" +0766 dead 0d 00 FCB CR,$00 +0767 deaf 0d LABF2 FCB CR +0768 deb0 42 52 45 41 4b FCC "BREAK" +0769 deb5 00 FCB $00 +0770 +0771 * SEARCH THE STACK FOR ‘GOSUB/RETURN’ OR ‘FOR/NEXT’ DATA. +0772 * THE ‘FOR/NEXT’ INDEX VARIABLE DESCRIPTOR ADDRESS BEING +0773 * SOUGHT IS STORED IN VARDES. EACH BLOCK OF FOR/NEXT DATA IS 18 +0774 * BYTES WITH A $80 LEADER BYTE AND THE GOSUB/RETURN DATA IS 5 BYTES +0775 * WITH AN $A6 LEADER BYTE. THE FIRST NON "FOR/NEXT" DATA +0776 * IS CONSIDERED ‘GOSUB/RETURN’ +0777 deb6 30 64 LABF9 LEAX 4,S POINT X TO 3RD ADDRESS ON STACK - IGNORE THE +0778 * FIRST TWO RETURN ADDRESSES ON THE STACK +0779 deb8 c6 12 LABFB LDB #18 18 BYTES SAVED ON STACK FOR EACH ‘FOR’ LOOP +0780 deba 9f 0f STX TEMPTR SAVE POINTER +0781 debc a6 84 LDA ,X GET 1ST BYTE +0782 debe 80 80 SUBA #$80 * CHECK FOR TYPE OF STACK JUMP FOUND +0783 dec0 26 15 BNE LAC1A * BRANCH IF NOT ‘FOR/NEXT’ +0784 dec2 ae 01 LDX 1,X = GET INDEX VARIABLE DESCRIPTOR +0785 dec4 9f 11 STX TMPTR1 = POINTER AND SAVE IT IN TMPTR1 +0786 dec6 9e 3b LDX VARDES GET INDEX VARIABLE BEING SEARCHED FOR +0787 dec8 27 09 BEQ LAC16 BRANCH IF DEFAULT INDEX VARIABLE - USE THE +0788 * FIRST ‘FOR/NEXT’ DATA FOUND ON STACK +0789 * IF NO INDEX VARIABLE AFTER ‘NEXT’ +0790 deca 9c 11 CMPX TMPTR1 DOES THE STACK INDEX MATCH THE ONE +0791 * BEING SEARCHED FOR? +0792 decc 27 09 BEQ LAC1A YES +0793 dece 9e 0f LDX TEMPTR * RESTORE INITIAL POINTER, ADD +0794 ded0 3a ABX * 18 TO IT AND LOOK FOR +0795 ded1 20 e5 BRA LABFB * NEXT BLOCK OF DATA +0796 ded3 9e 11 LAC16 LDX TMPTR1 = GET 1ST INDEX VARIABLE FOUND AND +0797 ded5 9f 3b STX VARDES = SAVE AS ‘NEXT’ INDEX +0798 ded7 9e 0f LAC1A LDX TEMPTR POINT X TO START OF ‘FOR/NEXT’ DATA +0799 ded9 4d TSTA SET ZERO FLAG IF ‘FOR/NEXT’ DATA +0800 deda 39 RTS +0801 * CHECK FOR MEMORY SPACE FOR NEW TOP OF +0802 * ARRAYS AND MOVE ARRAYS TO NEW LOCATION +0803 dedb 8d 17 LAC1E BSR LAC37 ACCD = NEW BOTTOM OF FREE RAM - IS THERE +0804 * ROOM FOR THE STACK? +0805 * MOVE BYTES FROM V43(X) TO V41(U) UNTIL (X) = V47 AND +0806 * SAVE FINAL VALUE OF U IN V45 +0807 dedd de 41 LAC20 LDU V41 POINT U TO DESTINATION ADDRESS (V41) +0808 dedf 33 41 LEAU 1,U ADD ONE TO U - COMPENSATE FOR FIRST PSHU +0809 dee1 9e 43 LDX V43 POINT X TO SOURCE ADDRESS (V43) +0810 dee3 30 01 LEAX 1,X ADD ONE - COMPENSATE FOR FIRST LDA ,X +0811 dee5 a6 82 LAC28 LDA ,-X GRAB A BYTE FROM SOURCE +0812 dee7 36 02 PSHU A MOVE IT TO DESTINATION +0813 dee9 9c 47 CMPX V47 DONE? +0814 deeb 26 f8 BNE LAC28 NO - KEEP MOVING BYTES +0815 deed df 45 STU V45 SAVE FINAL DESTINATION ADDRESS +0816 deef 39 LAC32 RTS +0817 * CHECK TO SEE IF THERE IS ROOM TO STORE 2*ACCB +0818 * BYTES IN FREE RAM - OM ERROR IF NOT +0819 def0 4f LAC33 CLRA * ACCD CONTAINS NUMBER OF EXTRA +0820 def1 58 ASLB * BYTES TO PUT ON STACK +0821 def2 d3 1f ADDD ARYEND END OF PROGRAM AND VARIABLES +0822 def4 c3 00 3a LAC37 ADDD #STKBUF ADD STACK BUFFER - ROOM FOR STACK? +0823 def7 25 08 BCS LAC44 BRANCH IF GREATER THAN $FFFF +0824 def9 10 df 17 STS BOTSTK CURRENT NEW BOTTOM OF STACK STACK POINTER +0825 defc 10 93 17 CMPD BOTSTK ARE WE GOING TO BE BELOW STACK? +0826 deff 25 ee BCS LAC32 YES - NO ERROR +0827 df01 c6 0c LAC44 LDB #6*2 OUT OF MEMORY ERROR +0828 +0829 * ERROR SERVICING ROUTINE +0830 df03 bd df d4 LAC46 JSR LAD33 RESET STACK, STRING STACK, CONTINUE POINTER +0831 df06 bd eb a9 JSR LB95C SEND A CR TO SCREEN +0832 df09 bd eb f8 JSR LB9AF SEND A ‘?‘ TO SCREEN +0833 df0c 8e de 68 LDX #LABAF POINT TO ERROR TABLE +0834 df0f 3a LAC60 ABX ADD MESSAGE NUMBER OFFSET +0835 df10 8d 31 BSR LACA0 * GET TWO CHARACTERS FROM X AND +0836 df12 8d 2f BSR LACA0 * SEND TO CONSOLE OUT (SCREEN) +0837 df14 8e de 9d LDX #LABE1-1 POINT TO "ERROR" MESSAGE +0838 df17 bd eb e5 LAC68 JSR LB99C PRINT MESSAGE POINTED TO BY X +0839 df1a 96 68 LDA CURLIN GET CURRENT LINE NUMBER (CURL IN) +0840 df1c 4c INCA TEST FOR DIRECT MODE +0841 df1d 27 03 BEQ LAC73 BRANCH IF DIRECT MODE +0842 df1f bd f0 0e JSR LBDC5 PRINT ‘IN ****‘ +0843 +0844 * THIS IS THE MAIN LOOP OF BASIC WHEN IN DIRECT MODE +0845 df22 bd eb a9 LAC73 JSR LB95C MOVE CURSOR TO START OF LINE +0846 df25 8e de aa LDX #LABED POINT X TO ‘OK’, CR MESSAGE +0847 df28 bd eb e5 JSR LB99C PRINT ‘OK’, CR +0848 df2b bd dc 3e LAC7C JSR LA390 GO GET AN INPUT LINE +0849 df2e ce ff ff LDU #$FFFF THE LINE NUMBER FOR DIRECT MODE IS $FFFF +0850 df31 df 68 STU CURLIN SAVE IT IN CURLIN +0851 df33 25 f6 BCS LAC7C BRANCH IF LINE INPUT TERMINATED BY BREAK +0852 df35 9f 83 STX CHARAD SAVE (X) AS CURRENT INPUT POINTER - THIS WILL +0853 * ENABLE THE ‘LIVE KEYBOARD’ (DIRECT) MODE. THE +0854 * LINE JUST ENTERED WILL BE INTERPRETED +0855 df37 9d 7c JSR GETNCH GET NEXT CHARACTER FROM BASIC +0856 df39 27 f0 BEQ LAC7C NO LINE INPUT - GET ANOTHER LINE +0857 df3b 25 0b BCS LACA5 BRANCH IF NUMER1C - THERE WAS A LINE NUMBER BEFORE +0858 * THE STATEMENT ENTERED, SO THIS STATEMENT +0859 * WILL BE MERGED INTO THE BASIC PROGRAM +0860 df3d bd ea 97 JSR LB821 GO CRUNCH LINE +0861 df40 7e e0 71 JMP LADC0 GO EXECUTE THE STATEMENT (LIVE KEYBOARD) +0862 * +0863 df43 a6 80 LACA0 LDA ,X+ GET A CHARACTER +0864 df45 7e eb fa JMP LB9B1 SEND TO CONSOLE OUT +0865 * TAKE A LINE FROM THE LINE INPUT BUFFER +0866 * AND INSERT IT INTO THE BASIC PROGRAM +0867 df48 bd e2 14 LACA5 JSR LAF67 CONVERT LINE NUMBER TO BINARY +0868 df4b 9e 2b LACA8 LDX BINVAL GET CONVERTED LINE NUMBER +0869 df4d 9f f1 STX LINHDR STORE IT IN LINE INPUT HEADER +0870 df4f bd ea 97 JSR LB821 GO CRUNCH THE LINE +0871 df52 d7 03 STB TMPLOC SAVE LINE LENGTH +0872 df54 8d 4c BSR LAD01 FIND OUT WHERE TO INSERT LINE +0873 df56 25 12 BCS LACC8 BRANCH IF LINE NUMBER DOES NOT ALREADY EXIST +0874 df58 dc 47 LDD V47 GET ABSOLUTE ADDRESS OF LINE NUMBER +0875 df5a a3 84 SUBD ,X SUBTRACT ADDRESS OF NEXT LINE NUMBER +0876 df5c d3 1b ADDD VARTAB * ADD TO CURRENT END OF PROGRAM - THIS WILL REMOVE +0877 df5e dd 1b STD VARTAB * THE LENGTH OF THIS LINE NUMBER FROM THE PROGRAM +0878 df60 ee 84 LDU ,X POINT U TO ADDRESS OF NEXT LINE NUMBER +0879 * DELETE OLD LINE FROM BASIC PROGRAM +0880 df62 37 02 LACC0 PULU A GET A BYTE FROM WHAT’S LEFT OF PROGRAM +0881 df64 a7 80 STA ,X+ MOVE IT DOWN +0882 df66 9c 1b CMPX VARTAB COMPARE TO END OF BASIC PROGRAM +0883 df68 26 f8 BNE LACC0 BRANCH IF NOT AT END +0884 df6a 96 f3 LACC8 LDA LINBUF * CHECK TO SEE IF THERE IS A LINE IN +0885 df6c 27 1c BEQ LACE9 * THE BUFFER AND BRANCH IF NONE +0886 df6e dc 1b LDD VARTAB = SAVE CURRENT END OF +0887 df70 dd 43 STD V43 = PROGRAM IN V43 +0888 df72 db 03 ADDB TMPLOC * ADD LENGTH OF CRUNCHED LINE, +0889 df74 89 00 ADCA #0 * PROPOGATE CARRY AND SAVE NEW END +0890 df76 dd 41 STD V41 * OF PROGRAM IN V41 +0891 df78 bd de db JSR LAC1E = MAKE SURE THERE’S ENOUGH RAM FOR THIS +0892 * = LINE & MAKE A HOLE IN BASIC FOR NEW LINE +0893 df7b ce 00 ef LDU #LINHDR-2 POINT U TO LINE TO BE INSERTED +0894 df7e 37 02 LACDD PULU A GET A BYTE FROM NEW LINE +0895 df80 a7 80 STA ,X+ INSERT IT IN PROGRAM +0896 df82 9c 45 CMPX V45 * COMPARE TO ADDRESS OF END OF INSERTED +0897 df84 26 f8 BNE LACDD * LINE AND BRANCH IF NOT DONE +0898 df86 9e 41 LDX V41 = GET AND SAVE +0899 df88 9f 1b STX VARTAB = END OF PROGRAM +0900 df8a 8d 36 LACE9 BSR LAD21 RESET INPUT POINTER, CLEAR VARIABLES, INITIALIZE +0901 df8c 8d 02 BSR LACEF ADJUST START OF NEXT LINE ADDRESSES +0902 df8e 20 9b BRA LAC7C REENTER BASIC’S INPUT LOOP +0903 * COMPUTE THE START OF NEXT LINE ADDRESSES FOR THE BASIC PROGRAM +0904 df90 9e 19 LACEF LDX TXTTAB POINT X TO START OF PROGRAM +0905 df92 ec 84 LACF1 LDD ,X GET ADDRESS OF NEXT LINE +0906 df94 27 21 BEQ LAD16 RETURN IF END OF PROGRAM +0907 df96 33 04 LEAU 4,X POINT U TO START OF BASIC TEXT IN LINE +0908 df98 a6 c0 LACF7 LDA ,U+ * SKIP THROUGH THE LINE UNTIL A +0909 df9a 26 fc BNE LACF7 * ZERO (END OF LINE) IS FOUND +0910 df9c ef 84 STU ,X SAVE THE NEW START OF NEXT LINE ADDRESS +0911 df9e ae 84 LDX ,X POINT X TO START OF NEXT LINE +0912 dfa0 20 f0 BRA LACF1 KEEP GOING +0913 * +0914 * FIND A LINE NUMBER IN THE BASIC PROGRAM +0915 * RETURN WITH CARRY SET IF NO MATCH FOUND +0916 dfa2 dc 2b LAD01 LDD BINVAL GET THE LINE NUMBER TO FIND +0917 dfa4 9e 19 LDX TXTTAB BEGINNING OF PROGRAM +0918 dfa6 ee 84 LAD05 LDU ,X GET ADDRESS OF NEXT LINE NUMBER +0919 dfa8 27 09 BEQ LAD12 BRANCH IF END OF PROG +0920 dfaa 10 a3 02 CMPD 2,X IS IT A MATCH? +0921 dfad 23 06 BLS LAD14 CARRY SET IF LOWER; CARRY CLEAR IF MATCH +0922 dfaf ae 84 LDX ,X X = ADDRESS OF NEXT LINE +0923 dfb1 20 f3 BRA LAD05 KEEP LOOPING FOR LINE NUMBER +0924 dfb3 1a 01 LAD12 ORCC #1 SET CARRY FLAG +0925 dfb5 9f 47 LAD14 STX V47 SAVE MATCH LINE NUMBER OR NUMBER OF LINE JUST AFTER +0926 * WHERE IT SHOULD HAVE BEEN +0927 dfb7 39 LAD16 RTS +0928 +0929 * NEW +0930 dfb8 26 fb NEW BNE LAD14 BRANCH IF ARGUMENT GIVEN +0931 dfba 9e 19 LAD19 LDX TXTTAB GET START OF BASIC +0932 dfbc 6f 80 CLR ,X+ * PUT 2 ZERO BYTES THERE - ERASE +0933 dfbe 6f 80 CLR ,X+ * THE BASIC PROGRAM +0934 dfc0 9f 1b STX VARTAB AND THE NEXT ADDRESS IS NOW THE END OF PROGRAM +0935 dfc2 9e 19 LAD21 LDX TXTTAB GET START OF BASIC +0936 dfc4 bd e1 68 JSR LAEBB PUT INPUT POINTER ONE BEFORE START OF BASIC +0937 * ERASE ALL VARIABLES +0938 dfc7 9e 27 LAD26 LDX MEMSIZ * RESET START OF STRING VARIABLES +0939 dfc9 9f 23 STX STRTAB * TO TOP OF STRING SPACE +0940 dfcb bd e0 9c JSR RESTOR RESET ‘DATA’ POINTER TO START OF BASIC +0941 dfce 9e 1b LDX VARTAB * GET START OF VARIABLES AND USE IT +0942 dfd0 9f 1d STX ARYTAB * TO RESET START OF ARRAYS +0943 dfd2 9f 1f STX ARYEND RESET END OF ARRAYS +0944 dfd4 8e 00 c9 LAD33 LDX #STRSTK * RESET STRING STACK POINTER TO +0945 dfd7 9f 0b STX TEMPPT * BOTTOM OF STRING STACK +0946 dfd9 ae e4 LDX ,S GET RETURN ADDRESS OFF STACK +0947 dfdb 10 de 21 LDS FRETOP RESTORE STACK POINTER +0948 dfde 6f e2 CLR ,-S PUT A ZERO BYTE ON STACK - TO CLEAR ANY RETURN OF +0949 * FOR/NEXT DATA FROM THE STACK +0950 dfe0 0f 2d CLR OLDPTR RESET ‘CONT’ ADDRESS SO YOU +0951 dfe2 0f 2e CLR OLDPTR+1 ‘CAN’T CONTINUE’ +0952 dfe4 0f 08 CLR ARYDIS CLEAR THE ARRAY DISABLE FLAG +0953 dfe6 6e 84 JMP ,X RETURN TO CALLING ROUTINE - THIS IS NECESSARY +0954 * SINCE THE STACK WAS RESET +0955 * +0956 * FOR +0957 * +0958 * THE FOR COMMAND WILL STORE 18 BYTES ON THE STACK FOR +0959 * EACH FOR-NEXT LOOP WHICH IS BEING PROCESSED. THESE +0960 * BYTES ARE DEFINED AS FOLLOWS: 0- $80 (FOR FLAG); +0961 * 1,2=INDEX VARIABLE DESCRIPTOR POINTER; 3-7=FP VALUE OF STEP; +0962 * 8=STEP DIRECTION: $FF IF NEGATIVE; 0 IF ZERO; 1 IF POSITIVE; +0963 * 9-13=FP VALUE OF ‘TO’ PARAMETER; +0964 * 14,15=CURRENT LINE NUMBER; 16,17=RAM ADDRESS OF THE END +0965 * OF THE LINE CONTAINING THE ‘FOR’ STATEMENT +0966 dfe8 86 80 FOR LDA #$80 * SAVE THE DISABLE ARRAY FLAG IN VO8 +0967 dfea 97 08 STA ARYDIS * DO NOT ALLOW THE INDEX VARIABLE TO BE AN ARRAY +0968 dfec bd e2 36 JSR LET SET INDEX VARIABLE TO INITIAL VALUE +0969 dfef bd de b6 JSR LABF9 SEARCH THE STACK FOR ‘FOR/NEXT’ DATA +0970 dff2 32 62 LEAS 2,S PURGE RETURN ADDRESS OFF OF THE STACK +0971 dff4 26 04 BNE LAD59 BRANCH IF INDEX VARIABLE NOT ALREADY BEING USED +0972 dff6 9e 0f LDX TEMPTR GET (ADDRESS + 18) OF MATCHED ‘FOR/NEXT’ DATA +0973 dff8 32 85 LEAS B,X MOVE THE STACK POINTER TO THE BEGINNING OF THE +0974 * MATCHED ‘FOR/NEXT’ DATA SO THE NEW DATA WILL +0975 * OVERLAY THE OLD DATA. THIS WILL ALSO DESTROY +0976 * ALL OF THE ‘RETURN’ AND ‘FOR/NEXT’ DATA BELOW +0977 * THIS POINT ON THE STACK +0978 dffa c6 09 LAD59 LDB #$09 * CHECK FOR ROOM FOR 18 BYTES +0979 dffc bd de f0 JSR LAC33 * IN FREE RAM +0980 dfff bd e1 95 JSR LAEE8 GET ADDR OF END OF SUBLINE IN X +0981 e002 dc 68 LDD CURLIN GET CURRENT LINE NUMBER +0982 e004 34 16 PSHS X,B,A SAVE LINE ADDR AND LINE NUMBER ON STACK +0983 e006 c6 a0 LDB #TOK_TO TOKEN FOR ‘TO’ +0984 e008 bd e4 f8 JSR LB26F SYNTAX CHECK FOR ‘TO’ +0985 e00b bd e3 cc JSR LB143 ‘TM’ ERROR IF INDEX VARIABLE SET TO STRING +0986 e00e bd e3 ca JSR LB141 EVALUATE EXPRESSION +0987 * +0988 e011 d6 54 LDB FP0SGN GET FPA0 MANTISSA SIGN +0989 e013 ca 7f ORB #$7F FORM A MASK TO SAVE DATA BITS OF HIGH ORDER MANTISSA +0990 e015 d4 50 ANDB FPA0 PUT THE MANTISSA SIGN IN BIT 7 OF HIGH ORDER MANTISSA +0991 e017 d7 50 STB FPA0 SAVE THE PACKED HIGH ORDER MANTISSA +0992 e019 10 8e e0 20 LDY #LAD7F LOAD FOLLOWING ADDRESS INTO Y AS A RETURN +0993 e01d 7e e4 73 JMP LB1EA ADDRESS - PUSH FPA0 ONTO THE STACK +0994 e020 8e ed 0e LAD7F LDX #LBAC5 POINT X TO FLOATING POINT NUMBER 1.0 (DEFAULT STEP VALUE) +0995 e023 bd ee 5d JSR LBC14 MOVE (X) TO FPA0 +0996 e026 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +0997 e028 81 a4 CMPA #TOK_STEP STEP TOKEN +0998 e02a 26 05 BNE LAD90 BRANCH IF NO ‘STEP’ VALUE +0999 e02c 9d 7c JSR GETNCH GET A CHARACTER FROM BASIC +1000 e02e bd e3 ca JSR LB141 EVALUATE NUMERIC EXPRESSION +1001 e031 bd ee b6 LAD90 JSR LBC6D CHECK STATUS OF FPA0 +1002 e034 bd e4 6f JSR LB1E6 SAVE STATUS AND FPA0 ON THE STACK +1003 e037 dc 3b LDD VARDES * GET DESCRIPTOR POINTER FOR THE ‘STEP’ +1004 e039 34 06 PSHS B,A * VARIABLE AND SAVE IT ON THE STACK +1005 e03b 86 80 LDA #$80 = GET THE ‘FOR’ FLAG AND +1006 e03d 34 02 PSHS A = SAVE IT ON THE STACK +1007 * +1008 * MAIN COMMAND INTERPRETATION LOOP +1009 e03f 1c af LAD9E ANDCC #$AF ENABLE IRQ,FIRQ +1010 e041 8d 60 BSR LADEB CHECK FOR KEYBOARD BREAK +1011 e043 9e 83 LDX CHARAD GET BASIC’S INPUT POINTER +1012 e045 9f 2f STX TINPTR SAVE IT +1013 e047 a6 80 LDA ,X+ GET CURRENT INPUT CHAR & MOVE POINTER +1014 e049 27 07 BEQ LADB4 BRANCH IF END OF LINE +1015 e04b 81 3a CMPA #': CHECK FOR LINE SEPARATOR +1016 e04d 27 22 BEQ LADC0 BRANCH IF COLON +1017 e04f 7e e5 00 LADB1 JMP LB277 ‘SYNTAX ERROR’-IF NOT LINE SEPARATOR +1018 e052 a6 81 LADB4 LDA ,X++ GET MS BYTE OF ADDRESS OF NEXT BASIC LINE +1019 e054 97 00 STA ENDFLG SAVE IN STOP/END FLAG - CAUSE A STOP IF +1020 * NEXT LINE ADDRESS IS < $8000; CAUSE +1021 * AN END IF ADDRESS > $8000 +1022 e056 27 72 BEQ LAE15 BRANCH TO ‘STOP’ - END OF PROGRAM +1023 e058 ec 80 LDD ,X+ GET CURRENT LINE NUMBER +1024 e05a dd 68 STD CURLIN SAVE IN CURLIN +1025 e05c 9f 83 STX CHARAD SAVE ADDRESS OF FIRST BYTE OF LINE +1026 * EXTENDED BASIC TRACE +1027 e05e 96 8c LDA TRCFLG TEST THE TRACE FLAG +1028 e060 27 0f BEQ LADC0 BRANCH IF TRACE OFF +1029 e062 86 5b LDA #$5B RIGHT HAND MARKER FOR TRON LINE NUMBER +1034 e06e bd db 14 JSR PUTCHR OUTPUT A CHARACTER +1035 * END OF EXTENDED BASIC TRACE +1036 e071 9d 7c LADC0 JSR GETNCH GET A CHARACTER FROM BASIC +1037 e073 8d 02 BSR LADC6 GO PROCESS COMMAND +1038 e075 20 c8 BRA LAD9E GO BACK TO MAIN LOOP +1039 e077 27 29 LADC6 BEQ LADEA RETURN IF END OF LINE (RTS - was BEQ LAE40) +1040 e079 4d TSTA CHECK FOR TOKEN - BIT 7 SET (NEGATIVE) +1041 e07a 10 2a 01 b8 LBPL LET BRANCH IF NOT A TOKEN - GO DO A ‘LET’ WHICH +1042 * IS THE ‘DEFAULT’ TOKEN FOR MICROSOFT BASIC +1043 e07e 81 ff CMPA #$FF SECONDARY TOKEN +1044 e080 27 0f BEQ SECTOK +1045 e082 81 9e CMPA #TOK_HIGH_EXEC SKIPF TOKEN - HIGHEST EXECUTABLE COMMAND IN BASIC +1046 e084 22 c9 BHI LADB1 ‘SYNTAX ERROR’ IF NON-EXECUTABLE TOKEN +1047 e086 be db f1 LDX COMVEC+3 GET ADDRESS OF BASIC’S COMMAND TABLE +1048 e089 48 LADD4 ASLA X2 (2 BYTE/JUMP ADDRESS) & DISCARD BIT 7 +1049 e08a 1f 89 TFR A,B SAVE COMMAND OFFSET IN ACCB +1050 e08c 3a ABX NON X POINTS TO COMMAND JUMP ADDR +1051 e08d 9d 7c JSR GETNCH GET AN INPUT CHAR +1052 * +1053 * HERE IS WHERE WE BRANCH TO DO A ‘COMMAND’ +1054 e08f 6e 94 JMP [,X] GO DO A COMMAND +1055 SECTOK +1056 * THE ONLY SECONDARY TOKEN THAT CAN ALSO BE AN EXECUTABLE IS +1057 * THE MID$ REPLACEMENT STATEMENT. SO SPECIAL-CASE CHECK DONE HERE +1058 e091 9d 7c JSR GETNCH GET AN INPUT CHAR +1059 e093 81 97 CMPA #TOK_MID TOKEN FOR "MID$" +1060 e095 10 27 14 f0 LBEQ L86D6 PROCESS MID$ REPLACEMENT +1061 e099 7e e5 00 JMP LB277 SYNTAX ERROR +1062 +1063 * +1064 * RESTORE +1065 e09c 9e 19 RESTOR LDX TXTTAB BEGINNING OF PROGRAM ADDRESS +1066 e09e 30 1f LEAX -1,X MOVE TO ONE BYTE BEFORE PROGRAM +1067 e0a0 9f 33 LADE8 STX DATPTR SAVE NEW DATA POINTER +1068 e0a2 39 LADEA RTS +1069 * +1070 * BREAK CHECK +1071 e0a3 bd db 05 LADEB JSR LA1C1 GET A KEYSTROKE ENTRY +1072 e0a6 27 0a BEQ LADFA RETURN IF NO INPUT +1073 e0a8 81 03 LADF0 CMPA #3 CONTROL C? (BREAK) +1074 e0aa 27 12 BEQ STOP YES +1075 e0ac 81 13 CMPA #$13 CONTROL S? (PAUSE) +1076 e0ae 27 03 BEQ LADFB YES +1077 e0b0 97 73 STA IKEYIM SAVE KEYSTROKE IN INKEY IMAGE +1078 e0b2 39 LADFA RTS +1079 e0b3 bd db 05 LADFB JSR KEYIN GET A KEY +1080 e0b6 27 fb BEQ LADFB BRANCH IF NO KEY DOWN +1081 e0b8 20 ee BRA LADF0 CONTINUE - DO A BREAK CHECK +1082 * +1083 * END +1084 e0ba 9d 82 END JSR GETCCH GET CURRENT INPUT CHAR +1085 e0bc 20 02 BRA LAE0B +1086 * +1087 * STOP +1088 e0be 1a 01 STOP ORCC #$01 SET CARRY FLAG +1089 e0c0 26 31 LAE0B BNE LAE40 BRANCH IF ARGUMENT EXISTS +1090 e0c2 9e 83 LDX CHARAD * SAVE CURRENT POSITION OF +1091 e0c4 9f 2f STX TINPTR * BASIC’S INPUT POINTER +1092 e0c6 06 00 LAE11 ROR ENDFLG ROTATE CARRY INTO BIT 7 OF STOP/END FLAG +1093 e0c8 32 62 LEAS 2,S PURGE RETURN ADDRESS OFF STACK +1094 e0ca 9e 68 LAE15 LDX CURLIN GET CURRENT LINE NUMBER +1095 e0cc 8c ff ff CMPX #$FFFF DIRECT MODE? +1096 e0cf 27 06 BEQ LAE22 YES +1097 e0d1 9f 29 STX OLDTXT SAVE CURRENT LINE NUMBER +1098 e0d3 9e 2f LDX TINPTR * GET AND SAVE CURRENT POSITION +1099 e0d5 9f 2d STX OLDPTR * OF BASIC’S INPUT POINTER +1100 LAE22 +1101 e0d7 8e de ae LDX #LABF2-1 POINT TO CR, ‘BREAK’ MESSAGE +1102 e0da 0d 00 TST ENDFLG CHECK STOP/END FLAG +1103 e0dc 10 2a fe 42 LBPL LAC73 BRANCH TO MAIN LOOP OF BASIC IF END +1104 e0e0 7e df 17 JMP LAC68 PRINT ‘BREAK AT ####’ AND GO TO +1105 * BASIC’S MAIN LOOP IF ‘STOP’ +1106 +1107 * CONT +1108 e0e3 26 0e CONT BNE LAE40 RETURN IF ARGUMENT GIVEN +1109 e0e5 c6 20 LDB #2*16 ‘CAN’T CONTINUE’ ERROR +1110 e0e7 9e 2d LDX OLDPTR GET CONTINUE ADDRESS (INPUT POINTER) +1111 e0e9 10 27 fe 16 LBEQ LAC46 ‘CN’ ERROR IF CONTINUE ADDRESS = 0 +1112 e0ed 9f 83 STX CHARAD RESET BASIC’S INPUT POINTER +1113 e0ef 9e 29 LDX OLDTXT GET LINE NUMBER +1114 e0f1 9f 68 STX CURLIN RESET CURRENT LINE NUMBER +1115 e0f3 39 LAE40 RTS +1116 * +1117 * CLEAR +1118 e0f4 27 2c CLEAR BEQ LAE6F BRANCH IF NO ARGUMENT +1119 e0f6 bd e6 6a JSR LB3E6 EVALUATE ARGUMENT +1120 e0f9 34 06 PSHS B,A SAVE AMOUNT OF STRING SPACE ON STACK +1121 e0fb 9e 27 LDX MEMSIZ GET CURRENT TOP OF CLEARED SPACE +1122 e0fd 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +1123 e0ff 27 0c BEQ LAE5A BRANCH IF NO NEW TOP OF CLEARED SPACE +1124 e101 bd e4 f6 JSR LB26D SYNTAX CHECK FOR COMMA +1125 e104 bd e9 c1 JSR LB73D EVALUATE EXPRESSlON; RETURN VALUE IN X +1126 e107 30 1f LEAX -1,X X = TOP OF CLEARED SPACE +1127 e109 9c 71 CMPX TOPRAM COMPARE TO TOP OF RAM +1128 e10b 22 18 BHI LAE72 ‘OM’ ERROR IF > TOP OF RAM +1129 e10d 1f 10 LAE5A TFR X,D ACCD = TOP OF CLEARED SPACE +1130 e10f a3 e1 SUBD ,S++ SUBTRACT OUT AMOUNT OF CLEARED SPACE +1131 e111 25 12 BCS LAE72 ‘OM’ ERROR IF FREE MEM < 0 +1132 e113 1f 03 TFR D,U U = BOTTOM OF CLEARED SPACE +1133 e115 83 00 3a SUBD #STKBUF SUBTRACT OUT STACK BUFFER +1134 e118 25 0b BCS LAE72 ‘OM’ ERROR IF FREE MEM < 0 +1135 e11a 93 1b SUBD VARTAB SUBTRACT OUT START OF VARIABLES +1136 e11c 25 07 BCS LAE72 ‘OM’ ERROR IF FREE MEM < 0 +1137 e11e df 21 STU FRETOP SAVE NEW BOTTOM OF CLEARED SPACE +1138 e120 9f 27 STX MEMSIZ SAVE NEW TOP OF CLEARED SPACE +1139 e122 7e df c7 LAE6F JMP LAD26 ERASE ALL VARIABLES, INITIALIZE POINTERS, ETC +1140 e125 7e df 01 LAE72 JMP LAC44 ‘OM’ ERROR +1141 * +1142 * RUN +1143 e128 9d 82 RUN JSR GETCCH * GET CURRENT INPUT CHARACTER +1144 e12a 10 27 fe 94 LBEQ LAD21 * IF NO LINE NUMBER +1145 e12e bd df c7 JSR LAD26 ERASE ALL VARIABLES +1146 e131 20 19 BRA LAE9F ‘GOTO’ THE RUN ADDRESS +1147 * +1148 * GO +1149 e133 1f 89 GO TFR A,B SAVE INPUT CHARACTER IN ACCB +1150 e135 9d 7c LAE88 JSR GETNCH GET A CHARACTER FROM BASIC +1151 e137 c1 a0 CMPB #TOK_TO ‘TO’ TOKEN +1152 e139 27 16 BEQ LAEA4 BRANCH IF GOTO +1153 e13b c1 a1 CMPB #TOK_SUB ‘SUB’ TOKEN +1154 e13d 26 45 BNE LAED7 ‘SYNTAX ERROR’ IF NEITHER +1155 e13f c6 03 LDB #3 =ROOM FOR 6 +1156 e141 bd de f0 JSR LAC33 =BYTES ON STACK? +1157 e144 de 83 LDU CHARAD * SAVE CURRENT BASIC INPUT POINTER, LINE +1158 e146 9e 68 LDX CURLIN * NUMBER AND SUB TOKEN ON STACK +1159 e148 86 a1 LDA #TOK_SUB * +1160 e14a 34 52 PSHS U,X,A * +1161 e14c 8d 03 LAE9F BSR LAEA4 GO DO A ‘GOTO’ +1162 e14e 7e e0 3f JMP LAD9E JUMP BACK TO BASIC’S MAIN LOOP +1163 * GOTO +1164 e151 9d 82 LAEA4 JSR GETCCH GET CURRENT INPUT CHAR +1165 e153 bd e2 14 JSR LAF67 GET LINE NUMBER TO BINARY IN BINVAL +1166 e156 8d 40 BSR LAEEB ADVANCE BASIC’S POINTER TO END OF LINE +1167 e158 30 01 LEAX $01,X POINT TO START OF NEXT LINE +1168 e15a dc 2b LDD BINVAL GET THE LINE NUMBER TO RUN +1169 e15c 10 93 68 CMPD CURLIN COMPARE TO CURRENT LINE NUMBER +1170 e15f 22 02 BHI LAEB6 IF REO’D LINE NUMBER IS > CURRENT LINE NUMBER, +1171 * DON’T START LOOKING FROM +1172 * START OF PROGRAM +1173 e161 9e 19 LDX TXTTAB BEGINNING OF PROGRAM +1174 e163 bd df a6 LAEB6 JSR LAD05 GO FIND A LINE NUMBER +1175 e166 25 17 BCS LAED2 ‘UNDEFINED LINE NUMBER’ +1176 e168 30 1f LAEBB LEAX -1,X MOVE BACK TO JUST BEFORE START OF LINE +1177 e16a 9f 83 STX CHARAD RESET BASIC’S INPUT POINTER +1178 e16c 39 LAEBF RTS +1179 * +1180 * RETURN +1181 e16d 26 fd RETURN BNE LAEBF EXIT ROUTINE IF ARGUMENT GIVEN +1182 e16f 86 ff LDA #$FF * PUT AN ILLEGAL VARIABLE NAME IN FIRST BYTE OF +1183 e171 97 3b STA VARDES * VARDES WHICH WILL CAUSE ‘FOR/NEXT’ DATA ON THE +1184 * STACK TO BE IGNORED +1185 e173 bd de b6 JSR LABF9 CHECK FOR RETURN DATA ON THE STACK +1186 e176 1f 14 TFR X,S RESET STACK POINTER - PURGE TWO RETURN ADDRESSES +1187 * FROM THE STACK +1188 e178 81 21 CMPA #TOK_SUB-$80 SUB TOKEN - $80 +1189 e17a 27 0b BEQ LAEDA BRANCH IF ‘RETURN’ FROM SUBROUTINE +1190 e17c c6 04 LDB #2*2 ERROR #2 ‘RETURN WITHOUT GOSUB’ +1191 e17e 8c FCB SKP2 SKIP TWO BYTES +1192 e17f c6 0e LAED2 LDB #7*2 ERROR #7 ‘UNDEFINED LINE NUMBER’ +1193 e181 7e df 03 JMP LAC46 JUMP TO ERROR HANDLER +1194 e184 7e e5 00 LAED7 JMP LB277 ‘SYNTAX ERROR’ +1195 e187 35 52 LAEDA PULS A,X,U * RESTORE VALUES OF CURRENT LINE NUMBER AND +1196 e189 9f 68 STX CURLIN * BASIC’S INPUT POINTER FOR THIS SUBROUTINE +1197 e18b df 83 STU CHARAD * AND LOAD ACCA WITH SUB TOKEN ($A6) +1198 * +1199 * DATA +1200 e18d 8d 06 DATA BSR LAEE8 MOVE INPUT POINTER TO END OF SUBLINE OR LINE +1201 e18f 8c FCB SKP2 SKIP 2 BYTES +1202 +1203 * REM, ELSE +1204 ELSE +1205 e190 8d 06 REM BSR LAEEB MOVE INPUT POINTER TO END OF LINE +1206 e192 9f 83 STX CHARAD RESET BASIC’S INPUT POINTER +1207 e194 39 LAEE7 RTS +1208 * ADVANCE INPUT POINTER TO END OF SUBLINE OR LINE +1209 e195 c6 3a LAEE8 LDB #': COLON = SUBLINE TERMINATOR CHARACTER +1210 e197 86 LAEEA FCB SKP1LD SKPILD SKIP ONE BYTE; LDA #$5F +1211 * ADVANCE BASIC’S INPUT POINTER TO END OF +1212 * LINE - RETURN ADDRESS OF END OF LINE+1 IN X +1213 e198 5f LAEEB CLRB 0 = LINE TERMINATOR CHARACTER +1214 e199 d7 01 STB CHARAC TEMP STORE PRIMARY TERMINATOR CHARACTER +1215 e19b 5f CLRB 0 (END OF LINE) = ALTERNATE TERM. CHAR. +1216 e19c 9e 83 LDX CHARAD LOAD X W/BASIC’S INPUT POINTER +1217 e19e 1f 98 LAEF1 TFR B,A * CHANGE TERMINATOR CHARACTER +1218 e1a0 d6 01 LDB CHARAC * FROM ACCB TO CHARAC - SAVE OLD TERMINATOR +1219 * IN CHARAC +1220 e1a2 97 01 STA CHARAC SWAP PRIMARY AND SECONDARY TERMINATORS +1221 e1a4 a6 84 LAEF7 LDA ,X GET NEXT INPUT CHARACTER +1222 e1a6 27 ec BEQ LAEE7 RETURN IF 0 (END OF LINE) +1223 e1a8 34 04 PSHS B SAVE TERMINATOR ON STACK +1224 e1aa a1 e0 CMPA ,S+ COMPARE TO INPUT CHARACTER +1225 e1ac 27 e6 BEQ LAEE7 RETURN IF EQUAL +1226 e1ae 30 01 LEAX 1,X MOVE POINTER UP ONE +1227 e1b0 81 22 CMPA #'" CHECK FOR DOUBLE QUOTES +1228 e1b2 27 ea BEQ LAEF1 BRANCH IF " - TOGGLE TERMINATOR CHARACTERS +1229 e1b4 4c INCA * CHECK FOR $FF AND BRANCH IF +1230 e1b5 26 02 BNE LAF0C * NOT SECONDARY TOKEN +1231 e1b7 30 01 LEAX 1,X MOVE INPUT POINTER 1 MORE IF SECONDARY +1232 e1b9 81 86 LAF0C CMPA #TOK_IF+1 TOKEN FOR IF? +1233 e1bb 26 e7 BNE LAEF7 NO - GET ANOTHER INPUT CHARACTER +1234 e1bd 0c 04 INC IFCTR INCREMENT IF COUNTER - KEEP TRACK OF HOW MANY +1235 * ‘IF’ STATEMENTS ARE NESTED IN ONE LINE +1236 e1bf 20 e3 BRA LAEF7 GET ANOTHER INPUT CHARACTER +1237 +1238 * IF +1239 e1c1 bd e3 ca IF JSR LB141 EVALUATE NUMERIC EXPRESSION +1240 e1c4 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +1241 e1c6 81 81 CMPA #TOK_GO TOKEN FOR GO +1242 e1c8 27 05 BEQ LAF22 TREAT ‘GO’ THE SAME AS ‘THEN’ +1243 e1ca c6 a2 LDB #TOK_THEN TOKEN FOR THEN +1244 e1cc bd e4 f8 JSR LB26F DO A SYNTAX CHECK ON ACCB +1245 e1cf 96 4f LAF22 LDA FP0EXP CHECK FOR TRUE/FALSE - FALSE IF FPA0 EXPONENT = ZERO +1246 e1d1 26 13 BNE LAF39 BRANCH IF CONDITION TRUE +1247 e1d3 0f 04 CLR IFCTR CLEAR FLAG - KEEP TRACK OF WHICH NESTED ELSE STATEMENT +1248 * TO SEARCH FOR IN NESTED ‘IF’ LOOPS +1249 e1d5 8d b6 LAF28 BSR DATA MOVE BASIC’S POINTER TO END OF SUBLINE +1250 e1d7 4d TSTA * CHECK TO SEE IF END OF LINE OR SUBLINE +1251 e1d8 27 ba BEQ LAEE7 * AND RETURN IF END OF LINE +1252 e1da 9d 7c JSR GETNCH GET AN INPUT CHARACTER FROM BASIC +1253 e1dc 81 84 CMPA #TOK_ELSE TOKEN FOR ELSE +1254 e1de 26 f5 BNE LAF28 IGNORE ALL DATA EXCEPT ‘ELSE’ UNTIL +1255 * END OF LINE (ZERO BYTE) +1256 e1e0 0a 04 DEC IFCTR CHECK TO SEE IF YOU MUST SEARCH ANOTHER SUBLINE +1257 e1e2 2a f1 BPL LAF28 BRANCH TO SEARCH ANOTHER SUBLINE FOR ‘ELSE’ +1258 e1e4 9d 7c JSR GETNCH GET AN INPUT CHARACTER FROM BASIC +1259 e1e6 9d 82 LAF39 JSR GETCCH GET CURRENT INPUT CHARACTER +1260 e1e8 10 25 ff 65 LBCS LAEA4 BRANCH TO ‘GOTO’ IF NUMERIC CHARACTER +1261 e1ec 7e e0 77 JMP LADC6 RETURN TO MAIN INTERPRETATION LOOP +1262 +1263 * ON +1264 e1ef bd e9 8f ON JSR LB70B EVALUATE EXPRESSION +1265 e1f2 c6 81 LDB #TOK_GO TOKEN FOR GO +1266 e1f4 bd e4 f8 JSR LB26F SYNTAX CHECK FOR GO +1267 e1f7 34 02 PSHS A SAVE NEW TOKEN (TO,SUB) +1268 e1f9 81 a1 CMPA #TOK_SUB TOKEN FOR SUB? +1269 e1fb 27 04 BEQ LAF54 YES +1270 e1fd 81 a0 CMPA #TOK_TO TOKEN FOR TO? +1271 e1ff 26 83 LAF52 BNE LAED7 ‘SYNTAX’ ERROR IF NOT ‘SUB’ OR ‘TO’ +1272 e201 0a 53 LAF54 DEC FPA0+3 DECREMENT IS BYTE OF MANTISSA OF FPA0 - THIS +1273 * IS THE ARGUMENT OF THE ‘ON’ STATEMENT +1274 e203 26 05 BNE LAF5D BRANCH IF NOT AT THE PROPER GOTO OR GOSUB LINE NUMBER +1275 e205 35 04 PULS B GET BACK THE TOKEN FOLLOWING ‘GO’ +1276 e207 7e e1 35 JMP LAE88 GO DO A ‘GOTO’ OR ‘GOSUB’ +1277 e20a 9d 7c LAF5D JSR GETNCH GET A CHARACTER FROM BASIC +1278 e20c 8d 06 BSR LAF67 CONVERT BASIC LINE NUMBER TO BINARY +1279 e20e 81 2c CMPA #', IS CHARACTER FOLLOWING LINE NUMBER A COMMA? +1280 e210 27 ef BEQ LAF54 YES +1281 e212 35 84 PULS B,PC IF NOT, FALL THROUGH TO NEXT COMMAND +1282 e214 9e 74 LAF67 LDX ZERO DEFAULT LINE NUMBER OF ZERO +1283 e216 9f 2b STX BINVAL SAVE IT IN BINVAL +1284 * +1285 * CONVERT LINE NUMBER TO BINARY - RETURN VALUE IN BINVAL +1286 * +1287 e218 24 61 LAF6B BCC LAFCE RETURN IF NOT NUMERIC CHARACTER +1288 e21a 80 30 SUBA #'0 MASK OFF ASCII +1289 e21c 97 01 STA CHARAC SAVE DIGIT IN VO1 +1290 e21e dc 2b LDD BINVAL GET ACCUMULATED LINE NUMBER VALUE +1291 e220 81 18 CMPA #24 LARGEST LINE NUMBER IS $F9FF (63999) - +1292 * (24*256+255)*10+9 +1293 e222 22 db BHI LAF52 ‘SYNTAX’ ERROR IF TOO BIG +1294 * MULT ACCD X 10 +1295 e224 58 ASLB * +1296 e225 49 ROLA * TIMES 2 +1297 e226 58 ASLB = +1298 e227 49 ROLA = TIMES 4 +1299 e228 d3 2b ADDD BINVAL ADD 1 = TIMES 5 +1300 e22a 58 ASLB * +1301 e22b 49 ROLA * TIMES 10 +1302 e22c db 01 ADDB CHARAC ADD NEXT DIGIT +1303 e22e 89 00 ADCA #0 PROPAGATE CARRY +1304 e230 dd 2b STD BINVAL SAVE NEW ACCUMULATED LINE NUMBER +1305 e232 9d 7c JSR GETNCH GET NEXT CHARACTER FROM BASIC +1306 e234 20 e2 BRA LAF6B LOOP- PROCESS NEXT DIGIT +1307 * +1308 * LET (EXBAS) +1309 * EVALUATE A NON-TOKEN EXPRESSION +1310 * TARGET = REPLACEMENT +1311 e236 bd e5 db LET JSR LB357 FIND TARGET VARIABLE DESCRIPTOR +1312 e239 9f 3b STX VARDES SAVE DESCRIPTOR ADDRESS OF 1ST EXPRESSION +1313 e23b c6 ae LDB #TOK_EQUALS TOKEN FOR "=" +1314 e23d bd e4 f8 JSR LB26F DO A SYNTAX CHECK FOR ‘=‘ +1315 e240 96 06 LDA VALTYP * GET VARIABLE TYPE AND +1316 e242 34 02 PSHS A * SAVE ON THE STACK +1317 e244 bd e3 df JSR LB156 EVALUATE EXPRESSION +1318 e247 35 02 PULS A * REGET VARIABLE TYPE OF 1ST EXPRESSION AND +1319 e249 46 RORA * SET CARRY IF STRING +1320 e24a bd e3 d1 JSR LB148 TYPE CHECK-TM ERROR IF VARIABLE TYPES ON +1321 * BOTH SIDES OF EQUALS SIGN NOT THE SAME +1322 e24d 10 27 0c 2b LBEQ LBC33 GO PUT FPA0 INTO VARIABLE DESCRIPTOR IF NUMERIC +1323 * MOVE A STRING WHOSE DESCRIPTOR IS LOCATED AT +1324 * FPA0+2 INTO THE STRING SPACE. TRANSFER THE +1325 * DESCRIPTOR ADDRESS TO THE ADDRESS IN VARDES +1326 * DON’T MOVE THE STRING IF IT IS ALREADY IN THE +1327 * STRING SPACE. REMOVE DESCRIPTOR FROM STRING +1328 * STACK IF IT IS LAST ONE ON THE STACK +1329 e251 9e 52 LAFA4 LDX FPA0+2 POINT X TO DESCRIPTOR OF REPLACEMENT STRING +1330 e253 dc 21 LDD FRETOP LOAD ACCD WITH START OF STRING SPACE +1331 e255 10 a3 02 CMPD 2,X IS THE STRING IN STRING SPACE? +1332 e258 24 11 BCC LAFBE BRANCH IF IT’S NOT IN THE STRING SPACE +1333 e25a 9c 1b CMPX VARTAB COMPARE DESCRIPTOR ADDRESS TO START OF VARIABLES +1334 e25c 25 0d BCS LAFBE BRANCH IF DESCRIPTOR ADDRESS NOT IN VARIABLES +1335 e25e e6 84 LAFB1 LDB ,X GET LENGTH OF REPLACEMENT STRING +1336 e260 bd e7 91 JSR LB50D RESERVE ACCB BYTES OF STRING SPACE +1337 e263 9e 4d LDX V4D GET DESCRIPTOR ADDRESS BACK +1338 e265 bd e8 c7 JSR LB643 MOVE STRING INTO STRING SPACE +1339 e268 8e 00 56 LDX #STRDES POINT X TO TEMP STRING DESCRIPTOR ADDRESS +1340 e26b 9f 4d LAFBE STX V4D SAVE STRING DESCRIPTOR ADDRESS IN V4D +1341 e26d bd e8 f9 JSR LB675 REMOVE STRING DESCRIPTOR IF LAST ONE +1342 * ON STRING STACK +1343 e270 de 4d LDU V4D POINT U TO REPLACEMENT DESCRIPTOR ADDRESS +1344 e272 9e 3b LDX VARDES GET TARGET DESCRIPTOR ADDRESS +1345 e274 37 26 PULU A,B,Y GET LENGTH AND START OF REPLACEMENT STRING +1346 e276 a7 84 STA ,X * SAVE STRING LENGTH AND START IN +1347 e278 10 af 02 STY 2,X * TARGET DESCRIPTOR LOCATION +1348 e27b 39 LAFCE RTS +1349 +1350 e27c 3f 52 45 44 4f LAFCF FCC "?REDO" ?REDO MESSAGE +1351 e281 0d 00 FCB CR,$00 +1352 +1353 LAFD6 +1354 e283 7e df 03 LAFDC JMP LAC46 JMP TO ERROR HANDLER +1355 e286 96 09 LAFDF LDA INPFLG = GET THE INPUT FLAG AND BRANCH +1356 e288 27 07 BEQ LAFEA = IF ‘INPUT’ +1357 e28a 9e 31 LDX DATTXT * GET LINE NUMBER WHERE THE ERROR OCCURRED +1358 e28c 9f 68 STX CURLIN * AND USE IT AS THE CURRENT LINE NUMBER +1359 e28e 7e e5 00 JMP LB277 ‘SYNTAX ERROR’ +1360 e291 8e e2 7b LAFEA LDX #LAFCF-1 * POINT X TO ‘?REDO’ AND PRINT +1361 e294 bd eb e5 JSR LB99C * IT ON THE SCREEN +1362 e297 9e 2f LDX TINPTR = GET THE SAVED ABSOLUTE ADDRESS OF +1363 e299 9f 83 STX CHARAD = INPUT POINTER AND RESTORE IT +1364 e29b 39 RTS +1365 * +1366 * INPUT +1367 e29c c6 16 INPUT LDB #11*2 ‘ID’ ERROR +1368 e29e 9e 68 LDX CURLIN GET CURRENT LINE NUMBER +1369 e2a0 30 01 LEAX 1,X ADD ONE +1370 e2a2 27 df BEQ LAFDC ‘ID’ ERROR BRANCH IF DIRECT MODE +1371 e2a4 8d 01 BSR LB00F GET SOME INPUT DATA - WAS LB002 +1372 e2a6 39 RTS +1373 e2a7 81 22 LB00F CMPA #'" CHECK FOR PROMPT STRING DELIMITER +1374 e2a9 26 0b BNE LB01E BRANCH IF NO PROMPT STRING +1375 e2ab bd e4 cd JSR LB244 PUT PROMPT STRING ON STRING STACK +1376 e2ae c6 3b LDB #'; * +1377 e2b0 bd e4 f8 JSR LB26F * DO A SYNTAX CHECK FOR SEMICOLON +1378 e2b3 bd eb e8 JSR LB99F PRINT MESSAGE TO CONSOLE OUT +1379 e2b6 8e 00 f3 LB01E LDX #LINBUF POINT TO BASIC’S LINE BUFFER +1380 e2b9 6f 84 CLR ,X CLEAR 1ST BYTE - FLAG TO INDICATE NO DATA +1381 * IN LINE BUFFER +1382 e2bb 8d 06 BSR LB02F INPUT A STRING TO LINE BUFFER +1383 e2bd c6 2c LDB #', * INSERT A COMMA AT THE END +1384 e2bf e7 84 STB ,X * OF THE LINE INPUT BUFFER +1385 e2c1 20 16 BRA LB049 +1386 * FILL BASIC’S LINE INPUT BUFFER CONSOLE IN +1387 e2c3 bd eb f8 LB02F JSR LB9AF SEND A "?" TO CONSOLE OUT +1388 e2c6 bd eb f5 JSR LB9AC SEND A ‘SPACE’ TO CONSOLE OUT +1389 e2c9 bd dc 3e LB035 JSR LA390 GO READ IN A BASIC LINE +1390 e2cc 24 05 BCC LB03F BRANCH IF ENTER KEY ENDED ENTRY +1391 e2ce 32 64 LEAS 4,S PURGE TWO RETURN ADDRESSES OFF THE STACK +1392 e2d0 7e e0 c6 JMP LAE11 GO DO A ‘STOP’ IF BREAK KEY ENDED LINE ENTRY +1393 e2d3 c6 2e LB03F LDB #2*23 ‘INPUT PAST END OF FILE’ ERROR +1394 e2d5 39 RTS +1395 * +1396 * READ +1397 e2d6 9e 33 READ LDX DATPTR GET ‘READ’ START ADDRESS +1398 e2d8 86 FCB SKP1LD SKIP ONE BYTE - LDA #*$4F +1399 e2d9 4f LB049 CLRA ‘INPUT’ ENTRY POINT: INPUT FLAG = 0 +1400 e2da 97 09 STA INPFLG SET INPUT FLAG; 0 = INPUT: <> 0 = READ +1401 e2dc 9f 35 STX DATTMP SAVE ‘READ’ START ADDRESS/’INPUT’ BUFFER START +1402 e2de bd e5 db LB04E JSR LB357 EVALUATE A VARIABLE +1403 e2e1 9f 3b STX VARDES SAVE DESCRIPTOR ADDRESS +1404 e2e3 9e 83 LDX CHARAD * GET BASIC’S INPUT POINTER +1405 e2e5 9f 2b STX BINVAL * AND SAVE IT +1406 e2e7 9e 35 LDX DATTMP GET ‘READ’ ADDRESS START/’INPUT’ BUFFER POINTER +1407 e2e9 a6 84 LDA ,X GET A CHARACTER FROM THE BASIC PROGRAM +1408 e2eb 26 09 BNE LB069 BRANCH IF NOT END OF LINE +1409 e2ed 96 09 LDA INPFLG * CHECK INPUT FLAG AND BRANCH +1410 e2ef 26 51 BNE LB0B9 * IF LOOKING FOR DATA (READ) +1411 * NO DATA IN ‘INPUT’ LINE BUFFER AND/OR INPUT +1412 * NOT COMING FROM SCREEN +1413 e2f1 bd eb f8 JSR LB9AF SEND A '?' TO CONSOLE OUT +1414 e2f4 8d cd BSR LB02F FILL INPUT BUFFER FROM CONSOLE IN +1415 e2f6 9f 83 LB069 STX CHARAD RESET BASIC’S INPUT POINTER +1416 e2f8 9d 7c JSR GETNCH GET A CHARACTER FROM BASIC +1417 e2fa d6 06 LDB VALTYP * CHECK VARIABLE TYPE AND +1418 e2fc 27 23 BEQ LB098 * BRANCH IF NUMERIC +1419 * READ/INPUT A STRING VARIABLE +1420 e2fe 9e 83 LDX CHARAD LOAD X WITH CURRENT BASIC INPUT POINTER +1421 e300 97 01 STA CHARAC SAVE CURRENT INPUT CHARACTER +1422 e302 81 22 CMPA #'" CHECK FOR STRING DELIMITER +1423 e304 27 0e BEQ LB08B BRANCH IF STRING DELIMITER +1424 e306 30 1f LEAX -1,X BACK UP POINTER +1425 e308 4f CLRA * ZERO = END OF LINE CHARACTER +1426 e309 97 01 STA CHARAC * SAVE AS TERMINATOR +1427 e30b bd dc 30 JSR LA35F SET UP PRINT PARAMETERS +1428 e30e 86 3a LDA #': END OF SUBLINE CHARACTER +1429 e310 97 01 STA CHARAC SAVE AS TERMINATOR I +1430 e312 86 2c LDA #', COMMA +1431 e314 97 02 LB08B STA ENDCHR SAVE AS TERMINATOR 2 +1432 e316 bd e7 a2 JSR LB51E STRIP A STRING FROM THE INPUT BUFFER +1433 e319 bd e4 d2 JSR LB249 MOVE INPUT POINTER TO END OF STRING +1434 e31c bd e2 51 JSR LAFA4 PUT A STRING INTO THE STRING SPACE IF NECESSARY +1435 e31f 20 06 BRA LB09E CHECK FOR ANOTHER DATA ITEM +1436 * SAVE A NUMERIC VALUE IN A READ OR INPUT DATA ITEM +1437 e321 bd ef 5b LB098 JSR LBD12 CONVERT AN ASCII STRING TO FP NUMBER +1438 e324 bd ee 7c JSR LBC33 PACK FPA0 AND STORE IT IN ADDRESS IN VARDES - +1439 * INPUT OR READ DATA ITEM +1440 e327 9d 82 LB09E JSR GETCCH GET CURRENT INPUT CHARACTER +1441 e329 27 06 BEQ LB0A8 BRANCH IF END OF LINE +1442 e32b 81 2c CMPA #', CHECK FOR A COMMA +1443 e32d 10 26 ff 52 LBNE LAFD6 BAD FILE DATA' ERROR OR RETRY +1444 e331 9e 83 LB0A8 LDX CHARAD * GET CURRENT INPUT +1445 e333 9f 35 STX DATTMP * POINTER (USED AS A DATA POINTER) AND SAVE IT +1446 e335 9e 2b LDX BINVAL * RESET INPUT POINTER TO INPUT OR +1447 e337 9f 83 STX CHARAD * READ STATEMENT +1448 e339 9d 82 JSR GETCCH GET CURRENT CHARACTER FROM BASIC +1449 e33b 27 21 BEQ LB0D5 BRANCH IF END OF LINE - EXIT COMMAND +1450 e33d bd e4 f6 JSR LB26D SYNTAX CHECK FOR COMMA +1451 e340 20 9c BRA LB04E GET ANOTHER INPUT OR READ ITEM +1452 * SEARCH FROM ADDRESS IN X FOR +1453 * 1ST OCCURENCE OF THE TOKEN FOR DATA +1454 e342 9f 83 LB0B9 STX CHARAD RESET BASIC’S INPUT POINTER +1455 e344 bd e1 95 JSR LAEE8 SEARCH FOR END OF CURRENT LINE OR SUBLINE +1456 e347 30 01 LEAX 1,X MOVE X ONE PAST END OF LINE +1457 e349 4d TSTA CHECK FOR END OF LINE +1458 e34a 26 0a BNE LB0CD BRANCH IF END OF SUBLINE +1459 e34c c6 06 LDB #2*3 ‘OUT OF DATA’ ERROR +1460 e34e ee 81 LDU ,X++ GET NEXT 2 CHARACTERS +1461 e350 27 41 BEQ LB10A ‘OD’ ERROR IF END OF PROGRAM +1462 e352 ec 81 LDD ,X++ GET BASIC LINE NUMBER AND +1463 e354 dd 31 STD DATTXT SAVE IT IN DATTXT +1464 e356 a6 84 LB0CD LDA ,X GET AN INPUT CHARACTER +1465 e358 81 86 CMPA #TOK_DATA DATA TOKEN? +1466 e35a 26 e6 BNE LB0B9 NO — KEEP LOOKING +1467 e35c 20 98 BRA LB069 YES +1468 * EXIT READ AND INPUT COMMANDS +1469 e35e 9e 35 LB0D5 LDX DATTMP GET DATA POINTER +1470 e360 d6 09 LDB INPFLG * CHECK INPUT FLAG +1471 e362 10 26 fd 3a LBNE LADE8 * SAVE NEW DATA POINTER IF READ +1472 e366 a6 84 LDA ,X = CHECK NEXT CHARACTER IN ‘INPUT’ BUFFER +1473 e368 27 06 BEQ LB0E7 = +1474 e36a 8e e3 70 LDX #LB0E8-1 POINT X TO ‘?EXTRA IGNORED’ +1475 e36d 7e eb e5 JMP LB99C PRINT THE MESSAGE +1476 e370 39 LB0E7 RTS +1477 +1478 e371 3f 45 58 54 52 41 LB0E8 FCC "?EXTRA IGNORED" ?EXTRA IGNORED MESSAGE + 20 49 47 4e 4f 52 + 45 44 +1479 +1480 +1481 e37f 0d 00 FCB CR,$00 +1482 +1483 * NEXT +1484 e381 26 04 NEXT BNE LB0FE BRANCH IF ARGUMENT GIVEN +1485 e383 9e 74 LDX ZERO X = 0: DEFAULT FOR NO ARGUMENT +1486 e385 20 03 BRA LB101 +1487 e387 bd e5 db LB0FE JSR LB357 EVALUATE AN ALPHA EXPRESSION +1488 e38a 9f 3b LB101 STX VARDES SAVE VARIABLE DESCRIPTOR POINTER +1489 e38c bd de b6 JSR LABF9 GO SCAN FOR ‘FOR/NEXT’ DATA ON STACK +1490 e38f 27 04 BEQ LB10C BRANCH IF DATA FOUND +1491 e391 c6 00 LDB #0 ‘NEXT WITHOUT FOR’ ERROR (SHOULD BE CLRB) +1492 e393 20 47 LB10A BRA LB153 PROCESS ERROR +1493 e395 1f 14 LB10C TFR X,S POINT S TO START OF ‘FOR/NEXT’ DATA +1494 e397 30 03 LEAX 3,X POINT X TO FP VALUE OF STEP +1495 e399 bd ee 5d JSR LBC14 COPY A FP NUMBER FROM (X) TO FPA0 +1496 e39c a6 68 LDA 8,S GET THE DIRECTION OF STEP +1497 e39e 97 54 STA FP0SGN SAVE IT AS THE SIGN OF FPA0 +1498 e3a0 9e 3b LDX VARDES POINT (X) TO INDEX VARIABLE DESCRIPTOR +1499 e3a2 bd ec 0b JSR LB9C2 ADD (X) TO FPA0 (STEP TO INDEX) +1500 e3a5 bd ee 7c JSR LBC33 PACK FPA0 AND STORE IT IN ADDRESS +1501 * CONTAINED IN VARDES +1502 e3a8 30 69 LEAX 9,S POINT (X) TO TERMINAL VALUE OF INDEX +1503 e3aa bd ee df JSR LBC96 COMPARE CURRENT INDEX VALUE TO TERMINAL VALUE OF INDEX +1504 e3ad e0 68 SUBB 8,S ACCB = 0 IF TERMINAL VALUE=CURRENT VALUE AND STEP=0 OR IF +1505 * STEP IS POSITIVE AND CURRENT VALUE>TERMINAL VALUE OR +1506 * STEP IS NEGATIVE AND CURRENT VALUE +1552 e3f5 25 13 BCS LB181 BRANCH IF LESS THAN RELATIONAL OPERATORS +1553 e3f7 81 03 CMPA #3 * +1554 e3f9 24 0f BCC LB181 * BRANCH IF GREATER THAN RELATIONAL OPERATORS +1555 e3fb 81 01 CMPA #1 SET CARRY IF ‘>‘ +1556 e3fd 49 ROLA CARRY TO BIT 0 +1557 e3fe 98 3f EORA TRELFL * CARRY SET IF +1558 e400 91 3f CMPA TRELFL * TRELFL = ACCA +1559 e402 25 64 BCS LB1DF BRANCH IF SYNTAX ERROR : == << OR >> +1560 e404 97 3f STA TRELFL BIT 0: >, BIT 1 =, BIT 2: < +1561 e406 9d 7c JSR GETNCH GET AN INPUT CHARACTER +1562 e408 20 e9 BRA LB16A CHECK FOR ANOTHER RELATIONAL OPERATOR +1563 * +1564 e40a d6 3f LB181 LDB TRELFL GET RELATIONAL OPERATOR FLAG +1565 e40c 26 33 BNE LB1B8 BRANCH IF RELATIONAL COMPARISON +1566 e40e 10 24 00 6b LBCC LB1F4 BRANCH IF > RELATIONAL OPERATOR +1567 e412 8b 07 ADDA #7 SEVEN ARITHMETIC/LOGICAL OPERATORS +1568 e414 24 67 BCC LB1F4 BRANCH IF NOT ARITHMETIC/LOGICAL OPERATOR +1569 e416 99 06 ADCA VALTYP ADD CARRY, NUMERIC FLAG AND MODIFIED TOKEN NUMBER +1570 e418 10 27 04 77 LBEQ LB60F BRANCH IF VALTYP = FF, AND ACCA = ‘+‘ TOKEN - +1571 * CONCATENATE TWO STRINGS +1572 e41c 89 ff ADCA #-1 RESTORE ARITHMETIC/LOGICAL OPERATOR NUMBER +1573 e41e 34 02 PSHS A * STORE OPERATOR NUMBER ON STACK; MULTIPLY IT BY 2 +1574 e420 48 ASLA * THEN ADD THE STORED STACK DATA = MULTIPLY +1575 e421 ab e0 ADDA ,S+ * X 3; 3 BYTE/TABLE ENTRY +1576 e423 8e dd 08 LDX #LAA51 JUMP TABLE FOR ARITHMETIC & LOGICAL OPERATORS +1577 e426 30 86 LEAX A,X POINT X TO PROPER TABLE +1578 e428 35 02 LB19F PULS A GET PRECEDENCE FLAG FROM STACK +1579 e42a a1 84 CMPA ,X COMPARE TO CURRENT OPERATOR +1580 e42c 24 55 BCC LB1FA BRANCH IF STACK OPERATOR > CURRENT OPERATOR +1581 e42e 8d 9c BSR LB143 ‘TM’ ERROR IF VARIABLE TYPE = STRING +1582 +1583 * OPERATION BEING PROCESSED IS OF HIGHER PRECEDENCE THAN THE PREVIOUS OPERATION. +1584 e430 34 02 LB1A7 PSHS A SAVE PRECEDENCE FLAG +1585 e432 8d 29 BSR LB1D4 PUSH OPERATOR ROUTINE ADDRESS AND FPA0 ONTO STACK +1586 e434 9e 3d LDX RELPTR GET POINTER TO ARITHMETIC/LOGICAL TABLE ENTRY FOR +1587 * LAST CALCULATED OPERATION +1588 e436 35 02 PULS A GET PRECEDENCE FLAG OF PREVIOUS OPERATION +1589 e438 26 1d BNE LB1CE BRANCH IF NOT END OF OPERATION +1590 e43a 4d TSTA CHECK TYPE OF PRECEDENCE FLAG +1591 e43b 10 27 00 6a LBEQ LB220 BRANCH IF END OF EXPRESSION OR SUB-EXPRESSION +1592 e43f 20 4b BRA LB203 EVALUATE AN OPERATION +1593 +1594 e441 08 06 LB1B8 ASL VALTYP BIT 7 OF TYPE FLAG TO CARRY +1595 e443 59 ROLB SHIFT RELATIONAL FLAG LEFT - VALTYP TO BIT 0 +1596 e444 8d 09 BSR LB1C6 MOVE THE INPUT POINTER BACK ONE +1597 e446 8e e4 54 LDX #LB1CB POINT X TO RELATIONAL COMPARISON JUMP TABLE +1598 e449 d7 3f STB TRELFL SAVE RELATIONAL COMPARISON DATA +1599 e44b 0f 06 CLR VALTYP SET VARIABLE TYPE TO NUMERIC +1600 e44d 20 d9 BRA LB19F PERFORM OPERATION OR SAVE ON STACK +1601 +1602 e44f 9e 83 LB1C6 LDX CHARAD * GET BASIC’S INPUT POINTER AND +1603 e451 7e e1 68 JMP LAEBB * MOVE IT BACK ONE +1604 * RELATIONAL COMPARISON JUMP TABLE +1605 e454 64 LB1CB FCB $64 RELATIONAL COMPARISON FLAG +1606 e455 e5 78 LB1CC FDB LB2F4 JUMP ADDRESS +1607 +1608 e457 a1 84 LB1CE CMPA ,X COMPARE PRECEDENCE OF LAST DONE OPERATION TO +1609 * NEXT TO BE DONE OPERATION +1610 e459 24 31 BCC LB203 EVALUATE OPERATION IF LOWER PRECEDENCE +1611 e45b 20 d3 BRA LB1A7 PUSH OPERATION DATA ON STACK IF HIGHER PRECEDENCE +1612 +1613 * PUSH OPERATOR EVALUATION ADDRESS AND FPA0 ONTO STACK AND EVALUATE ANOTHER EXPR +1614 e45d ec 01 LB1D4 LDD 1,X GET ADDRESS OF OPERATOR ROUTINE +1615 e45f 34 06 PSHS B,A SAVE IT ON THE STACK +1616 e461 8d 08 BSR LB1E2 PUSH FPA0 ONTO STACK +1617 e463 d6 3f LDB TRELFL GET BACK RELATIONAL OPERATOR FLAG +1618 e465 16 ff 7b LBRA LB15A EVALUATE ANOTHER EXPRESSION +1619 e468 7e e5 00 LB1DF JMP LB277 ‘SYNTAX ERROR’ +1620 * PUSH FPA0 ONTO THE STACK. ,S = EXPONENT +1621 * 1-2,S =HIGH ORDER MANTISSA 3-4,S = LOW ORDER MANTISSA +1622 * 5,S = SIGN RETURN WITH PRECEDENCE CODE IN ACCA +1623 e46b d6 54 LB1E2 LDB FP0SGN GET SIGN OF FPA0 MANTISSA +1624 e46d a6 84 LDA ,X GET PRECEDENCE CODE TO ACCA +1625 e46f 35 20 LB1E6 PULS Y GET RETURN ADDRESS FROM STACK & PUT IT IN Y +1626 e471 34 04 PSHS B SAVE ACCB ON STACK +1627 e473 d6 4f LB1EA LDB FP0EXP * PUSH FPA0 ONTO THE STACK +1628 e475 9e 50 LDX FPA0 * +1629 e477 de 52 LDU FPA0+2 * +1630 e479 34 54 PSHS U,X,B * +1631 e47b 6e a4 JMP ,Y JUMP TO ADDRESS IN Y +1632 +1633 * BRANCH HERE IF NON-OPERATOR CHARACTER FOUND - USUALLY ‘)‘ OR END OF LINE +1634 e47d 9e 74 LB1F4 LDX ZERO POINT X TO DUMMY VALUE (ZERO) +1635 e47f a6 e0 LDA ,S+ GET PRECEDENCE FLAG FROM STACK +1636 e481 27 26 BEQ LB220 BRANCH IF END OF EXPRESSION +1637 e483 81 64 LB1FA CMPA #$64 * CHECK FOR RELATIONAL COMPARISON FLAG +1638 e485 27 03 BEQ LB201 * AND BRANCH IF RELATIONAL COMPARISON +1639 e487 bd e3 cc JSR LB143 ‘TM’ ERROR IF VARIABLE TYPE = STRING +1640 e48a 9f 3d LB201 STX RELPTR SAVE POINTER TO OPERATOR ROUTINE +1641 e48c 35 04 LB203 PULS B GET RELATIONAL OPERATOR FLAG FROM STACK +1642 e48e 81 5a CMPA #$5A CHECK FOR ‘NOT’ OPERATOR +1643 e490 27 19 BEQ LB222 RETURN IF ‘NOT’ - NO RELATIONAL COMPARISON +1644 e492 81 7d CMPA #$7D CHECK FOR NEGATION (UNARY) FLAG +1645 e494 27 15 BEQ LB222 RETURN IF NEGATION - NO RELATIONAL COMPARISON +1646 +1647 * EVALUATE AN OPERATION. EIGHT BYTES WILL BE STORED ON STACK, FIRST SIX BYTES +1648 * ARE A TEMPORARY FLOATING POINT RESULT THEN THE ADDRESS OF ROUTINE WHICH +1649 * WILL EVALUATE THE OPERATION. THE RTS AT END OF ROUTINE WILL VECTOR +1650 * TO EVALUATING ROUTINE. +1651 e496 54 LSRB = ROTATE VALTYP BIT INTO CARRY +1652 e497 d7 0a STB RELFLG = FLAG AND SAVE NEW RELFLG +1653 e499 35 52 PULS A,X,U * PULL A FP VALUE OFF OF THE STACK +1654 e49b 97 5c STA FP1EXP * AND SAVE IT IN FPA1 +1655 e49d 9f 5d STX FPA1 * +1656 e49f df 5f STU FPA1+2 * +1657 e4a1 35 04 PULS B = GET MANTISSA SIGN AND +1658 e4a3 d7 61 STB FP1SGN = SAVE IT IN FPA1 +1659 e4a5 d8 54 EORB FP0SGN EOR IT WITH FPA1 MANTISSA SIGN +1660 e4a7 d7 62 STB RESSGN SAVE IT IN RESULT SIGN BYTE +1661 e4a9 d6 4f LB220 LDB FP0EXP GET EXPONENT OF FPA0 +1662 e4ab 39 LB222 RTS +1663 +1664 e4ac bd f6 f9 LB223 JSR XVEC15 CALL EXTENDED BASIC ADD-IN +1665 e4af 0f 06 CLR VALTYP INITIALIZE TYPE FLAG TO NUMERIC +1666 e4b1 9d 7c JSR GETNCH GET AN INPUT CHAR +1667 e4b3 24 03 BCC LB22F BRANCH IF NOT NUMERIC +1668 e4b5 7e ef 5b LB22C JMP LBD12 CONVERT ASCII STRING TO FLOATING POINT - +1669 * RETURN RESULT IN FPA0 +1670 * PROCESS A NON NUMERIC FIRST CHARACTER +1671 e4b8 bd e6 26 LB22F JSR LB3A2 SET CARRY IF NOT ALPHA +1672 e4bb 24 50 BCC LB284 BRANCH IF ALPHA CHARACTER +1673 e4bd 81 2e CMPA #'. IS IT ‘.‘ (DECIMAL POINT)? +1674 e4bf 27 f4 BEQ LB22C CONVERT ASCII STRING TO FLOATING POINT +1675 e4c1 81 a7 CMPA #TOK_MINUS MINUS TOKEN +1676 e4c3 27 40 BEQ LB27C YES - GO PROCESS THE MINUS OPERATOR +1677 e4c5 81 a6 CMPA #TOK_PLUS PLUS TOKEN +1678 e4c7 27 e3 BEQ LB223 YES - GET ANOTHER CHARACTER +1679 e4c9 81 22 CMPA #'" STRING DELIMITER? +1680 e4cb 26 0a BNE LB24E NO +1681 e4cd 9e 83 LB244 LDX CHARAD CURRENT BASIC POINTER TO X +1682 e4cf bd e7 9c JSR LB518 SAVE STRING ON STRING STACK +1683 e4d2 9e 64 LB249 LDX COEFPT * GET ADDRESS OF END OF STRING AND +1684 e4d4 9f 83 STX CHARAD * PUT BASIC’S INPUT POINTER THERE +1685 e4d6 39 RTS +1686 e4d7 81 a3 LB24E CMPA #TOK_NOT NOT TOKEN? +1687 e4d9 26 0d BNE LB25F NO +1688 * PROCESS THE NOT OPERATOR +1689 e4db 86 5a LDA #$5A ‘NOT’ PRECEDENCE FLAG +1690 e4dd bd e3 e3 JSR LB15A PROCESS OPERATION FOLLOWING ‘NOT’ +1691 e4e0 bd e6 71 JSR INTCNV CONVERT FPA0 TO INTEGER IN ACCD +1692 e4e3 43 COMA * ‘NOT’ THE INTEGER +1693 e4e4 53 COMB * +1694 e4e5 7e e7 78 JMP GIVABF CONVERT ACCD TO FLOATING POINT (FPA0) +1695 e4e8 4c LB25F INCA CHECK FOR TOKENS PRECEEDED BY $FF +1696 e4e9 27 2e BEQ LB290 IT WAS PRECEEDED BY $FF +1697 e4eb 8d 06 LB262 BSR LB26A SYNTAX CHECK FOR A ‘(‘ +1698 e4ed bd e3 df JSR LB156 EVALUATE EXPRESSIONS WITHIN PARENTHESES AT +1699 * HIGHEST PRECEDENCE +1700 e4f0 c6 29 LB267 LDB #') SYNTAX CHECK FOR ‘)‘ +1701 e4f2 8c FCB SKP2 SKIP 2 BYTES +1702 e4f3 c6 28 LB26A LDB #'( SYNTAX CHECK FOR ‘(‘ +1703 e4f5 8c FCB SKP2 SKIP 2 BYTES +1704 e4f6 c6 2c LB26D LDB #', SYNTAX CHECK FOR COMMA +1705 e4f8 e1 9f 00 83 LB26F CMPB [CHARAD] * COMPARE ACCB TO CURRENT INPUT +1706 e4fc 26 02 BNE LB277 * CHARACTER - SYNTAX ERROR IF NO MATCH +1707 e4fe 0e 7c JMP GETNCH GET A CHARACTER FROM BASIC +1708 e500 c6 02 LB277 LDB #2*1 SYNTAX ERROR +1709 e502 7e df 03 JMP LAC46 JUMP TO ERROR HANDLER +1710 +1711 * PROCESS THE MINUS (UNARY) OPERATOR +1712 e505 86 7d LB27C LDA #$7D MINUS (UNARY) PRECEDENCE FLAG +1713 e507 bd e3 e3 JSR LB15A PROCESS OPERATION FOLLOWING ‘UNARY’ NEGATION +1714 e50a 7e f1 32 JMP LBEE9 CHANGE SIGN OF FPA0 MANTISSA +1715 +1716 * EVALUATE ALPHA EXPRESSION +1717 e50d bd e5 db LB284 JSR LB357 FIND THE DESCRIPTOR ADDRESS OF A VARIABLE +1718 e510 9f 52 LB287 STX FPA0+2 SAVE DESCRIPTOR ADDRESS IN FPA0 +1719 e512 96 06 LDA VALTYP TEST VARIABLE TYPE +1720 e514 26 95 BNE LB222 RETURN IF STRING +1721 e516 7e ee 5d JMP LBC14 COPY A FP NUMBER FROM (X) TO FPA0 +1722 +1723 * EVALUATING A SECONDARY TOKEN +1724 e519 9d 7c LB290 JSR GETNCH GET AN INPUT CHARACTER (SECONDARY TOKEN) +1725 e51b 1f 89 TFR A,B SAVE IT IN ACCB +1726 e51d 58 ASLB X2 & BET RID OF BIT 7 +1727 e51e 9d 7c JSR GETNCH GET ANOTHER INPUT CHARACTER +1728 e520 c1 38 CMPB #NUM_SEC_FNS-1*2 29 SECONDARY FUNCTIONS - 1 +1729 e522 23 03 BLS LB29F BRANCH IF COLOR BASIC TOKEN +1730 e524 7e e5 00 JMP LB277 SYNTAX ERROR +1731 e527 34 04 LB29F PSHS B SAVE TOKEN OFFSET ON STACK +1732 e529 c1 2a CMPB #TOK_LEFT-$80*2 CHECK FOR TOKEN WITH AN ARGUMENT +1733 e52b 25 1e BCS LB2C7 DO SECONDARIES STRING$ OR LESS +1734 e52d c1 30 CMPB #TOK_INKEY-$80*2 * +1735 e52f 24 1c BCC LB2C9 * DO SECONDARIES $92 (INKEY$) OR > +1736 e531 8d c0 BSR LB26A SYNTAX CHECK FOR A ‘(‘ +1737 e533 a6 e4 LDA ,S GET TOKEN NUMBER +1738 * DO SECONDARIES (LEFT$, RIGHT$, MID$) +1739 e535 bd e3 df JSR LB156 EVALUATE FIRST STRING IN ARGUMENT +1740 e538 8d bc BSR LB26D SYNTAX CHECK FOR A COMMA +1741 e53a bd e3 cf JSR LB146 ‘TM’ ERROR IF NUMERIC VARiABLE +1742 e53d 35 02 PULS A GET TOKEN OFFSET FROM STACK +1743 e53f de 52 LDU FPA0+2 POINT U TO STRING DESCRIPTOR +1744 e541 34 42 PSHS U,A SAVE TOKEN OFFSET AND DESCRIPTOR ADDRESS +1745 e543 bd e9 8f JSR LB70B EVALUATE FIRST NUMERIC ARGUMENT +1746 e546 35 02 PULS A GET TOKEN OFFSET FROM STACK +1747 e548 34 06 PSHS B,A SAVE TOKEN OFFSET AND NUMERIC ARGUMENT +1748 e54a 8e FCB $8E OP CODE OF LDX# - SKlP 2 BYTES +1749 e54b 8d 9e LB2C7 BSR LB262 SYNTAX CHECK FOR A ‘(‘ +1750 e54d 35 04 LB2C9 PULS B GET TOKEN OFFSET +1751 e54f be db f6 LDX COMVEC+8 GET SECONDARY FUNCTION JUMP TABLE ADDRESS +1752 e552 3a LB2CE ABX ADD IN COMMAND OFFSET +1753 * +1754 * HERE IS WHERE WE BRANCH TO A SECONDARY FUNCTION +1755 e553 ad 94 JSR [,X] GO DO AN SECONDARY FUNCTION +1756 e555 7e e3 cc JMP LB143 ‘TM’ ERROR IF VARIABLE TYPE = STRING +1757 +1758 * LOGICAL OPERATOR ‘OR’ JUMPS HERE +1759 e558 86 LB2D4 FCB SKP1LD SKIP ONE BYTE - ‘OR’ FLAG = $4F +1760 +1761 * LOGICAL OPERATOR ‘AND’ JUMPS HERE +1762 e559 4f LB2D5 CLRA AND FLAG = 0 +1763 e55a 97 03 STA TMPLOC AND/OR FLAG +1764 e55c bd e6 71 JSR INTCNV CONVERT FPA0 INTO AN INTEGER IN ACCD +1765 e55f dd 01 STD CHARAC TEMP SAVE ACCD +1766 e561 bd ee 93 JSR LBC4A MOVE FPA1 TO FPA0 +1767 e564 bd e6 71 JSR INTCNV CONVERT FPA0 INTO AN INTEGER IN ACCD +1768 e567 0d 03 TST TMPLOC CHECK AND/OR FLAG +1769 e569 26 06 BNE LB2ED BRANCH IF OR +1770 e56b 94 01 ANDA CHARAC * ‘AND’ ACCD WITH FPA0 INTEGER +1771 e56d d4 02 ANDB ENDCHR * STORED IN ENDCHR +1772 e56f 20 04 BRA LB2F1 CONVERT TO FP +1773 e571 9a 01 LB2ED ORA CHARAC * ‘OR’ ACCD WITH FPA0 INTEGER +1774 e573 da 02 ORB ENDCHR * STORED IN CHARAC +1775 e575 7e e7 78 LB2F1 JMP GIVABF CONVERT THE VALUE IN ACCD INTO A FP NUMBER +1776 +1777 * RELATIONAL COMPARISON PROCESS HANDLER +1778 e578 bd e3 d1 LB2F4 JSR LB148 ‘TM’ ERROR IF TYPE MISMATCH +1779 e57b 26 10 BNE LB309 BRANCH IF STRING VARIABLE +1780 e57d 96 61 LDA FP1SGN * ‘PACK’ THE MANTISSA +1781 e57f 8a 7f ORA #$7F * SIGN OF FPA1 INTO +1782 e581 94 5d ANDA FPA1 * BIT 7 OF THE +1783 e583 97 5d STA FPA1 * MANTISSA MS BYTE +1784 e585 8e 00 5c LDX #FP1EXP POINT X TO FPA1 +1785 e588 bd ee df JSR LBC96 COMPARE FPA0 TO FPA1 +1786 e58b 20 36 BRA LB33F CHECK TRUTH OF RELATIONAL COMPARISON +1787 +1788 * RELATIONAL COMPARISON OF STRINGS +1789 e58d 0f 06 LB309 CLR VALTYP SET VARIABLE TYPE TO NUMERIC +1790 e58f 0a 3f DEC TRELFL REMOVE STRING TYPE FLAG (BIT0=1 FOR STRINGS) FROM THE +1791 * DESIRED RELATIONAL COMPARISON DATA +1792 e591 bd e8 db JSR LB657 GET LENGTH AND ADDRESS OF STRING WHOSE +1793 * DESCRIPTOR ADDRESS IS IN THE BOTTOM OF FPA0 +1794 e594 d7 56 STB STRDES * SAVE LENGTH AND ADDRESS IN TEMPORARY +1795 e596 9f 58 STX STRDES+2 * DESCRIPTOR (STRING B) +1796 e598 9e 5f LDX FPA1+2 = RETURN LENGTH AND ADDRESS OF STRING +1797 e59a bd e8 dd JSR LB659 = WHOSE DESCRIPTOR ADDRESS IS STORED IN FPA1+2 +1798 e59d 96 56 LDA STRDES LOAD ACCA WITH LENGTH OF STRING B +1799 e59f 34 04 PSHS B SAVE LENGTH A ON STACK +1800 e5a1 a0 e0 SUBA ,S+ SUBTRACT LENGTH A FROM LENGTH B +1801 e5a3 27 07 BEQ LB328 BRANCH IF STRINGS OF EQUAL LENGTH +1802 e5a5 86 01 LDA #1 TRUE FLAG +1803 e5a7 24 03 BCC LB328 TRUE IF LENGTH B > LENGTH A +1804 e5a9 d6 56 LDB STRDES LOAD ACCB WITH LENGTH B +1805 e5ab 40 NEGA SET FLAG = FALSE (1FF) +1806 e5ac 97 54 LB328 STA FP0SGN SAVE TRUE/FALSE FLAG +1807 e5ae de 58 LDU STRDES+2 POINT U TO START OF STRING +1808 e5b0 5c INCB COMPENSATE FOR THE DECB BELOW +1809 * ENTER WITH ACCB CONTAINING LENGTH OF SHORTER STRING +1810 e5b1 5a LB32D DECB DECREMENT SHORTER STRING LENGTH +1811 e5b2 26 04 BNE LB334 BRANCH IF ALL OF STRING NOT COMPARED +1812 e5b4 d6 54 LDB FP0SGN GET TRUE/FALSE FLAB +1813 e5b6 20 0b BRA LB33F CHECK TRUTH OF RELATIONAL COMPARISON +1814 e5b8 a6 80 LB334 LDA ,X+ GET A BYTE FROM STRING A +1815 e5ba a1 c0 CMPA ,U+ COMPARE TO STRING B +1816 e5bc 27 f3 BEQ LB32D CHECK ANOTHER CHARACTER IF = +1817 e5be c6 ff LDB #$FF FALSE FLAG IF STRING A > B +1818 e5c0 24 01 BCC LB33F BRANCH IF STRING A > STRING B +1819 e5c2 50 NEGB SET FLAG = TRUE +1820 +1821 * DETERMINE TRUTH OF COMPARISON - RETURN RESULT IN FPA0 +1822 e5c3 cb 01 LB33F ADDB #1 CONVERT $FF,0,1 TO 0,1,2 +1823 e5c5 59 ROLB NOW IT’S 1,2,4 FOR > = < +1824 e5c6 d4 0a ANDB RELFLG ‘AND’ THE ACTUAL COMPARISON WITH THE DESIRED - +1825 COMPARISON +1826 e5c8 27 02 BEQ LB348 BRANCH IF FALSE (NO MATCHING BITS) +1827 e5ca c6 ff LDB #$FF TRUE FLAG +1828 e5cc 7e ee c5 LB348 JMP LBC7C CONVERT ACCB INTO FP NUMBER IN FPA0 +1829 +1830 * DIM +1831 e5cf bd e4 f6 LB34B JSR LB26D SYNTAX CHECK FOR COMMA +1832 e5d2 c6 01 DIM LDB #1 DIMENSION FLAG +1833 e5d4 8d 08 BSR LB35A SAVE ARRAY SPACE FOR THIS VARIABLE +1834 e5d6 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +1835 e5d8 26 f5 BNE LB34B KEEP DIMENSIONING IF NOT END OF LINE +1836 e5da 39 RTS +1837 * EVALUATE A VARIABLE - RETURN X AND +1838 * VARPTR POINTING TO VARIABLE DESCRIPTOR +1839 * EACH VARIABLE REQUIRES 7 BYTES - THE FIRST TWO +1840 * BYTES ARE THE VARIABLE NAME AND THE NEXT 5 +1841 * BYTES ARE THE DESCRIPTOR. IF BIT 7 OF THE +1842 * FIRST BYTE OF VARlABLE NAME IS SET, THE +1843 * VARIABLE IS A DEF FN VARIABLE. IF BIT 7 OF +1844 * THE SECOND BYTE OF VARIABLE NAME IS SET, THE +1845 * VARIABLE IS A STRING, OTHERWISE THE VARIABLE +1846 * IS NUMERIC. +1847 * IF THE VARIABLE IS NOT FOUND, A ZERO VARIABLE IS +1848 * INSERTED INTO THE VARIABLE SPACE +1849 e5db 5f LB357 CLRB DIMENSION FLAG = 0; DO NOT SET UP AN ARRAY +1850 e5dc 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +1851 e5de d7 05 LB35A STB DIMFLG SAVE ARRAY FLAG +1852 * ENTRY POINT FOR DEF FN VARIABLE SEARCH +1853 e5e0 97 37 LB35C STA VARNAM SAVE INPUT CHARACTER +1854 e5e2 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +1855 e5e4 8d 40 BSR LB3A2 SET CARRY IF NOT ALPHA +1856 e5e6 10 25 ff 16 LBCS LB277 SYNTAX ERROR IF NOT ALPHA +1857 e5ea 5f CLRB DEFAULT 2ND VARIABLE CHARACTER TO ZERO +1858 e5eb d7 06 STB VALTYP SET VARIABLE TYPE TO NUMERIC +1859 e5ed 9d 7c JSR GETNCH GET ANOTHER CHARACTER FROM BASIC +1860 e5ef 25 04 BCS LB371 BRANCH IF NUMERIC (2ND CHARACTER IN +1861 * VARIABLE MAY BE NUMERIC) +1862 e5f1 8d 33 BSR LB3A2 SET CARRY IF NOT ALPHA +1863 e5f3 25 0a BCS LB37B BRANCH IF NOT ALPHA +1864 e5f5 1f 89 LB371 TFR A,B SAVE 2ND CHARACTER IN ACCB +1865 * READ INPUT CHARACTERS UNTIL A NON ALPHA OR +1866 * NON NUMERIC IS FOUND - IGNORE ALL CHARACTERS +1867 * IN VARIABLE NAME AFTER THE 1ST TWO +1868 e5f7 9d 7c LB373 JSR GETNCH GET AN INPUT CHARACTER +1869 e5f9 25 fc BCS LB373 BRANCH IF NUMERIC +1870 e5fb 8d 29 BSR LB3A2 SET CARRY IF NOT ALPHA +1871 e5fd 24 f8 BCC LB373 BRANCH IF ALPHA +1872 e5ff 81 24 LB37B CMPA #'$ CHECK FOR A STRING VARIABLE +1873 e601 26 06 BNE LB385 BRANCH IF IT IS NOT A STRING +1874 e603 03 06 COM VALTYP SET VARIABLE TYPE TO STRING +1875 e605 cb 80 ADDB #$80 SET BIT 7 OF 2ND CHARACTER (STRING) +1876 e607 9d 7c JSR GETNCH GET AN INPUT CHARACTER +1877 e609 d7 38 LB385 STB VARNAM+1 SAVE 2ND CHARACTER IN VARNAM+1 +1878 e60b 9a 08 ORA ARYDIS OR IN THE ARRAY DISABLE FLAG - IF = $80, +1879 * DON’T SEARCH FOR VARIABLES IN THE ARRAYS +1880 e60d 80 28 SUBA #'( IS THIS AN ARRAY VARIABLE? +1881 e60f 10 27 00 75 LBEQ LB404 BRANCH IF IT IS +1882 e613 0f 08 CLR ARYDIS RESET THE ARRAY DISABLE FLAG +1883 e615 9e 1b LDX VARTAB POINT X TO THE START OF VARIABLES +1884 e617 dc 37 LDD VARNAM GET VARIABLE IN QUESTION +1885 e619 9c 1d LB395 CMPX ARYTAB COMPARE X TO THE END OF VARIABLES +1886 e61b 27 12 BEQ LB3AB BRANCH IF END OF VARIABLES +1887 e61d 10 a3 81 CMPD ,X++ * COMPARE VARIABLE IN QUESTION TO CURRENT +1888 e620 27 3e BEQ LB3DC * VARIABLE AND BRANCH IF MATCH +1889 e622 30 05 LEAX 5,X = MOVE POINTER TO NEXT VARIABLE AND +1890 e624 20 f3 BRA LB395 = KEEP LOOKING +1891 +1892 * SET CARRY IF NOT UPPER CASE ALPHA +1893 e626 81 41 LB3A2 CMPA #'A * CARRY SET IF < ‘A’ +1894 e628 25 04 BCS LB3AA * +1895 e62a 80 5b SUBA #'Z+1 = +1896 * SUBA #-('Z+1) = CARRY CLEAR IF <= 'Z' +1897 e62c 80 a5 FCB $80,$A5 +1898 e62e 39 LB3AA RTS +1899 * PUT A NEW VARIABLE IN TABLE OF VARIABLES +1900 e62f 8e 00 74 LB3AB LDX #ZERO POINT X TO ZERO LOCATION +1901 e632 ee e4 LDU ,S GET CURRENT RETURN ADDRESS +1902 e634 11 83 e5 10 CMPU #LB287 DID WE COME FROM ‘EVALUATE ALPHA EXPR’? +1903 e638 27 28 BEQ LB3DE YES - RETURN A ZERO VALUE +1904 e63a dc 1f LDD ARYEND * GET END OF ARRAYS ADDRESS AND +1905 e63c dd 43 STD V43 * SAVE IT AT V43 +1906 e63e c3 00 07 ADDD #7 = ADD 7 TO END OF ARRAYS (EACH +1907 e641 dd 41 STD V41 = VARIABLE = 7 BYTES) AND SAVE AT V41 +1908 e643 9e 1d LDX ARYTAB * GET END OF VARIABLES AND SAVE AT V47 +1909 e645 9f 47 STX V47 * +1910 e647 bd de db JSR LAC1E MAKE A SEVEN BYTE SLOT FOR NEW VARIABLE AT +1911 * TOP OF VARIABLES +1912 e64a 9e 41 LDX V41 = GET NEW END OF ARRAYS AND SAVE IT +1913 e64c 9f 1f STX ARYEND = +1914 e64e 9e 45 LDX V45 * GET NEW END OF VARIABLES AND SAVE IT +1915 e650 9f 1d STX ARYTAB * +1916 e652 9e 47 LDX V47 GET OLD END OF VARIABLES +1917 e654 dc 37 LDD VARNAM GET NEW VARIABLE NAME +1918 e656 ed 81 STD ,X++ SAVE VARIABLE NAME +1919 e658 4f CLRA * ZERO OUT THE FP VALUE OF THE NUMERIC +1920 e659 5f CLRB * VARIABLE OR THE LENGTH AND ADDRESS +1921 e65a ed 84 STD ,X * OF A STRING VARIABLE +1922 e65c ed 02 STD 2,X * +1923 e65e a7 04 STA 4,X * +1924 e660 9f 39 LB3DC STX VARPTR STORE ADDRESS OF VARIABLE VALUE +1925 e662 39 LB3DE RTS +1926 * +1927 e663 90 80 00 00 00 LB3DF FCB $90,$80,$00,$00,$00 * FLOATING POINT -32768 +1928 * SMALLEST SIGNED TWO BYTE INTEGER +1929 * +1930 e668 9d 7c LB3E4 JSR GETNCH GET AN INPUT CHARACTER FROM BASIC +1931 e66a bd e3 ca LB3E6 JSR LB141 GO EVALUATE NUMERIC EXPRESSION +1932 e66d 96 54 LB3E9 LDA FP0SGN GET FPA0 MANTISSA SIGN +1933 e66f 2b 5d BMI LB44A ‘FC’ ERROR IF NEGATIVE NUMBER +1934 +1935 +1936 e671 bd e3 cc INTCNV JSR LB143 ‘TM’ ERROR IF STRING VARIABLE +1937 e674 96 4f LDA FP0EXP GET FPA0 EXPONENT +1938 e676 81 90 CMPA #$90 * COMPARE TO 32768 - LARGEST INTEGER EXPONENT AND +1939 e678 25 08 BCS LB3FE * BRANCH IF FPA0 < 32768 +1940 e67a 8e e6 63 LDX #LB3DF POINT X TO FP VALUE OF -32768 +1941 e67d bd ee df JSR LBC96 COMPARE -32768 TO FPA0 +1942 e680 26 4c BNE LB44A ‘FC’ ERROR IF NOT = +1943 e682 bd ef 11 LB3FE JSR LBCC8 CONVERT FPA0 TO A TWO BYTE INTEGER +1944 e685 dc 52 LDD FPA0+2 GET THE INTEGER +1945 e687 39 RTS +1946 * EVALUATE AN ARRAY VARIABLE +1947 e688 dc 05 LB404 LDD DIMFLG GET ARRAY FLAG AND VARIABLE TYPE +1948 e68a 34 06 PSHS B,A SAVE THEM ON STACK +1949 e68c 12 NOP DEAD SPACE CAUSED BY 1.2 REVISION +1950 e68d 5f CLRB RESET DIMENSION COUNTER +1951 e68e 9e 37 LB40A LDX VARNAM GET VARIABLE NAME +1952 e690 34 14 PSHS X,B SAVE VARIABLE NAME AND DIMENSION COUNTER +1953 e692 8d d4 BSR LB3E4 EVALUATE EXPRESSION (DIMENSlON LENGTH) +1954 e694 35 34 PULS B,X,Y PULL OFF VARIABLE NAME, DIMENSlON COUNTER, +1955 * ARRAY FLAG +1956 e696 9f 37 STX VARNAM SAVE VARIABLE NAME AND VARIABLE TYPE +1957 e698 de 52 LDU FPA0+2 GET DIMENSION LENGTH +1958 e69a 34 60 PSHS U,Y SAVE DIMENSION LENGTH, ARRAY FLAG, VARIABLE TYPE +1959 e69c 5c INCB INCREASE DIMENSION COUNTER +1960 e69d 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +1961 e69f 81 2c CMPA #', CHECK FOR ANOTHER DIMENSION +1962 e6a1 27 eb BEQ LB40A BRANCH IF MORE +1963 e6a3 d7 03 STB TMPLOC SAVE DIMENSION COUNTER +1964 e6a5 bd e4 f0 JSR LB267 SYNTAX CHECK FOR A ‘)‘ +1965 e6a8 35 06 PULS A,B * RESTORE VARIABLE TYPE AND ARRAY +1966 e6aa dd 05 STD DIMFLG * FLAG - LEAVE DIMENSION LENGTH ON STACK +1967 e6ac 9e 1d LDX ARYTAB GET START OF ARRAYS +1968 e6ae 9c 1f LB42A CMPX ARYEND COMPARE TO END OF ARRAYS +1969 e6b0 27 21 BEQ LB44F BRANCH IF NO MATCH FOUND +1970 e6b2 dc 37 LDD VARNAM GET VARIABLE IN QUESTION +1971 e6b4 10 a3 84 CMPD ,X COMPARE TO CURRENT VARIABLE +1972 e6b7 27 06 BEQ LB43B BRANCH IF = +1973 e6b9 ec 02 LDD 2,X GET OFFSET TO NEXT ARRAY VARIABLE +1974 e6bb 30 8b LEAX D,X ADD TO CURRENT POINTER +1975 e6bd 20 ef BRA LB42A KEEP SEARCHING +1976 e6bf c6 12 LB43B LDB #2*9 ‘REDIMENSIONED ARRAY’ ERROR +1977 e6c1 96 05 LDA DIMFLG * TEST ARRAY FLAG - IF <>0 YOU ARE TRYING +1978 e6c3 26 0b BNE LB44C * TO REDIMENSION AN ARRAY +1979 e6c5 d6 03 LDB TMPLOC GET NUMBER OF DIMENSIONS IN ARRAY +1980 e6c7 e1 04 CMPB 4,X COMPARE TO THIS ARRAYS DIMENSIONS +1981 e6c9 27 59 BEQ LB4A0 BRANCH IF = +1982 e6cb c6 10 LB447 LDB #8*2 ‘BAD SUBSCRIPT’ +1983 e6cd 8c FCB SKP2 SKIP TWO BYTES +1984 e6ce c6 08 LB44A LDB #4*2 ‘ILLEGAL FUNCTION CALL’ +1985 e6d0 7e df 03 LB44C JMP LAC46 JUMP TO ERROR SERVICING ROUTINE +1986 +1987 * INSERT A NEW ARRAY INTO ARRAY VARIABLES +1988 * EACH SET OF ARRAY VARIABLES IS PRECEEDED BY A DE- +1989 * SCRIPTOR BLOCK COMPOSED OF 5+2*N BYTES WHERE N IS THE +1990 * NUMBER OF DIMENSIONS IN THE ARRAY. THE BLOCK IS DEFINED +1991 * AS FOLLOWS: BYTES 0,1:VARIABLE’S NAME; 2,3:TOTAL LENGTH +1992 * OF ARRAY ITEMS AND DESCRIPTOR BLOCK; 4:NUMBER OF DIMEN- +1993 * ISIONS; 5,6:LENGTH OF DIMENSION 1; 7,8:LENGTH OF DIMEN- +1994 * SION 2;… 4+N,5+N:LENGTH OF DIMENSION N. +1995 +1996 e6d3 cc 00 05 LB44F LDD #5 * 5 BYTES/ARRAY ENTRY SAVE AT COEFPT +1997 e6d6 dd 64 STD COEFPT * +1998 e6d8 dc 37 LDD VARNAM = GET NAME OF ARRAY AND SAVE IN +1999 e6da ed 84 STD ,X = FIRST 2 BYTES OF DESCRIPTOR +2000 e6dc d6 03 LDB TMPLOC GET NUMBER OF DIMENSIONS AND SAVE IN +2001 e6de e7 04 STB 4,X * 5TH BYTE OF DESCRIPTOR +2002 e6e0 bd de f0 JSR LAC33 CHECK FOR ROOM FOR DESCRIPTOR IN FREE RAM +2003 e6e3 9f 41 STX V41 TEMPORARILY SAVE DESCRIPTOR ADDRESS +2004 e6e5 c6 0b LB461 LDB #11 * DEFAULT DIMENSION VALUE:X(10) +2005 e6e7 4f CLRA * +2006 e6e8 0d 05 TST DIMFLG = CHECK ARRAY FLAG AND BRANCH IF +2007 e6ea 27 05 BEQ LB46D = NOT DIMENSIONING AN ARRAY +2008 e6ec 35 06 PULS A,B GET DIMENSION LENGTH +2009 e6ee c3 00 01 ADDD #1 ADD ONE (X(0) HAS A LENGTH OF ONE) +2010 e6f1 ed 05 LB46D STD 5,X SAVE LENGTH OF ARRAY DIMENSION +2011 e6f3 8d 5d BSR LB4CE MULTIPLY ACCUM ARRAY SIZE NUMBER LENGTH +2012 * OF NEW DIMENSION +2013 e6f5 dd 64 STD COEFPT TEMP STORE NEW CURRENT ACCUMULATED ARRAY SIZE +2014 e6f7 30 02 LEAX 2,X BUMP POINTER UP TWO +2015 e6f9 0a 03 DEC TMPLOC * DECREMENT DIMENSION COUNTER AND BRANCH IF +2016 e6fb 26 e8 BNE LB461 * NOT DONE WITH ALL DIMENSIONS +2017 e6fd 9f 0f STX TEMPTR SAVE ADDRESS OF (END OF ARRAY DESCRIPTOR - 5) +2018 e6ff d3 0f ADDD TEMPTR ADD TOTAL SIZE OF NEW ARRAY +2019 e701 10 25 f7 fc LBCS LAC44 ‘OM’ ERROR IF > $FFFF +2020 e705 1f 01 TFR D,X SAVE END OF ARRAY IN X +2021 e707 bd de f4 JSR LAC37 MAKE SURE THERE IS ENOUGH FREE RAM FOR ARRAY +2022 e70a 83 00 35 SUBD #STKBUF-5 SUBTRACT OUT THE (STACK BUFFER - 5) +2023 e70d dd 1f STD ARYEND SAVE NEW END OF ARRAYS +2024 e70f 4f CLRA ZERO = TERMINATOR BYTE +2025 e710 30 1f LB48C LEAX -1,X * STORE TWO TERMINATOR BYTES AT +2026 e712 a7 05 STA 5,X * THE END OF THE ARRAY DESCRIPTOR +2027 e714 9c 0f CMPX TEMPTR * +2028 e716 26 f8 BNE LB48C * +2029 e718 9e 41 LDX V41 GET ADDRESS OF START OF DESCRIPTOR +2030 e71a 96 1f LDA ARYEND GET MSB OF END OF ARRAYS; LSB ALREADY THERE +2031 e71c 93 41 SUBD V41 SUBTRACT OUT ADDRESS OF START OF DESCRIPTOR +2032 e71e ed 02 STD 2,X SAVE LENGTH OF (ARRAY AND DESCRIPTOR) +2033 e720 96 05 LDA DIMFLG * GET ARRAY FLAG AND BRANCH +2034 e722 26 2d BNE LB4CD * BACK IF DIMENSIONING +2035 * CALCULATE POINTER TO CORRECT ELEMENT +2036 e724 e6 04 LB4A0 LDB 4,X GET THE NUMBER OF DIMENSIONS +2037 e726 d7 03 STB TMPLOC TEMPORARILY SAVE +2038 e728 4f CLRA * INITIALIZE POINTER +2039 e729 5f CLRB * TO ZERO +2040 e72a dd 64 LB4A6 STD COEFPT SAVE ACCUMULATED POINTER +2041 e72c 35 06 PULS A,B * PULL DIMENSION ARGUMENT OFF THE +2042 e72e dd 52 STD FPA0+2 * STACK AND SAVE IT +2043 e730 10 a3 05 CMPD 5,X COMPARE TO STORED ‘DIM’ ARGUMENT +2044 e733 24 3a BCC LB4EB ‘BS’ ERROR IF > = "DIM" ARGUMENT +2045 e735 de 64 LDU COEFPT * GET ACCUMULATED POINTER AND +2046 e737 27 04 BEQ LB4B9 * BRANCH IF 1ST DIMENSION +2047 e739 8d 17 BSR LB4CE = MULTIPLY ACCUMULATED POINTER AND DIMENSION +2048 e73b d3 52 ADDD FPA0+2 = LENGTH AND ADD TO CURRENT ARGUMENT +2049 e73d 30 02 LB4B9 LEAX 2,X MOVE POINTER TO NEXT DIMENSION +2050 e73f 0a 03 DEC TMPLOC * DECREMENT DIMENSION COUNTER AND +2051 e741 26 e7 BNE LB4A6 * BRANCH IF ANY DIMENSIONS LEFT +2052 * MULTIPLY ACCD BY 5 - 5 BYTES/ARRAY VALUE +2053 e743 ed e3 STD ,--S +2054 e745 58 ASLB +2055 e746 49 ROLA TIMES 2 +2056 e747 58 ASLB +2057 e748 49 ROLA TIMES 4 +2058 e749 e3 e1 ADDD ,S++ TIMES 5 +2059 e74b 30 8b LEAX D,X ADD OFFSET TO START OF ARRAY +2060 e74d 30 05 LEAX 5,X ADJUST POINTER FOR SIZE OF DESCRIPTOR +2061 e74f 9f 39 STX VARPTR SAVE POINTER TO ARRAY VALUE +2062 e751 39 LB4CD RTS +2063 * MULTIPLY 2 BYTE NUMBER IN 5,X BY THE 2 BYTE NUMBER +2064 * IN COEFPT. RETURN RESULT IN ACCD, BS ERROR IF > $FFFF +2065 e752 86 10 LB4CE LDA #16 16 SHIFTS TO DO A MULTIPLY +2066 e754 97 45 STA V45 SHIFT COUNTER +2067 e756 ec 05 LDD 5,X * GET SIZE OF DIMENSION +2068 e758 dd 17 STD BOTSTK * AND SAVE IT +2069 e75a 4f CLRA * ZERO +2070 e75b 5f CLRB * ACCD +2071 e75c 58 LB4D8 ASLB = SHIFT ACCB LEFT +2072 e75d 49 ROLA = ONE BIT +2073 e75e 25 0f BCS LB4EB BS' ERROR IF CARRY +2074 e760 08 65 ASL COEFPT+1 * SHIFT MULTIPLICAND LEFT ONE +2075 e762 09 64 ROL COEFPT * BIT - ADD MULTIPLIER TO ACCUMULATOR +2076 e764 24 04 BCC LB4E6 * IF CARRY <> 0 +2077 e766 d3 17 ADDD BOTSTK ADD MULTIPLIER TO ACCD +2078 e768 25 05 BCS LB4EB BS' ERROR IF CARRY (>$FFFF) +2079 e76a 0a 45 LB4E6 DEC V45 * DECREMENT SHIFT COUNTER +2080 e76c 26 ee BNE LB4D8 * IF NOT DONE +2081 e76e 39 RTS +2082 e76f 7e e6 cb LB4EB JMP LB447 BS' ERROR +2083 * +2084 * MEM +2085 * THIS IS NOT A TRUE INDICATOR OF FREE MEMORY BECAUSE +2086 * BASIC REQUIRES A STKBUF SIZE BUFFER FOR THE STACK +2087 * FOR WHICH MEM DOES NOT ALLOW. +2088 * +2089 e772 1f 40 MEM TFR S,D PUT STACK POINTER INTO ACCD +2090 e774 93 1f SUBD ARYEND SUBTRACT END OF ARRAYS +2091 e776 21 FCB SKP1 SKIP ONE BYTE +2092 *CONVERT THE VALUE IN ACCB INTO A FP NUMBER IN FPA0 +2093 e777 4f LB4F3 CLRA CLEAR MS BYTE OF ACCD +2094 * CONVERT THE VALUE IN ACCD INTO A FLOATING POINT NUMBER IN FPA0 +2095 e778 0f 06 GIVABF CLR VALTYP SET VARIABLE TYPE TO NUMERIC +2096 e77a dd 50 STD FPA0 SAVE ACCD IN TOP OF FACA +2097 e77c c6 90 LDB #$90 EXPONENT REQUIRED IF THE TOP TWO BYTES +2098 * OF FPA0 ARE TO BE TREATED AS AN INTEGER IN FPA0 +2099 e77e 7e ee cb JMP LBC82 CONVERT THE REST OF FPA0 TO AN INTEGER +2100 +2101 * STR$ +2102 e781 bd e3 cc STR JSR LB143 TM' ERROR IF STRING VARIABLE +2103 e784 ce 01 f0 LDU #STRBUF+2 *CONVERT FP NUMBER TO ASCII STRING IN +2104 e787 bd f0 25 JSR LBDDC *THE STRING BUFFER +2105 e78a 32 62 LEAS 2,S PURGE THE RETURN ADDRESS FROM THE STACK +2106 e78c 8e 01 ef LDX #STRBUF+1 *POINT X TO STRING BUFFER AND SAVE +2107 e78f 20 0b BRA LB518 *THE STRING IN THE STRING SPACE +2108 * RESERVE ACCB BYTES OF STRING SPACE. RETURN START +2109 * ADDRESS IN (X) AND FRESPC +2110 e791 9f 4d LB50D STX V4D SAVE X IN V4D +2111 e793 8d 5c LB50F BSR LB56D RESERVE ACCB BYTES IN STRING SPACE +2112 e795 9f 58 LB511 STX STRDES+2 SAVE NEW STRING ADDRESS +2113 e797 d7 56 STB STRDES SAVE LENGTH OF RESERVED BLOCK +2114 e799 39 RTS +2115 e79a 30 1f LB516 LEAX -1,X MOVE POINTER BACK ONE +2116 * SCAN A LINE FROM (X) UNTIL AN END OF LINE FLAG (ZERO) OR +2117 * EITHER OF THE TWO TERMINATORS STORED IN CHARAC OR ENDCHR IS MATCHED. +2118 * THE RESULTING STRING IS STORED IN THE STRING SPACE +2119 * ONLY IF THE START OF THE STRING IS <= STRBUF+2 +2120 e79c 86 22 LB518 LDA #'" * INITIALIZE +2121 e79e 97 01 STA CHARAC * TERMINATORS +2122 e7a0 97 02 LB51A STA ENDCHR * TO " +2123 e7a2 30 01 LB51E LEAX 1,X MOVE POINTER UP ONE +2124 e7a4 9f 62 STX RESSGN TEMPORARILY SAVE START OF STRING +2125 e7a6 9f 58 STX STRDES+2 SAVE START OF STRING IN TEMP DESCRIPTOR +2126 e7a8 c6 ff LDB #-1 INITIALIZE CHARACTER COUNTER TO - 1 +2127 e7aa 5c LB526 INCB INCREMENT CHARACTER COUNTER +2128 e7ab a6 80 LDA ,X+ GET CHARACTER +2129 e7ad 27 0c BEQ LB537 BRANCH IF END OF LINE +2130 e7af 91 01 CMPA CHARAC * CHECK FOR TERMINATORS +2131 e7b1 27 04 BEQ LB533 * IN CHARAC AND ENDCHR +2132 e7b3 91 02 CMPA ENDCHR * DON’T MOVE POINTER BACK +2133 e7b5 26 f3 BNE LB526 * ONE IF TERMINATOR IS "MATCHED" +2134 e7b7 81 22 LB533 CMPA #'" = COMPARE CHARACTER TO STRING DELIMITER +2135 e7b9 27 02 BEQ LB539 = & DON’T MOVE POINTER BACK IF SO +2136 e7bb 30 1f LB537 LEAX -1,X MOVE POINTER BACK ONE +2137 e7bd 9f 64 LB539 STX COEFPT SAVE END OF STRING ADDRESS +2138 e7bf d7 56 STB STRDES SAVE STRING LENGTH IN TEMP DESCRIPTOR +2139 e7c1 de 62 LDU RESSGN GET INITlAL STRING START +2140 e7c3 11 83 01 f0 CMPU #STRBUF+2 COMPARE TO START OF STRING BUFFER +2141 e7c7 22 07 LB543 BHI LB54C BRANCH IF > START OF STRING BUFFER +2142 e7c9 8d c6 BSR LB50D GO RESERVE SPACE FOR THE STRING +2143 e7cb 9e 62 LDX RESSGN POINT X TO THE BEGINNING OF THE STRING +2144 e7cd bd e8 c9 JSR LB645 MOVE (B) BYTES FROM (X) TO +2145 * [FRESPC] - MOVE STRING DATA +2146 * PUT DIRECT PAGE STRING DESCRIPTOR BUFFER DATA +2147 * ON THE STRING STACK. SET VARIABLE TYPE TO STRING +2148 e7d0 9e 0b LB54C LDX TEMPPT GET NEXT AVAILABLE STRING STACK DESCRIPTOR +2149 e7d2 8c 00 f1 CMPX #LINHDR COMPARE TO TOP OF STRING DESCRIPTOR STACK - WAS #CFNBUF +2150 e7d5 26 05 BNE LB558 FORMULA O.K. +2151 e7d7 c6 1e LDB #15*2 STRING FORMULA TOO COMPLEX' ERROR +2152 e7d9 7e df 03 LB555 JMP LAC46 JUMP TO ERROR SERVICING ROUTINE +2153 e7dc 96 56 LB558 LDA STRDES * GET LENGTH OF STRING AND SAVE IT +2154 * STA ,X * IN BYTE 0 OF DESCRIPTOR +2155 e7de a7 00 FCB $A7,$00 +2156 e7e0 dc 58 LDD STRDES+2 = GET START ADDRESS OF ACTUAL STRING +2157 e7e2 ed 02 STD 2,X = AND SAVE IN BYTES 2,3 OF DESCRIPTOR +2158 e7e4 86 ff LDA #$FF * VARIABLE TYPE = STRING +2159 e7e6 97 06 STA VALTYP * SAVE IN VARIABLE TYPE FLAG +2160 e7e8 9f 0d STX LASTPT = SAVE START OF DESCRIPTOR +2161 e7ea 9f 52 STX FPA0+2 = ADDRESS IN LASTPT AND FPA0 +2162 e7ec 30 05 LEAX 5,X 5 BYTES/STRING DESCRIPTOR +2163 e7ee 9f 0b STX TEMPPT NEXT AVAILABLE STRING VARIABLE DESCRIPTOR +2164 e7f0 39 RTS +2165 * RESERVE ACCB BYTES IN STRING STORAGE SPACE +2166 * RETURN WITH THE STARTING ADDRESS OF THE +2167 * RESERVED STRING SPACE IN (X) AND FRESPC +2168 e7f1 0f 07 LB56D CLR GARBFL CLEAR STRING REORGANIZATION FLAG +2169 e7f3 4f LB56F CLRA * PUSH THE LENGTH OF THE +2170 e7f4 34 06 PSHS B,A * STRING ONTO THE STACK +2171 e7f6 dc 23 LDD STRTAB GET START OF STRING VARIABLES +2172 e7f8 a3 e0 SUBD ,S+ SUBTRACT STRING LENGTH +2173 e7fa 10 93 21 CMPD FRETOP COMPARE TO START OF STRING STORAGE +2174 e7fd 25 0a BCS LB585 IF BELOW START, THEN REORGANIZE +2175 e7ff dd 23 STD STRTAB SAVE NEW START OF STRING VARIABLES +2176 e801 9e 23 LDX STRTAB GET START OF STRING VARIABLES +2177 e803 30 01 LEAX 1,X ADD ONE +2178 e805 9f 25 STX FRESPC SAVE START ADDRESS OF NEWLY RESERVED SPACE +2179 e807 35 84 PULS B,PC RESTORE NUMBER OF BYTES RESERVED AND RETURN +2180 e809 c6 1a LB585 LDB #2*13 OUT OF STRING SPACE' ERROR +2181 e80b 03 07 COM GARBFL TOGGLE REORGANIZATiON FLAG +2182 e80d 27 ca BEQ LB555 ERROR IF FRESHLY REORGANIZED +2183 e80f 8d 04 BSR LB591 GO REORGANIZE STRING SPACE +2184 e811 35 04 PULS B GET BACK THE NUMBER OF BYTES TO RESERVE +2185 e813 20 de BRA LB56F TRY TO RESERVE ACCB BYTES AGAIN +2186 * REORGANIZE THE STRING SPACE +2187 e815 9e 27 LB591 LDX MEMSIZ GET THE TOP OF STRING SPACE +2188 e817 9f 23 LB593 STX STRTAB SAVE TOP OF UNORGANIZED STRING SPACE +2189 e819 4f CLRA * ZERO OUT ACCD +2190 e81a 5f CLRB * AND RESET VARIABLE +2191 e81b dd 4b STD V4B * POINTER TO 0 +2192 e81d 9e 21 LDX FRETOP POINT X TO START OF STRING SPACE +2193 e81f 9f 47 STX V47 SAVE POINTER IN V47 +2194 e821 8e 00 c9 LDX #STRSTK POINT X TO START OF STRING DESCRIPTOR STACK +2195 e824 9c 0b LB5A0 CMPX TEMPPT COMPARE TO ADDRESS OF NEXT AVAILABLE DESCRIPTOR +2196 e826 27 04 BEQ LB5A8 BRANCH IF TOP OF STRING STACK +2197 e828 8d 32 BSR LB5D8 CHECK FOR STRING IN UNORGANIZED STRING SPACE +2198 e82a 20 f8 BRA LB5A0 KEEP CHECKING +2199 e82c 9e 1b LB5A8 LDX VARTAB GET THE END OF BASIC PROGRAM +2200 e82e 9c 1d LB5AA CMPX ARYTAB COMPARE TO END OF VARIABLES +2201 e830 27 04 BEQ LB5B2 BRANCH IF AT TOP OF VARIABLES +2202 e832 8d 22 BSR LB5D2 CHECK FOR STRING IN UNORGANIZED STRING SPACE +2203 e834 20 f8 BRA LB5AA KEEP CHECKING VARIABLES +2204 e836 9f 41 LB5B2 STX V41 SAVE ADDRESS OF THE END OF VARIABLES +2205 e838 9e 41 LB5B4 LDX V41 GET CURRENT ARRAY POINTER +2206 e83a 9c 1f LB5B6 CMPX ARYEND COMPARE TO THE END OF ARRAYS +2207 e83c 27 35 BEQ LB5EF BRANCH IF AT END OF ARRAYS +2208 e83e ec 02 LDD 2,X GET LENGTH OF ARRAY AND DESCRIPTOR +2209 e840 d3 41 ADDD V41 * ADD TO CURRENT ARRAY POINTER +2210 e842 dd 41 STD V41 * AND SAVE IT +2211 e844 a6 01 LDA 1,X GET 1ST CHARACTER OF VARIABLE NAME +2212 e846 2a f0 BPL LB5B4 BRANCH IF NUMERIC ARRAY +2213 e848 e6 04 LDB 4,X GET THE NUMBER OF DIMENSIONS IN THIS ARRAY +2214 e84a 58 ASLB MULTIPLY BY 2 +2215 e84b cb 05 ADDB #5 ADD FIVE BYTES (VARIABLE NAME, ARRAY +2216 * LENGTH, NUMBER DIMENSIONS) +2217 e84d 3a ABX X NOW POINTS TO START OF ARRAY ELEMENTS +2218 e84e 9c 41 LB5CA CMPX V41 AT END OF THIS ARRAY? +2219 e850 27 e8 BEQ LB5B6 YES - CHECK FOR ANOTHER +2220 e852 8d 08 BSR LB5D8 CHECK FOR STRING LOCATED IN +2221 * UNORGANIZED STRING SPACE +2222 e854 20 f8 BRA LB5CA KEEP CHECKING ELEMENTS IN THIS ARRAY +2223 e856 a6 01 LB5D2 LDA 1,X GET F1RST BYTE OF VARIABLE NAME +2224 e858 30 02 LEAX 2,X MOVE POINTER TO DESCRIPTOR +2225 e85a 2a 14 BPL LB5EC BRANCH IF VARIABLE IS NUMERIC +2226 * SEARCH FOR STRING - ENTER WITH X POINTING TO +2227 * THE STRING DESCRIPTOR. IF STRING IS STORED +2228 * BETWEEN V47 AND STRTAB, SAVE DESCRIPTOR POINTER +2229 * IN V4B AND RESET V47 TO STRING ADDRESS +2230 e85c e6 84 LB5D8 LDB ,X GET THE LENGTH OF THE STRING +2231 e85e 27 10 BEQ LB5EC BRANCH IF NULL - NO STRING +2232 e860 ec 02 LDD 2,X GET STARTING ADDRESS OF THE STRING +2233 e862 10 93 23 CMPD STRTAB COMPARE TO THE START OF STRING VARIABLES +2234 e865 22 09 BHI LB5EC BRANCH IF THIS STRING IS STORED IN +2235 * THE STRING VARIABLES +2236 e867 10 93 47 CMPD V47 COMPARE TO START OF STRING SPACE +2237 e86a 23 04 BLS LB5EC BRANCH IF NOT STORED IN THE STRING SPACE +2238 e86c 9f 4b STX V4B SAVE VARIABLE POINTER IF STORED IN STRING SPACE +2239 e86e dd 47 STD V47 SAVE STRING STARTING ADDRESS +2240 e870 30 05 LB5EC LEAX 5,X MOVE TO NEXT VARIABLE DESCRIPTOR +2241 e872 39 LB5EE RTS +2242 e873 9e 4b LB5EF LDX V4B GET ADDRESS OF THE DESCRIPTOR FOR THE +2243 * STRING WHICH IS STORED IN THE HIGHEST RAM ADDRESS IN +2244 * THE UNORGANIZED STRING SPACE +2245 e875 27 fb BEQ LB5EE BRANCH IF NONE FOUND AND REORGANIZATION DONE +2246 e877 4f CLRA CLEAR MS BYTE OF LENGTH +2247 e878 e6 84 LDB ,X GET LENGTH OF STRING +2248 e87a 5a DECB SUBTRACT ONE +2249 e87b d3 47 ADDD V47 ADD LENGTH OF STRING TO ITS STARTING ADDRESS +2250 e87d dd 43 STD V43 SAVE AS MOVE STARTING ADDRESS +2251 e87f 9e 23 LDX STRTAB POINT X TO THE START OF ORGANIZED STRING VARIABLES +2252 e881 9f 41 STX V41 SAVE AS MOVE ENDING ADDRESS +2253 e883 bd de dd JSR LAC20 MOVE STRING FROM CURRENT POSITION TO THE +2254 * TOP OF UNORGANIZED STRING SPACE +2255 e886 9e 4b LDX V4B POINT X TO STRING DESCRIPTOR +2256 e888 dc 45 LDD V45 * GET NEW STARTING ADDRESS OF STRING AND +2257 e88a ed 02 STD 2,X * SAVE IT IN DESCRIPTOR +2258 e88c 9e 45 LDX V45 GET NEW TOP OF UNORGANIZED STRING SPACE +2259 e88e 30 1f LEAX -1,X MOVE POINTER BACK ONE +2260 e890 7e e8 17 JMP LB593 JUMP BACK AND REORGANIZE SOME MORE +2261 +2262 +2263 e893 dc 52 LB60F LDD FPA0+2 * GET DESCRIPTOR ADDRESS OF STRING A +2264 e895 34 06 PSHS B,A * AND SAVE IT ON THE STACK +2265 e897 bd e4 ac JSR LB223 GET DESCRIPTOR ADDRESS OF STRING B +2266 e89a bd e3 cf JSR LB146 TM' ERROR IF NUMERIC VARIABLE +2267 e89d 35 10 PULS X * POINT X TO STRING A DESCRIPTOR +2268 e89f 9f 62 STX RESSGN * ADDRESS AND SAVE IT IN RESSGN +2269 e8a1 e6 84 LDB ,X GET LENGTH OF STRING A +2270 e8a3 9e 52 LDX FPA0+2 POINT X TO DESCRIPTOR OF STRING B +2271 e8a5 eb 84 ADDB ,X ADD LENGTH OF STRING B TO STR1NG A +2272 e8a7 24 05 BCC LB62A BRANCH IF LENGTH < 256 +2273 e8a9 c6 1c LDB #2*14 STRING TOO LONG' ERROR IF LENGTH > 255 +2274 e8ab 7e df 03 JMP LAC46 JUMP TO ERROR SERVICING ROUTINE +2275 e8ae bd e7 91 LB62A JSR LB50D RESERVE ROOM IN STRING SPACE FOR NEW STRING +2276 e8b1 9e 62 LDX RESSGN GET DESCRIPTOR ADDRESS OF STRING A +2277 e8b3 e6 84 LDB ,X GET LENGTH OF STRING A +2278 e8b5 8d 10 BSR LB643 MOVE STRING A INTO RESERVED BUFFER IN STRING SPACE +2279 e8b7 9e 4d LDX V4D GET DESCRIPTOR ADDRESS OF STRING B +2280 e8b9 8d 22 BSR LB659 GET LENGTH AND ADDRESS OF STRING B +2281 e8bb 8d 0c BSR LB645 MOVE STRING B INTO REST OF RESERVED BUFFER +2282 e8bd 9e 62 LDX RESSGN POINT X TO DESCRIPTOR OF STRING A +2283 e8bf 8d 1c BSR LB659 DELETE STRING A IF LAST STRING ON STRING STACK +2284 e8c1 bd e7 d0 JSR LB54C PUT STRING DESCRIPTOR ON THE STRING STACK +2285 e8c4 7e e3 f1 JMP LB168 BRANCH BACK TO EXPRESSION EVALUATION +2286 +2287 * MOVE (B) BYTES FROM 2,X TO FRESPC +2288 e8c7 ae 02 LB643 LDX 2,X POINT X TO SOURCE ADDRESS +2289 e8c9 de 25 LB645 LDU FRESPC POINT U TO DESTINATION ADDRESS +2290 e8cb 5c INCB COMPENSATION FOR THE DECB BELOW +2291 e8cc 20 04 BRA LB64E GO MOVE THE BYTES +2292 * MOVE B BYTES FROM (X) TO (U) +2293 e8ce a6 80 LB64A LDA ,X+ * GET A SOURCE BYTE AND MOVE IT +2294 e8d0 a7 c0 STA ,U+ * TO THE DESTINATION +2295 e8d2 5a LB64E DECB DECREMENT BYTE COUNTER +2296 e8d3 26 f9 BNE LB64A BRANCH IF ALL BYTES NOT MOVED +2297 e8d5 df 25 STU FRESPC SAVE ENDING ADDRESS IN FRESPC +2298 e8d7 39 RTS +2299 * RETURN LENGTH (ACCB) AND ADDRESS (X) OF +2300 * STRING WHOSE DESCRIPTOR IS IN FPA0+2 +2301 * DELETE THE STRING IF IT IS THE LAST ONE +2302 * PUT ON THE STRING STACK. REMOVE STRING FROM STRING +2303 * SPACE IF IT IS AT THE BOTTOM OF STRING VARIABLES. +2304 e8d8 bd e3 cf LB654 JSR LB146 TM' ERROR IF VARIABLE TYPE = NUMERIC +2305 e8db 9e 52 LB657 LDX FPA0+2 GET ADDRESS OF SELECTED STRING DESCRIPTOR +2306 e8dd e6 84 LB659 LDB ,X GET LENGTH OF STRING +2307 e8df 8d 18 BSR LB675 * CHECK TO SEE IF THIS STRING DESCRIPTOR WAS +2308 e8e1 26 13 BNE LB672 * THE LAST ONE PUT ON THE STRING STACK AND +2309 * * BRANCH IF NOT +2310 e8e3 ae 07 LDX 5+2,X GET START ADDRESS OF STRING JUST REMOVED +2311 e8e5 30 1f LEAX -1,X MOVE POINTER DOWN ONE +2312 e8e7 9c 23 CMPX STRTAB COMPARE TO START OF STRING VARIABLES +2313 e8e9 26 08 BNE LB66F BRANCH IF THIS STRING IS NOT AT THE BOTTOM +2314 * OF STRING VARIABLES +2315 e8eb 34 04 PSHS B SAVE LENGTH; ACCA WAS CLEARED +2316 e8ed d3 23 ADDD STRTAB * ADD THE LENGTH OF THE JUST REMOVED STRING +2317 e8ef dd 23 STD STRTAB * TO THE START OF STRING VARIABLES - THIS WILL +2318 * * REMOVE THE STRING FROM THE STRING SPACE +2319 e8f1 35 04 PULS B RESTORE LENGTH +2320 e8f3 30 01 LB66F LEAX 1,X ADD ONE TO POINTER +2321 e8f5 39 RTS +2322 e8f6 ae 02 LB672 LDX 2,X *POINT X TO ADDRESS OF STRING NOT +2323 e8f8 39 RTS *ON THE STRING STACK +2324 * REMOVE STRING FROM STRING STACK. ENTER WITH X +2325 * POINTING TO A STRING DESCRIPTOR - DELETE THE +2326 * STRING FROM STACK IF IT IS ON TOP OF THE +2327 * STACK. IF THE STRING IS DELETED, SET THE ZERO FLAG +2328 e8f9 9c 0d LB675 CMPX LASTPT *COMPARE TO LAST USED DESCRIPTOR ADDRESS +2329 e8fb 26 07 BNE LB680 *ON THE STRING STACK, RETURN IF DESCRIPTOR +2330 * *ADDRESS NOT ON THE STRING STACK +2331 e8fd 9f 0b STX TEMPPT SAVE LAST USED DESCRIPTOR AS NEXT AVAILABLE +2332 e8ff 30 1b LEAX -5,X * MOVE LAST USED DESCRIPTOR BACK 5 BYTES +2333 e901 9f 0d STX LASTPT * AND SAVE AS THE LAST USED DESCRIPTOR ADDR +2334 e903 4f CLRA SET ZERO FLAG +2335 e904 39 LB680 RTS +2336 +2337 * LEN +2338 e905 8d 03 LEN BSR LB686 POINT X TO PROPER STRING AND GET LENGTH +2339 e907 7e e7 77 LB683 JMP LB4F3 CONVERT ACCB TO FP NUMBER IN FPA0 +2340 * POINT X TO STRING ADDRESS LOAD LENGTH INTO +2341 * ACCB. ENTER WITH THE STRING DESCRIPTOR IN +2342 * BOTTOM TWO BYTES OF FPA0 +2343 e90a 8d cc LB686 BSR LB654 GET LENGTH AND ADDRESS OF STRING +2344 e90c 0f 06 CLR VALTYP SET VARIABLE TYPE TO NUMERIC +2345 e90e 5d TSTB SET FLAGS ACCORDING TO LENGTH +2346 e90f 39 RTS +2347 +2348 * CHR$ +2349 e910 bd e9 92 CHR JSR LB70E CONVERT FPA0 TO AN INTEGER IN ACCD +2350 e913 c6 01 LB68F LDB #1 * RESERVE ONE BYTE IN +2351 e915 bd e7 f1 JSR LB56D * THE STRING SPACE +2352 e918 96 53 LDA FPA0+3 GET ASCII STRING VALUE +2353 e91a bd e7 95 JSR LB511 SAVE RESERVED STRING DESCRIPTOR IN TEMP DESCRIPTOR +2354 e91d a7 84 STA ,X SAVE THE STRING (IT’S ONLY ONE BYTE) +2355 e91f 32 62 LB69B LEAS 2,S PURGE THE RETURN ADDRESS OFF OF THE STACK +2356 e921 7e e7 d0 LB69D JMP LB54C PUT TEMP DESCRIPTOR DATA ONTO STRING STACK +2357 +2358 +2359 e924 8d 02 ASC BSR LB6A4 PUT 1ST CHARACTER OF STRING INTO ACCB +2360 e926 20 df BRA LB683 CONVERT ACCB INTO FP NUMBER IN FPA0 +2361 e928 8d e0 LB6A4 BSR LB686 POINT X TO STRING DESCRIPTOR +2362 e92a 27 5e BEQ LB706 FC' ERROR IF NULL STRING +2363 e92c e6 84 LDB ,X GET FIRST BYTE OF STRING +2364 e92e 39 RTS +2365 +2366 +2367 e92f 8d 48 LEFT BSR LB6F5 GET ARGUMENTS FROM STACK +2368 e931 4f LB6AD CLRA CLEAR STRING POINTER OFFSET - OFFSET = 0 FOR LEFT$ +2369 e932 e1 84 LB6AE CMPB ,X * COMPARE LENGTH PARAMETER TO LENGTH OF +2370 e934 23 03 BLS LB6B5 * STRING AND BRANCH IF LENGTH OF STRING +2371 * >= LENGTH PARAMETER +2372 e936 e6 84 LDB ,X USE LENGTH OF STRING OTHERWISE +2373 e938 4f CLRA CLEAR STRING POINTER OFFSET (0 FOR LEFT$) +2374 e939 34 06 LB6B5 PSHS B,A PUSH PARAMETERS ONTO STACK +2375 e93b bd e7 93 JSR LB50F RESERVE ACCB BYTES IN THE STRING SPACE +2376 e93e 9e 4d LDX V4D POINT X TO STRING DESCRIPTOR +2377 e940 8d 9b BSR LB659 GET ADDRESS OF OLD STRING (X=ADDRESS) +2378 e942 35 04 PULS B * PULL STRING POINTER OFFSET OFF OF THE STACK +2379 e944 3a ABX * AND ADD IT TO STRING ADDRESS +2380 e945 35 04 PULS B PULL LENGTH PARAMETER OFF OF THE STACK +2381 e947 bd e8 c9 JSR LB645 MOVE ACCB BYTES FROM (X) TO [FRESPC] +2382 e94a 20 d5 BRA LB69D PUT TEMP STRING DESCRIPTOR ONTO THE STRING STACK +2383 +2384 * RIGHT$ +2385 e94c 8d 2b RIGHT BSR LB6F5 GET ARGUMENTS FROM STACK +2386 e94e a0 84 SUBA ,X ACCA=LENGTH PARAMETER - LENGTH OF OLD STRING +2387 e950 40 NEGA NOW ACCA = LENGTH OF OLD STRING +2388 e951 20 df BRA LB6AE PUT NEW STRING IN THE STRING SPACE +2389 +2390 * MID$ +2391 e953 c6 ff MID LDB #$FF * GET DEFAULT VALUE OF LENGTH AND +2392 e955 d7 53 STB FPA0+3 * SAVE IT IN FPA0 +2393 e957 9d 82 JSR GETCCH GET CURRENT CHARACTER FROM BASIC +2394 e959 81 29 CMPA #') ARGUMENT DELIMITER? +2395 e95b 27 05 BEQ LB6DE YES - NO LENGTH PARAMETER GIVEN +2396 e95d bd e4 f6 JSR LB26D SYNTAX CHECK FOR COMMA +2397 e960 8d 2d BSR LB70B EVALUATE NUMERIC EXPRESSION (LENGTH) +2398 e962 8d 15 LB6DE BSR LB6F5 GET ARGUMENTS FROM STACK +2399 e964 27 24 BEQ LB706 FC' ERROR IF NULL STRING +2400 e966 5f CLRB CLEAR LENGTH COUNTER (DEFAULT VALUE) +2401 e967 4a DECA *SUOTRACT ONE FROM POSITION PARAMETER (THESE +2402 e968 a1 84 CMPA ,X *ROUTINES EXPECT 1ST POSITION TO BE ZERO, NOT ONE) +2403 * *AND COMPARE IT TO LENGTH OF OLD STRING +2404 e96a 24 cd BCC LB6B5 IF POSITION > LENGTH OF OLD STRING, THEN NEW +2405 * STRING WILL BE A NULL STRING +2406 e96c 1f 89 TFR A,B SAVE ABSOLUTE POSITION PARAMETER IN ACCB +2407 e96e e0 84 SUBB ,X ACCB=POSITION-LENGTH OF OLD STRING +2408 e970 50 NEGB NOW ACCB=LENGTH OF OLDSTRING-POSITION +2409 e971 d1 53 CMPB FPA0+3 *IF THE AMOUNT OF OLD STRING TO THE RIGHT OF +2410 e973 23 c4 BLS LB6B5 *POSITION IS <= THE LENGTH PARAMETER, BRANCH AND +2411 * USE ALL OF THE STRING TO THE RIGHT OF THE POSITION +2412 * INSTEAD OF THE LENGTH PARAMETER +2413 e975 d6 53 LDB FPA0+3 GET LENGTH OF NEW STRING +2414 e977 20 c0 BRA LB6B5 PUT NEW STRING IN STRING SPACE +2415 * DO A SYNTAX CHECK FOR ")", THEN PULL THE PREVIOUSLY CALCULATED NUMERIC +2416 * ARGUMENT (ACCD) AND STRING ARGUMENT DESCRIPTOR ADDR OFF OF THE STACK +2417 e979 bd e4 f0 LB6F5 JSR LB267 SYNTAX CHECK FOR A ")" +2418 e97c ee e4 LDU ,S LOAD THE RETURN ADDRESS INTO U REGISTER +2419 e97e ae 65 LDX 5,S * GET ADDRESS OF STRING AND +2420 e980 9f 4d STX V4D * SAVE IT IN V4D +2421 e982 a6 64 LDA 4,S = PUT LENGTH OF STRING IN +2422 e984 e6 64 LDB 4,S = BOTH ACCA AND ACCB +2423 e986 32 67 LEAS 7,S REMOVE DESCRIPTOR AND RETURN ADDRESS FROM STACK +2424 e988 1f 35 TFR U,PC JUMP TO ADDRESS IN U REGISTER +2425 e98a 7e e6 ce LB706 JMP LB44A ILLEGAL FUNCTION CALL' +2426 * EVALUATE AN EXPRESSION - RETURN AN INTEGER IN +2427 * ACCB - 'FC' ERROR IF EXPRESSION > 255 +2428 e98d 9d 7c LB709 JSR GETNCH GET NEXT BASIC INPUT CHARACTER +2429 e98f bd e3 ca LB70B JSR LB141 EVALUATE A NUMERIC EXPRESSION +2430 e992 bd e6 6d LB70E JSR LB3E9 CONVERT FPA0 TO INTEGER IN ACCD +2431 e995 4d TSTA TEST MS BYTE OF INTEGER +2432 e996 26 f2 BNE LB706 FC' ERROR IF EXPRESSION > 255 +2433 e998 0e 82 JMP GETCCH GET CURRENT INPUT CHARACTER FROM BASIC +2434 +2435 * VAL +2436 e99a bd e9 0a VAL JSR LB686 POINT X TO STRING ADDRESS +2437 e99d 10 27 02 e1 LBEQ LBA39 IF NULL STRING SET FPA0 +2438 e9a1 de 83 LDU CHARAD SAVE INPUT POINTER IN REGISTER U +2439 e9a3 9f 83 STX CHARAD POINT INPUT POINTER TO ADDRESS OF STRING +2440 e9a5 3a ABX MOVE POINTER TO END OF STRING TERMINATOR +2441 e9a6 a6 84 LDA ,X GET LAST BYTE OF STRING +2442 e9a8 34 52 PSHS U,X,A SAVE INPUT POINTER, STRING TERMINATOR +2443 * ADDRESS AND CHARACTER +2444 e9aa 6f 84 CLR ,X CLEAR STRING TERMINATOR : FOR ASCII - FP CONVERSION +2445 e9ac 9d 82 JSR GETCCH GET CURRENT CHARACTER FROM BASIC +2446 e9ae bd ef 5b JSR LBD12 CONVERT AN ASCII STRING TO FLOATING POINT +2447 e9b1 35 52 PULS A,X,U RESTORE CHARACTERS AND POINTERS +2448 e9b3 a7 84 STA ,X REPLACE STRING TERMINATOR +2449 e9b5 df 83 STU CHARAD RESTORE INPUT CHARACTER +2450 e9b7 39 RTS +2451 +2452 e9b8 8d 07 LB734 BSR LB73D * EVALUATE AN EXPRESSION, RETURN +2453 e9ba 9f 2b STX BINVAL * THE VALUE IN X; STORE IT IN BINVAL +2454 e9bc bd e4 f6 LB738 JSR LB26D SYNTAX CHECK FOR A COMMA +2455 e9bf 20 ce BRA LB70B EVALUATE EXPRESSION IN RANGE 0 <= X < 256 +2456 * EVALUATE EXPRESSION : RETURN INTEGER PORTION IN X - 'FC' ERROR IF +2457 +2458 e9c1 bd e3 ca LB73D JSR LB141 EVALUATE NUMERIC EXPRESSION +2459 e9c4 96 54 LB740 LDA FP0SGN GET SIGN OF FPA0 MANTISSA +2460 e9c6 2b c2 BMI LB706 ILLEGAL FUNCTION CALL' IF NEGATIVE +2461 e9c8 96 4f LDA FP0EXP GET EXPONENT OF FPA0 +2462 e9ca 81 90 CMPA #$90 COMPARE TO LARGEST POSITIVE INTEGER +2463 e9cc 22 bc BHI LB706 ILLEGAL FUNCTION CALL' IF TOO LARGE +2464 e9ce bd ef 11 JSR LBCC8 SHIFT BINARY POINT TO EXTREME RIGHT OF FPA0 +2465 e9d1 9e 52 LDX FPA0+2 LOAD X WITH LOWER TWO BYTES OF FPA0 +2466 e9d3 39 RTS +2467 +2468 * PEEK +2469 e9d4 8d ee PEEK BSR LB740 CONVERT FPA0 TO INTEGER IN REGISTER X +2470 e9d6 e6 84 LDB ,X GET THE VALUE BEING 'PEEK'ED +2471 e9d8 7e e7 77 JMP LB4F3 CONVERT ACCB INTO A FP NUMBER +2472 +2473 * POKE +2474 e9db 8d db POKE BSR LB734 EVALUATE 2 EXPRESSIONS +2475 e9dd 9e 2b LDX BINVAL GET THE ADDRESS TO BE 'POKE'ED +2476 e9df e7 84 STB ,X STORE THE DATA IN THAT ADDRESS +2477 e9e1 39 RTS +2478 +2479 +2480 * LIST +2481 e9e2 34 01 LIST PSHS CC SAVE ZERO FLAG ON STACK +2482 e9e4 bd e2 14 JSR LAF67 CONVERT DECIMAL LINE NUMBER TO BINARY +2483 e9e7 bd df a2 JSR LAD01 * FIND RAM ADDRESS OF THAT LINE NUMBER AND +2484 e9ea 9f 66 STX LSTTXT * SAVE IT IN LSTTXT +2485 e9ec 35 01 PULS CC GET ZERO FLAG FROM STACK +2486 e9ee 27 12 BEQ LB784 BRANCH IF END OF LINE +2487 e9f0 9d 82 JSR GETCCH GET CURRENT CHARACTER FROM BASIC +2488 e9f2 27 13 BEQ LB789 BRANCH IF END OF LINE +2489 e9f4 81 a7 CMPA #TOK_MINUS MINUS TOKEN (IS IT A RANGE OF LINE NUMBERS?) +2490 e9f6 26 09 BNE LB783 NO - RETURN +2491 e9f8 9d 7c JSR GETNCH GET NEXT CHARACTER FROM BASIC +2492 e9fa 27 06 BEQ LB784 BRANCH IF END OF LINE +2493 e9fc bd e2 14 JSR LAF67 GET ENDING LINE NUMBER +2494 e9ff 27 06 BEQ LB789 BRANCH IF LEGAL LINE NUMBER +2495 ea01 39 LB783 RTS +2496 * LIST THE ENTIRE PROGRAM +2497 ea02 ce ff ff LB784 LDU #$FFFF * SET THE DEFAULT ENDING LINE NUMBER +2498 ea05 df 2b STU BINVAL * TO $FFFF +2499 ea07 32 62 LB789 LEAS 2,S PURGE RETURN ADDRESS FROM THE STACK +2500 ea09 9e 66 LDX LSTTXT POINT X TO STARTING LINE ADDRESS +2501 ea0b bd eb a9 LB78D JSR LB95C MOVE CURSOR TO START OF A NEW LINE +2502 ea0e bd dc 97 JSR LA549 CHECK FOR A BREAK OR PAUSE +2503 ea11 ec 84 LDD ,X GET ADDRESS OF NEXT BASIC LINE +2504 ea13 26 03 BNE LB79F BRANCH IF NOT END OF PROGRAM +2505 LB797 +2506 ea15 7e df 22 JMP LAC73 RETURN TO BASIC’S MAIN INPUT LOOP +2507 ea18 9f 66 LB79F STX LSTTXT SAVE NEW STARTING LINE ADDRESS +2508 ea1a ec 02 LDD 2,X * GET THE LINE NUMBER OF THIS LINE AND +2509 ea1c 10 93 2b CMPD BINVAL * COMPARE IT TO ENDING LINE NUMBER +2510 ea1f 22 f4 BHI LB797 EXIT IF LINE NUMBER > ENDING LINE NUMBER +2511 ea21 bd f0 15 JSR LBDCC PRINT THE NUMBER IN ACCD ON SCREEN IN DECIMAL +2512 ea24 bd eb f5 JSR LB9AC SEND A SPACE TO CONSOLE OUT +2513 ea27 9e 66 LDX LSTTXT GET RAM ADDRESS OF THIS LINE +2514 ea29 8d 10 BSR LB7C2 UNCRUNCH A LINE +2515 ea2b ae 9f 00 66 LDX [LSTTXT] POINT X TO START OF NEXT LINE +2516 ea2f ce 00 f4 LDU #LINBUF+1 POINT U TO BUFFER FULL OF UNCRUNCHED LINE +2517 ea32 a6 c0 LB7B9 LDA ,U+ GET A BYTE FROM THE BUFFER +2518 ea34 27 d5 BEQ LB78D BRANCH IF END OF BUFFER +2519 ea36 bd eb fa JSR LB9B1 SEND CHARACTER TO CONSOLE OUT +2520 ea39 20 f7 BRA LB7B9 GET ANOTHER CHARACTER +2521 +2522 * UNCRUNCH A LINE INTO BASIC’S LINE INPUT BUFFER +2523 ea3b 30 04 LB7C2 LEAX 4,X MOVE POINTER PAST ADDRESS OF NEXT LINE AND LINE NUMBER +2524 ea3d 10 8e 00 f4 LDY #LINBUF+1 UNCRUNCH LINE INTO LINE INPUT BUFFER +2525 ea41 a6 80 LB7CB LDA ,X+ GET A CHARACTER +2526 ea43 27 51 BEQ LB820 BRANCH IF END OF LINE +2527 ea45 2b 15 BMI LB7E6 BRANCH IF IT’S A TOKEN +2528 ea47 81 3a CMPA #': CHECK FOR END OF SUB LINE +2529 ea49 26 0d BNE LB7E2 BRNCH IF NOT END OF SUB LINE +2530 ea4b e6 84 LDB ,X GET CHARACTER FOLLOWING COLON +2531 ea4d c1 84 CMPB #TOK_ELSE TOKEN FOR ELSE? +2532 ea4f 27 f0 BEQ LB7CB YES - DON’T PUT IT IN BUFFER +2533 ea51 c1 83 CMPB #TOK_SNGL_Q TOKEN FOR REMARK? +2534 ea53 27 ec BEQ LB7CB YES - DON’T PUT IT IN BUFFER +2535 ea55 8c FCB SKP2 SKIP TWO BYTES +2536 ea56 86 21 LB7E0 LDA #'! EXCLAMATION POINT +2537 ea58 8d 30 LB7E2 BSR LB814 PUT CHARACTER IN BUFFER +2538 ea5a 20 e5 BRA LB7CB GET ANOTHER CHARACTER +2539 +2540 ea5c ce db e4 LB7E6 LDU #COMVEC-10 FIRST DO COMMANDS +2541 ea5f 81 ff CMPA #$FF CHECK FOR SECONDARY TOKEN +2542 ea61 26 04 BNE LB7F1 BRANCH IF NON SECONDARY TOKEN +2543 ea63 a6 80 LDA ,X+ GET SECONDARY TOKEN +2544 ea65 33 45 LEAU 5,U BUMP IT UP TO SECONDARY FUNCTIONS +2545 ea67 84 7f LB7F1 ANDA #$7F MASK OFF BIT 7 OF TOKEN +2546 ea69 33 4a LB7F3 LEAU 10,U MOVE TO NEXT COMMAND TABLE +2547 ea6b 6d c4 TST ,U IS THIS TABLE ENABLED? +2548 ea6d 27 e7 BEQ LB7E0 NO - ILLEGAL TOKEN +2549 ea6f a0 c4 SUBA ,U SUBTRACT THE NUMBER OF TOKENS FROM THE CURRENT TOKEN NUMBER +2550 ea71 2a f6 BPL LB7F3 BRANCH IF TOKEN NOT IN THIS TABLE +2551 ea73 ab c4 ADDA ,U RESTORE TOKEN NUMBER RELATIVE TO THIS TABLE +2552 ea75 ee 41 LDU 1,U POINT U TO COMMAND DICTIONARY TABLE +2553 ea77 4a LB801 DECA DECREMENT TOKEN NUMBER +2554 ea78 2b 06 BMI LB80A BRANCH IF THIS IS THE CORRECT TOKEN +2555 * SKIP THROUGH DICTIONARY TABLE TO START OF NEXT TOKEN +2556 ea7a 6d c0 LB804 TST ,U+ GRAB A BYTE +2557 ea7c 2a fc BPL LB804 BRANCH IF BIT 7 NOT SET +2558 ea7e 20 f7 BRA LB801 GO SEE IF THIS IS THE CORRECT TOKEN +2559 ea80 a6 c4 LB80A LDA ,U GET A CHARACTER FROM DICTIONARY TABLE +2560 ea82 8d 06 BSR LB814 PUT CHARACTER IN BUFFER +2561 ea84 6d c0 TST ,U+ CHECK FOR START OF NEXT TOKEN +2562 ea86 2a f8 BPL LB80A BRANCH IF NOT DONE WITH THIS TOKEN +2563 ea88 20 b7 BRA LB7CB GO GET ANOTHER CHARACTER +2564 ea8a 10 8c 01 ed LB814 CMPY #LINBUF+LBUFMX TEST FOR END OF LINE INPUT BUFFER +2565 ea8e 24 06 BCC LB820 BRANCH IF AT END OF BUFFER +2566 ea90 84 7f ANDA #$7F MASK OFF BIT 7 +2567 ea92 a7 a0 STA ,Y+ * SAVE CHARACTER IN BUFFER AND +2568 ea94 6f a4 CLR ,Y * CLEAR NEXT CHARACTER SLOT IN BUFFER +2569 ea96 39 LB820 RTS +2570 * +2571 * CRUNCH THE LINE THAT THE INPUT POINTER IS +2572 * POINTING TO INTO THE LINE INPUT BUFFER +2573 * RETURN LENGTH OF CRUNCHED LINE IN ACCD +2574 * +2575 ea97 9e 83 LB821 LDX CHARAD GET BASIC'S INPUT POINTER ADDRESS +2576 ea99 ce 00 f3 LDU #LINBUF POINT X TO LINE INPUT BUFFER +2577 ea9c 0f 43 LB829 CLR V43 CLEAR ILLEGAL TOKEN FLAG +2578 ea9e 0f 44 CLR V44 CLEAR DATA FLAG +2579 eaa0 a6 80 LB82D LDA ,X+ GET INPUT CHAR +2580 eaa2 27 21 BEQ LB852 BRANCH IF END OF LINE +2581 eaa4 0d 43 TST V43 * CHECK ILLEGAL TOKEN FLAG & BRANCH IF NOT +2582 eaa6 27 0f BEQ LB844 * PROCESSING AN ILLEGAL TOKEN +2583 eaa8 bd e6 26 JSR LB3A2 SET CARRY IF NOT UPPER CASE ALPHA +2584 eaab 24 18 BCC LB852 BRANCH IF UPPER CASE ALPHA +2585 eaad 81 30 CMPA #'0 * DON’T CRUNCH ASCII NUMERIC CHARACTERS +2586 eaaf 25 04 BLO LB842 * BRANCH IF NOT NUMERIC +2587 eab1 81 39 CMPA #'9 * +2588 eab3 23 10 BLS LB852 * BRANCH IF NUMERIC +2589 * END UP HERE IF NOT UPPER CASE ALPHA OR NUMERIC +2590 eab5 0f 43 LB842 CLR V43 CLEAR ILLEGAL TOKEN FLAG +2591 eab7 81 20 LB844 CMPA #SPACE SPACE? +2592 eab9 27 0a BEQ LB852 DO NOT REMOVE SPACES +2593 eabb 97 42 STA V42 SAVE INPUT CHARACTER AS SCAN DELIMITER +2594 eabd 81 22 CMPA #'" CHECK FOR STRING DELIMITER +2595 eabf 27 38 BEQ LB886 BRANCH IF STRING +2596 eac1 0d 44 TST V44 * CHECK DATA FLAG AND BRANCH IF CLEAR +2597 eac3 27 19 BEQ LB86B * DO NOT CRUNCH DATA +2598 eac5 a7 c0 LB852 STA ,U+ SAVE CHARACTER IN BUFFER +2599 eac7 27 06 BEQ LB85C BRANCH IF END OF LINE +2600 eac9 81 3a CMPA #': * CHECK FOR END OF SUBLINE +2601 eacb 27 cf BEQ LB829 * AND RESET FLAGS IF END OF SUBLINE +2602 eacd 20 d1 LB85A BRA LB82D GO GET ANOTHER CHARACTER +2603 eacf 6f c0 LB85C CLR ,U+ * DOUBLE ZERO AT END OF LINE +2604 ead1 6f c0 CLR ,U+ * +2605 ead3 1f 30 TFR U,D SAVE ADDRESS OF END OF LINE IN ACCD +2606 ead5 83 00 f1 SUBD #LINHDR LENGTH OF LINE IN ACCD +2607 ead8 8e 00 f2 LDX #LINBUF-1 * SET THE INPUT POINTER TO ONE BEFORE +2608 eadb 9f 83 STX CHARAD * THE START OF THE CRUNCHED LINE +2609 eadd 39 RTS EXIT 'CRUNCH' +2610 eade 81 3f LB86B CMPA #'? CHECK FOR "?" - PRINT ABBREVIATION +2611 eae0 26 04 BNE LB873 BRANCH IF NOT PRINT ABBREVIATION +2612 eae2 86 87 LDA #TOK_PRINT * GET THE PRINT TOKEN AND SAVE IT +2613 eae4 20 df BRA LB852 * IN BUFFER +2614 eae6 81 27 LB873 CMPA #'' APOSTROPHE IS SAME AS REM +2615 eae8 26 13 BNE LB88A BRANCH IF NOT REMARK +2616 eaea cc 3a 83 LDD #$3A00+TOK_SNGL_Q COLON, REM TOKEN +2617 eaed ed c1 STD ,U++ SAVE IN BUFFER +2618 eaef 0f 42 LB87C CLR V42 SET DELIMITER = 0 (END OF LINE) +2619 eaf1 a6 80 LB87E LDA ,X+ SCAN TILL WE MATCH [V42] +2620 eaf3 27 d0 BEQ LB852 BRANCH IF END OF LINE +2621 eaf5 91 42 CMPA V42 DELIMITER? +2622 eaf7 27 cc BEQ LB852 BRANCH OUT IF SO +2623 eaf9 a7 c0 LB886 STA ,U+ DON’T CRUNCH REMARKS OR STRINGS +2624 eafb 20 f4 BRA LB87E GO GET MORE STRING OR REMARK +2625 eafd 81 30 LB88A CMPA #'0 * LESS THAN ASCII ZERO? +2626 eaff 25 04 BCS LB892 * BRANCH IF SO +2627 eb01 81 3c CMPA #';+1 = CHECK FOR NUMERIC VALUE, COLON OR SEMICOLON +2628 eb03 25 c0 BCS LB852 = AND INSERT IN BUFFER IF SO +2629 eb05 30 1f LB892 LEAX -1,X MOVE INPUT POINTER BACK ONE +2630 eb07 34 50 PSHS U,X SAVE POINTERS TO INPUT STRING, OUTPUT STRING +2631 eb09 0f 41 CLR V41 TOKEN FLAG 0 = COMMAND, FF = SECONDARY +2632 eb0b ce db e4 LDU #COMVEC-10 POINT U TO COMMAND INTERPRETATION +2633 * TABLE FOR BASIC - 10 +2634 eb0e 0f 42 LB89B CLR V42 INITIALIZE V42 AS TOKEN COUNTER +2635 eb10 33 4a LB89D LEAU 10,U MOVE TO NEXT COMMAND INTERPRETATION TABLE +2636 eb12 a6 c4 LDA ,U GET NUMBER OF COMMANDS +2637 eb14 27 31 BEQ LB8D4 GO DO SECONDARY FUNCTIONS IF NO COMMAND TABLE +2638 eb16 10 ae 41 LDY 1,U POINT Y TO COMMAND DICTIONARY TABLE +2639 eb19 ae e4 LB8A6 LDX ,S GET POINTER TO INPUT STRING +2640 eb1b e6 a0 LB8A8 LDB ,Y+ GET A BYTE FROM DICTIONARY TABLE +2641 eb1d e0 80 SUBB ,X+ SUBTRACT INPUT CHARACTER +2642 eb1f 27 fa BEQ LB8A8 LOOP IF SAME +2643 eb21 c1 80 CMPB #$80 LAST CHAR IN RESERVED WORD TABLE HAD +2644 * BIT 7 SET, SO IF WE HAVE $80 HERE +2645 * THEN IT IS A GOOD COMPARE +2646 eb23 26 38 BNE LB8EA BRANCH IF NO MATCH - CHECK ANOTHER COMMAND +2647 eb25 32 62 LEAS 2,S DELETE OLD INPUT POINTER FROM STACK +2648 eb27 35 40 PULS U GET POINTER TO OUTPUT STRING +2649 eb29 da 42 ORB V42 OR IN THE TABLE POSITION TO MAKE THE TOKEN +2650 * - NOTE THAT B ALREADY HAD $80 IN IT - +2651 eb2b 96 41 LDA V41 * CHECK TOKEN FLAG AND BRANCH +2652 eb2d 26 06 BNE LB8C2 * IF SECONDARY +2653 eb2f c1 84 CMPB #TOK_ELSE IS IT ELSE TOKEN? +2654 eb31 26 06 BNE LB8C6 NO +2655 eb33 86 3a LDA #': PUT A COLON (SUBLINE) BEFORE ELSE TOKEN +2656 eb35 ed c1 LB8C2 STD ,U++ SECONDARY TOKENS PRECEEDED BY $FF +2657 eb37 20 94 BRA LB85A GO PROCESS MORE INPUT CHARACTERS +2658 eb39 e7 c0 LB8C6 STB ,U+ SAVE THIS TOKEN +2659 eb3b c1 86 CMPB #TOK_DATA DATA TOKEN? +2660 eb3d 26 02 BNE LB8CE NO +2661 eb3f 0c 44 INC V44 SET DATA FLAG +2662 eb41 c1 82 LB8CE CMPB #TOK_REM REM TOKEN? +2663 eb43 27 aa BEQ LB87C YES +2664 eb45 20 86 LB8D2 BRA LB85A GO PROCESS MORE INPUT CHARACTERS +2665 * CHECK FOR A SECONDARY TOKEN +2666 eb47 ce db e9 LB8D4 LDU #COMVEC-5 NOW DO SECONDARY FUNCTIONS +2667 eb4a 03 41 COM V41 TOGGLE THE TOKEN FLAG +2668 eb4c 26 c0 BNE LB89B BRANCH IF NOW CHECKING SECONDARY COMMANDS +2669 +2670 * THIS CODE WILL PROCESS INPUT DATA WHICH CANNOT BE CRUNCHED AND SO +2671 * IS ASSUMED TO BE ILLEGAL DATA OR AN ILLEGAL TOKEN +2672 eb4e 35 50 PULS X,U RESTORE INPUT AND OUTPUT POINTERS +2673 eb50 a6 80 LDA ,X+ * MOVE THE FIRST CHARACTER OF AN +2674 eb52 a7 c0 STA ,U+ * ILLEGAL TOKEN +2675 eb54 bd e6 26 JSR LB3A2 SET CARRY IF NOT ALPHA +2676 eb57 25 ec BCS LB8D2 BRANCH IF NOT ALPHA +2677 eb59 03 43 COM V43 SET ILLEGAL TOKEN FLAG IF UPPER CASE ALPHA +2678 eb5b 20 e8 BRA LB8D2 PROCESS MORE INPUT CHARACTERS +2679 eb5d 0c 42 LB8EA INC V42 INCREMENT TOKEN COUNTER +2680 eb5f 4a DECA DECR COMMAND COUNTER +2681 eb60 27 ae BEQ LB89D GET ANOTHER COMMAND TABLE IF DONE W/THIS ONE +2682 eb62 31 3f LEAY -1,Y MOVE POINTER BACK ONE +2683 eb64 e6 a0 LB8F1 LDB ,Y+ * GET TO NEXT +2684 eb66 2a fc BPL LB8F1 * RESERVED WORD +2685 eb68 20 af BRA LB8A6 GO SEE IF THIS WORD IS A MATCH +2686 +2687 * PRINT +2688 eb6a 27 39 PRINT BEQ LB958 BRANCH IF NO ARGUMENT +2689 eb6c 8d 01 BSR LB8FE CHECK FOR ALL PRINT OPTIONS +2690 eb6e 39 RTS +2691 LB8FE +2692 eb6f bd fa cf LB918 JSR XVEC9 CALL EXTENDED BASIC ADD-IN +2693 eb72 27 3e LB91B BEQ LB965 RETURN IF END OF LINE +2694 eb74 81 9f LB91D CMPA #TOK_TAB TOKEN FOR TAB( ? +2695 eb76 27 53 BEQ LB97E YES +2696 eb78 81 2c CMPA #', COMMA? +2697 eb7a 27 37 BEQ LB966 YES - ADVANCE TO NEXT TAB FIELD +2698 eb7c 81 3b CMPA #'; SEMICOLON? +2699 eb7e 27 60 BEQ LB997 YES - DO NOT ADVANCE CURSOR +2700 eb80 bd e3 df JSR LB156 EVALUATE EXPRESSION +2701 eb83 96 06 LDA VALTYP * GET VARIABLE TYPE AND +2702 eb85 34 02 PSHS A * SAVE IT ON THE STACK +2703 eb87 26 06 BNE LB938 BRANCH IF STRING VARIABLE +2704 eb89 bd f0 22 JSR LBDD9 CONVERT FP NUMBER TO AN ASCII STRING +2705 eb8c bd e7 9a JSR LB516 PARSE A STRING FROM (X-1) AND PUT +2706 * DESCRIPTOR ON STRING STACK +2707 eb8f 8d 57 LB938 BSR LB99F PRINT STRING POINTED TO BY X +2708 eb91 35 04 PULS B GET VARIABLE TYPE BACK +2709 eb93 bd dc 30 JSR LA35F SET UP TAB WIDTH ZONE, ETC +2710 eb96 5d LB949 TSTB CHECK CURRENT PRINT POSITION +2711 eb97 26 08 BNE LB954 BRANCH IF NOT AT START OF LINE +2712 eb99 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +2713 eb9b 81 2c CMPA #', COMMA? +2714 eb9d 27 14 BEQ LB966 SKIP TO NEXT TAB FIELD +2715 eb9f 8d 54 BSR LB9AC SEND A SPACE TO CONSOLE OUT +2716 eba1 9d 82 LB954 JSR GETCCH GET CURRENT INPUT CHARACTER +2717 eba3 26 cf BNE LB91D BRANCH IF NOT END OF LINE +2718 eba5 86 0d LB958 LDA #CR * SEND A CR TO +2719 eba7 20 51 BRA LB9B1 * CONSOLE OUT +2720 eba9 bd dc 30 LB95C JSR LA35F SET UP TAB WIDTH, ZONE ETC +2721 ebac 27 f7 BEQ LB958 BRANCH IF WIDTH = ZERO +2722 ebae 96 6c LDA DEVPOS GET PRINT POSITION +2723 ebb0 26 f3 BNE LB958 BRANCH IF NOT AT START OF LINE +2724 ebb2 39 LB965 RTS +2725 * SKIP TO NEXT TAB FIELD +2726 ebb3 bd dc 30 LB966 JSR LA35F SET UP TAB WIDTH, ZONE ETC +2727 ebb6 27 0a BEQ LB975 BRANCH IF LINE WIDTH = 0 (CASSETTE) +2728 ebb8 d6 6c LDB DEVPOS GET CURRENT POSITION +2729 ebba d1 6b CMPB DEVLCF COMPARE TO LAST TAB ZONE +2730 ebbc 25 06 BCS LB977 BRANCH IF < LAST TAB ZONE +2731 ebbe 8d e5 BSR LB958 SEND A CARRIAGE RETURN TO CONSOLE OUT +2732 ebc0 20 1e BRA LB997 GET MORE DATA +2733 ebc2 d6 6c LB975 LDB DEVPOS * +2734 ebc4 d0 6a LB977 SUBB DEVCFW * SUBTRACT TAB FIELD WIDTH FROM CURRENT +2735 ebc6 24 fc BCC LB977 * POSITION UNTIL CARRY SET - NEGATING THE +2736 ebc8 50 NEGB * REMAINDER LEAVES THE NUMBER OF SPACES TO NEXT +2737 * * TAB ZONE IN ACCB +2738 ebc9 20 10 BRA LB98E GO ADVANCE TO NEXT TAB ZONE +2739 +2740 * PRINT TAB( +2741 ebcb bd e9 8d LB97E JSR LB709 EVALUATE EXPRESSION - RETURN VALUE IN B +2742 ebce 81 29 CMPA #') * 'SYNTAX' ERROR IF NOT ')' +2743 ebd0 10 26 f9 2c LBNE LB277 * +2744 ebd4 bd dc 30 JSR LA35F SET UP TAB WIDTH, ZONE ETC +2745 ebd7 d0 6c SUBB DEVPOS GET DIFFERENCE OF PRINT POSITION & TAB POSITION +2746 ebd9 23 05 BLS LB997 BRANCH IF TAB POSITION < CURRENT POSITION +2747 LB98E +2748 ebdb 8d 18 LB992 BSR LB9AC SEND A SPACE TO CONSOLE OUT +2749 ebdd 5a DECB DECREMENT DIFFERENCE COUNT +2750 ebde 26 fb BNE LB992 BRANCH UNTIL CURRENT POSITION = TAB POSITION +2751 ebe0 9d 7c LB997 JSR GETNCH GET NEXT CHARACTER FROM BASIC +2752 ebe2 7e eb 72 JMP LB91B LOOK FOR MORE PRINT DATA +2753 * COPY A STRING FROM (X) TO CONSOLE OUT +2754 ebe5 bd e7 9c LB99C JSR LB518 PARSE A STRING FROM X AND PUT +2755 * DESCRIPTOR ON STRING STACK +2756 ebe8 bd e8 db LB99F JSR LB657 GET LENGTH OF STRING AND REMOVE +2757 * DESCRIPTOR FROM STRING STACK +2758 ebeb 5c INCB COMPENSATE FOR DECB BELOW +2759 ebec 5a LB9A3 DECB DECREMENT COUNTER +2760 ebed 27 c3 BEQ LB965 EXIT ROUTINE +2761 ebef a6 80 LDA ,X+ GET A CHARACTER FROM X +2762 ebf1 8d 07 BSR LB9B1 SEND TO CONSOLE OUT +2763 ebf3 20 f7 BRA LB9A3 KEEP LOOPING +2764 ebf5 86 20 LB9AC LDA #SPACE SPACE TO CONSOLE OUT +2765 ebf7 8c FCB SKP2 SKIP NEXT TWO BYTES +2766 ebf8 86 3f LB9AF LDA #'? QUESTION MARK TO CONSOLE OUT +2767 ebfa 7e db 14 LB9B1 JMP PUTCHR JUMP TO CONSOLE OUT +2768 +2769 * FLOATING POINT MATH PACKAGE +2770 +2771 * ADD .5 TO FPA0 +2772 ebfd 8e f1 09 LB9B4 LDX #LBEC0 FLOATING POINT CONSTANT (.5) +2773 ec00 20 09 BRA LB9C2 ADD .5 TO FPA0 +2774 * SUBTRACT FPA0 FROM FP NUMBER POINTED +2775 * TO BY (X), LEAVE RESULT IN FPA0 +2776 ec02 bd ed 78 LB9B9 JSR LBB2F COPY PACKED FP DATA FROM (X) TO FPA1 +2777 +2778 * ARITHMETIC OPERATION (-) JUMPS HERE - SUBTRACT FPA0 FROM FPA1 (ENTER +2779 * WITH EXPONENT OF FPA0 IN ACCB AND EXPONENT OF FPA1 IN ACCA) +2780 ec05 03 54 LB9BC COM FP0SGN CHANGE MANTISSA SIGN OF FPA0 +2781 ec07 03 62 COM RESSGN REVERSE RESULT SIGN FLAG +2782 ec09 20 03 BRA LB9C5 GO ADD FPA1 AND FPA0 +2783 * ADD FP NUMBER POINTED TO BY +2784 * (X) TO FPA0 - LEAVE RESULT IN FPA0 +2785 ec0b bd ed 78 LB9C2 JSR LBB2F UNPACK PACKED FP DATA FROM (X) TO +2786 * FPA1; RETURN EXPONENT OF FPA1 IN ACCA +2787 +2788 * ARITHMETIC OPERATION (+) JUMPS HERE - ADD FPA0 TO +2789 +2790 ec0e 5d LB9C5 TSTB CHECK EXPONENT OF FPA0 +2791 ec0f 10 27 02 80 LBEQ LBC4A COPY FPA1 TO FPA0 IF FPA0 = +2792 ec13 8e 00 5c LDX #FP1EXP POINT X TO FPA1 +2793 ec16 1f 89 LB9CD TFR A,B PUT EXPONENT OF FPA1 INTO ACCB +2794 ec18 5d TSTB CHECK EXPONENT +2795 ec19 27 6c BEQ LBA3E RETURN IF EXPONENT = 0 (ADDING 0 TO FPA0) +2796 ec1b d0 4f SUBB FP0EXP SUBTRACT EXPONENT OF FPA0 FROM EXPONENT OF FPA1 +2797 ec1d 27 69 BEQ LBA3F BRANCH IF EXPONENTS ARE EQUAL +2798 ec1f 25 0a BCS LB9E2 BRANCH IF EXPONENT FPA0 > FPA1 +2799 ec21 97 4f STA FP0EXP REPLACE FPA0 EXPONENT WITH FPA1 EXPONENT +2800 ec23 96 61 LDA FP1SGN * REPLACE FPA0 MANTISSA SIGN +2801 ec25 97 54 STA FP0SGN * WITH FPA1 MANTISSA SIGN +2802 ec27 8e 00 4f LDX #FP0EXP POINT X TO FPA0 +2803 ec2a 50 NEGB NEGATE DIFFERENCE OF EXPONENTS +2804 ec2b c1 f8 LB9E2 CMPB #-8 TEST DIFFERENCE OF EXPONENTS +2805 ec2d 2f 59 BLE LBA3F BRANCH IF DIFFERENCE OF EXPONENTS <= 8 +2806 ec2f 4f CLRA CLEAR OVERFLOW BYTE +2807 ec30 64 01 LSR 1,X SHIFT MS BYTE OF MANTISSA; BIT 7 = 0 +2808 ec32 bd ed 03 JSR LBABA GO SHIFT MANTISSA OF (X) TO THE RIGHT (B) TIMES +2809 ec35 d6 62 LB9EC LDB RESSGN GET SIGN FLAG +2810 ec37 2a 0b BPL LB9FB BRANCH IF FPA0 AND FPA1 SIGNS ARE THE SAME +2811 ec39 63 01 COM 1,X * COMPLEMENT MANTISSA POINTED +2812 ec3b 63 02 COM 2,X * TO BY (X) THE +2813 ec3d 63 03 COM 3,X * ADCA BELOW WILL +2814 ec3f 63 04 COM 4,X * CONVERT THIS OPERATION +2815 ec41 43 COMA * INTO A NEG (MANTISSA) +2816 ec42 89 00 ADCA #0 ADD ONE TO ACCA - COMA ALWAYS SETS THE CARRY FLAG +2817 * THE PREVIOUS TWO BYTES MAY BE REPLACED BY A NEGA +2818 * +2819 * ADD MANTISSAS OF FPA0 AND FPA1, PUT RESULT IN FPA0 +2820 ec44 97 63 LB9FB STA FPSBYT SAVE FPA SUB BYTE +2821 ec46 96 53 LDA FPA0+3 * ADD LS BYTE +2822 ec48 99 60 ADCA FPA1+3 * OF MANTISSA +2823 ec4a 97 53 STA FPA0+3 SAVE IN FPA0 LSB +2824 ec4c 96 52 LDA FPA0+2 * ADD NEXT BYTE +2825 ec4e 99 5f ADCA FPA1+2 * OF MANTISSA +2826 ec50 97 52 STA FPA0+2 SAVE IN FPA0 +2827 ec52 96 51 LDA FPA0+1 * ADD NEXT BYTE +2828 ec54 99 5e ADCA FPA1+1 * OF MANTISSA +2829 ec56 97 51 STA FPA0+1 SAVE IN FPA0 +2830 ec58 96 50 LDA FPA0 * ADD MS BYTE +2831 ec5a 99 5d ADCA FPA1 * OF MANTISSA +2832 ec5c 97 50 STA FPA0 SAVE IN FPA0 +2833 ec5e 5d TSTB TEST SIGN FLAG +2834 ec5f 2a 44 BPL LBA5C BRANCH IF FPA0 & FPA1 SIGNS WERE ALIKE +2835 ec61 25 02 LBA18 BCS LBA1C BRANCH IF POSITIVE MANTISSA +2836 ec63 8d 5d BSR LBA79 NEGATE FPA0 MANTISSA +2837 +2838 * NORMALIZE FPA0 +2839 ec65 5f LBA1C CLRB CLEAR TEMPORARY EXPONENT ACCUMULATOR +2840 ec66 96 50 LBA1D LDA FPA0 TEST MSB OF MANTISSA +2841 ec68 26 2e BNE LBA4F BRANCH IF <> 0 +2842 ec6a 96 51 LDA FPA0+1 * IF THE MSB IS +2843 ec6c 97 50 STA FPA0 * 0, THEN SHIFT THE +2844 ec6e 96 52 LDA FPA0+2 * MANTISSA A WHOLE BYTE +2845 ec70 97 51 STA FPA0+1 * AT A TIME. THIS +2846 ec72 96 53 LDA FPA0+3 * IS FASTER THAN ONE +2847 ec74 97 52 STA FPA0+2 * BIT AT A TIME +2848 ec76 96 63 LDA FPSBYT * BUT USES MORE MEMORY. +2849 ec78 97 53 STA FPA0+3 * FPSBYT, THE CARRY IN +2850 ec7a 0f 63 CLR FPSBYT * BYTE, REPLACES THE MATISSA LSB. +2851 ec7c cb 08 ADDB #8 SHIFTING ONE BYTE = 8 BIT SHIFTS; ADD 8 TO EXPONENT +2852 ec7e c1 28 CMPB #5*8 CHECK FOR 5 SHIFTS +2853 ec80 2d e4 BLT LBA1D BRANCH IF < 5 SHIFTS, IF > 5, THEN MANTISSA = 0 +2854 ec82 4f LBA39 CLRA A ZERO EXPONENT = 0 FLOATING POINT +2855 ec83 97 4f LBA3A STA FP0EXP ZERO OUT THE EXPONENT +2856 ec85 97 54 STA FP0SGN ZERO OUT THE MANTISSA SIGN +2857 ec87 39 LBA3E RTS +2858 ec88 8d 6d LBA3F BSR LBAAE SHIFT FPA0 MANTISSA TO RIGHT +2859 ec8a 5f CLRB CLEAR CARRY FLAG +2860 ec8b 20 a8 BRA LB9EC +2861 * SHIFT FPA0 LEFT ONE BIT UNTIL BIT 7 +2862 * OF MATISSA MS BYTE = 1 +2863 ec8d 5c LBA44 INCB ADD ONE TO EXPONENT ACCUMULATOR +2864 ec8e 08 63 ASL FPSBYT SHIFT SUB BYTE ONE LEFT +2865 ec90 09 53 ROL FPA0+3 SHIFT LS BYTE +2866 ec92 09 52 ROL FPA0+2 SHIFT NS BYTE +2867 ec94 09 51 ROL FPA0+1 SHIFT NS BYTE +2868 ec96 09 50 ROL FPA0 SHIFT MS BYTE +2869 ec98 2a f3 LBA4F BPL LBA44 BRANCH IF NOT YET NORMALIZED +2870 ec9a 96 4f LDA FP0EXP GET CURRENT EXPONENT +2871 ec9c 34 04 PSHS B SAVE EXPONENT MODIFIER CAUSED BY NORMALIZATION +2872 ec9e a0 e0 SUBA ,S+ SUBTRACT ACCUMULATED EXPONENT MODIFIER +2873 eca0 97 4f STA FP0EXP SAVE AS NEW EXPONENT +2874 eca2 23 de BLS LBA39 SET FPA0 = 0 IF THE NORMALIZATION CAUSED +2875 * MORE OR EQUAL NUMBER OF LEFT SHIFTS THAN THE +2876 * SIZE OF THE EXPONENT +2877 eca4 8c FCB SKP2 SKIP 2 BYTES +2878 eca5 25 08 LBA5C BCS LBA66 BRANCH IF MANTISSA OVERFLOW +2879 eca7 08 63 ASL FPSBYT SUB BYTE BIT 7 TO CARRY - USE AS ROUND-OFF +2880 * FLAG (TRUNCATE THE REST OF SUB BYTE) +2881 eca9 86 00 LDA #0 CLRA, BUT DO NOT CHANGE CARRY FLAG +2882 ecab 97 63 STA FPSBYT CLEAR THE SUB BYTE +2883 ecad 20 0c BRA LBA72 GO ROUND-OFF RESULT +2884 ecaf 0c 4f LBA66 INC FP0EXP INCREMENT EXPONENT - MULTIPLY BY 2 +2885 ecb1 27 28 BEQ LBA92 OVERFLOW ERROR IF CARRY PAST $FF +2886 ecb3 06 50 ROR FPA0 * SHIFT MANTISSA +2887 ecb5 06 51 ROR FPA0+1 * ONE TO +2888 ecb7 06 52 ROR FPA0+2 * THE RIGHT - +2889 ecb9 06 53 ROR FPA0+3 * DIVIDE BY TWO +2890 ecbb 24 04 LBA72 BCC LBA78 BRANCH IF NO ROUND-OFF NEEDED +2891 ecbd 8d 0d BSR LBA83 ADD ONE TO MANTISSA - ROUND OFF +2892 ecbf 27 ee BEQ LBA66 BRANCH iF OVERFLOW - MANTISSA = 0 +2893 ecc1 39 LBA78 RTS +2894 * NEGATE FPA0 MANTISSA +2895 ecc2 03 54 LBA79 COM FP0SGN TOGGLE SIGN OF MANTISSA +2896 ecc4 03 50 LBA7B COM FPA0 * COMPLEMENT ALL 4 MANTISSA BYTES +2897 ecc6 03 51 COM FPA0+1 * +2898 ecc8 03 52 COM FPA0+2 * +2899 ecca 03 53 COM FPA0+3 * +2900 * ADD ONE TO FPA0 MANTISSA +2901 eccc 9e 52 LBA83 LDX FPA0+2 * GET BOTTOM 2 MANTISSA +2902 ecce 30 01 LEAX 1,X * BYTES, ADD ONE TO +2903 ecd0 9f 52 STX FPA0+2 * THEM AND SAVE THEM +2904 ecd2 26 06 BNE LBA91 BRANCH IF NO OVERFLOW +2905 ecd4 9e 50 LDX FPA0 * IF OVERFLOW ADD ONE +2906 ecd6 30 01 LEAX 1,X * TO TOP 2 MANTISSA +2907 ecd8 9f 50 STX FPA0 * BYTES AND SAVE THEM +2908 ecda 39 LBA91 RTS +2909 ecdb c6 0a LBA92 LDB #2*5 OV' OVERFLOW ERROR +2910 ecdd 7e df 03 JMP LAC46 PROCESS AN ERROR +2911 ece0 8e 00 12 LBA97 LDX #FPA2-1 POINT X TO FPA2 +2912 * SHIFT FPA POINTED TO BY (X) TO +2913 * THE RIGHT -(B) TIMES. EXIT WITH +2914 * ACCA CONTAINING DATA SHIFTED OUT +2915 * TO THE RIGHT (SUB BYTE) AND THE DATA +2916 * SHIFTED IN FROM THE LEFT WILL COME FROM FPCARY +2917 ece3 a6 04 LBA9A LDA 4,X GET LS BYTE OF MANTISSA (X) +2918 ece5 97 63 STA FPSBYT SAVE IN FPA SUB BYTE +2919 ece7 a6 03 LDA 3,X * SHIFT THE NEXT THREE BYTES OF THE +2920 ece9 a7 04 STA 4,X * MANTISSA RIGHT ONE COMPLETE BYTE. +2921 eceb a6 02 LDA 2,X * +2922 eced a7 03 STA 3,X * +2923 ecef a6 01 LDA 1,X * +2924 ecf1 a7 02 STA 2,X * +2925 ecf3 96 5b LDA FPCARY GET THE CARRY IN BYTE +2926 ecf5 a7 01 STA 1,X STORE AS THE MS MANTISSA BYTE OF (X) +2927 ecf7 cb 08 LBAAE ADDB #8 ADD 8 TO DIFFERENCE OF EXPONENTS +2928 ecf9 2f e8 BLE LBA9A BRANCH IF EXPONENT DIFFERENCE < -8 +2929 ecfb 96 63 LDA FPSBYT GET FPA SUB BYTE +2930 ecfd c0 08 SUBB #8 CAST OUT THE 8 ADDED IN ABOVE +2931 ecff 27 0c BEQ LBAC4 BRANCH IF EXPONENT DIFFERENCE = 0 +2932 +2933 +2934 ed01 67 01 LBAB8 ASR 1,X * SHIFT MANTISSA AND SUB BYTE ONE BIT TO THE RIGHT +2935 ed03 66 02 LBABA ROR 2,X * +2936 ed05 66 03 ROR 3,X * +2937 ed07 66 04 ROR 4,X * +2938 ed09 46 RORA * +2939 ed0a 5c INCB ADD ONE TO EXPONENT DIFFERENCE +2940 ed0b 26 f4 BNE LBAB8 BRANCH IF EXPONENTS NOT = +2941 ed0d 39 LBAC4 RTS +2942 ed0e 81 00 00 00 00 LBAC5 FCB $81,$00,$00,$00,$00 FLOATING POINT CONSTANT 1.0 +2943 +2944 * ARITHMETIC OPERATION (*) JUMPS HERE - MULTIPLY +2945 * FPA0 BY (X) - RETURN PRODUCT IN FPA0 +2946 ed13 8d 63 LBACA BSR LBB2F MOVE PACKED FPA FROM (X) TO FPA1 +2947 ed15 27 60 LBACC BEQ LBB2E BRANCH IF EXPONENT OF FPA0 = 0 +2948 ed17 8d 78 BSR LBB48 CALCULATE EXPONENT OF PRODUCT +2949 * MULTIPLY FPA0 MANTISSA BY FPA1. NORMALIZE +2950 * HIGH ORDER BYTES OF PRODUCT IN FPA0. THE +2951 * LOW ORDER FOUR BYTES OF THE PRODUCT WILL +2952 * BE STORED IN VAB-VAE. +2953 ed19 86 00 LBAD0 LDA #0 * ZERO OUT MANTISSA OF FPA2 +2954 ed1b 97 13 STA FPA2 * +2955 ed1d 97 14 STA FPA2+1 * +2956 ed1f 97 15 STA FPA2+2 * +2957 ed21 97 16 STA FPA2+3 * +2958 ed23 d6 53 LDB FPA0+3 GET LS BYTE OF FPA0 +2959 ed25 8d 22 BSR LBB00 MULTIPLY BY FPA1 +2960 ed27 d6 63 LDB FPSBYT * TEMPORARILY SAVE SUB BYTE 4 +2961 ed29 d7 8b STB VAE * +2962 ed2b d6 52 LDB FPA0+2 GET NUMBER 3 MANTISSA BYTE OF FPA0 +2963 ed2d 8d 1a BSR LBB00 MULTIPLY BY FPA1 +2964 ed2f d6 63 LDB FPSBYT * TEMPORARILY SAVE SUB BYTE 3 +2965 ed31 d7 8a STB VAD * +2966 ed33 d6 51 LDB FPA0+1 GET NUMBER 2 MANTISSA BYTE OF FPA0 +2967 ed35 8d 12 BSR LBB00 MULTIPLY BY FPA1 +2968 ed37 d6 63 LDB FPSBYT * TEMPORARILY SAVE SUB BYTE 2 +2969 ed39 d7 89 STB VAC * +2970 ed3b d6 50 LDB FPA0 GET MS BYTE OF FPA0 MANTISSA +2971 ed3d 8d 0c BSR LBB02 MULTIPLY BY FPA1 +2972 ed3f d6 63 LDB FPSBYT * TEMPORARILY SAVE SUB BYTE 1 +2973 ed41 d7 88 STB VAB * +2974 ed43 bd ee 54 JSR LBC0B COPY MANTISSA FROM FPA2 TO FPA0 +2975 ed46 7e ec 65 JMP LBA1C NORMALIZE FPA0 +2976 ed49 27 95 LBB00 BEQ LBA97 SHIFT FPA2 ONE BYTE TO RIGHT +2977 ed4b 43 LBB02 COMA SET CARRY FLAG +2978 * MULTIPLY FPA1 MANTISSA BY ACCB AND +2979 * ADD PRODUCT TO FPA2 MANTISSA +2980 ed4c 96 13 LBB03 LDA FPA2 GET FPA2 MS BYTE +2981 ed4e 56 RORB ROTATE CARRY FLAG INTO SHIFT COUNTER; +2982 * DATA BIT INTO CARRY +2983 ed4f 27 26 BEQ LBB2E BRANCH WHEN 8 SHIFTS DONE +2984 ed51 24 16 BCC LBB20 DO NOT ADD FPA1 IF DATA BIT = 0 +2985 ed53 96 16 LDA FPA2+3 * ADD MANTISSA LS BYTE +2986 ed55 9b 60 ADDA FPA1+3 * +2987 ed57 97 16 STA FPA2+3 * +2988 ed59 96 15 LDA FPA2+2 = ADD MANTISSA NUMBER 3 BYTE +2989 ed5b 99 5f ADCA FPA1+2 = +2990 ed5d 97 15 STA FPA2+2 = +2991 ed5f 96 14 LDA FPA2+1 * ADD MANTISSA NUMBER 2 BYTE +2992 ed61 99 5e ADCA FPA1+1 * +2993 ed63 97 14 STA FPA2+1 * +2994 ed65 96 13 LDA FPA2 = ADD MANTISSA MS BYTE +2995 ed67 99 5d ADCA FPA1 = +2996 ed69 46 LBB20 RORA * ROTATE CARRY INTO MS BYTE +2997 ed6a 97 13 STA FPA2 * +2998 ed6c 06 14 ROR FPA2+1 = ROTATE FPA2 ONE BIT TO THE RIGHT +2999 ed6e 06 15 ROR FPA2+2 = +3000 ed70 06 16 ROR FPA2+3 = +3001 ed72 06 63 ROR FPSBYT = +3002 ed74 4f CLRA CLEAR CARRY FLAG +3003 ed75 20 d5 BRA LBB03 KEEP LOOPING +3004 ed77 39 LBB2E RTS +3005 * UNPACK A FP NUMBER FROM (X) TO FPA1 +3006 ed78 ec 01 LBB2F LDD 1,X GET TWO MSB BYTES OF MANTISSA FROM +3007 * FPA POINTED TO BY X +3008 ed7a 97 61 STA FP1SGN SAVE PACKED MANTISSA SIGN BYTE +3009 ed7c 8a 80 ORA #$80 FORCE BIT 7 OF MSB MANTISSA = 1 +3010 ed7e dd 5d STD FPA1 SAVE 2 MSB BYTES IN FPA1 +3011 ed80 d6 61 LDB FP1SGN * GET PACKED MANTISSA SIGN BYTE. EOR W/FPA0 +3012 ed82 d8 54 EORB FP0SGN * SIGN - NEW SIGN POSITION IF BOTH OLD SIGNS ALIKE, +3013 ed84 d7 62 STB RESSGN * NEG IF BOTH OLD SIGNS DIFF. SAVE ADJUSTED +3014 * * MANTISSA SIGN BYTE +3015 ed86 ec 03 LDD 3,X = GET 2 LSB BYTES OF MANTISSA +3016 ed88 dd 5f STD FPA1+2 = AND PUT IN FPA1 +3017 ed8a a6 84 LDA ,X * GET EXPONENT FROM (X) AND +3018 ed8c 97 5c STA FP1EXP * PUT IN EXPONENT OF FPA1 +3019 ed8e d6 4f LDB FP0EXP GET EXPONENT OF FPA0 +3020 ed90 39 RTS +3021 * CALCULATE EXPONENT FOR PRODUCT OF FPA0 & FPA1 +3022 * ENTER WITH EXPONENT OF FPA1 IN ACCA +3023 ed91 4d LBB48 TSTA TEST EXPONENT OF FPA1 +3024 ed92 27 16 BEQ LBB61 PURGE RETURN ADDRESS & SET FPA0 = 0 +3025 ed94 9b 4f ADDA FP0EXP ADD FPA1 EXPONENT TO FPA0 EXPONENT +3026 ed96 46 RORA ROTATE CARRY INTO BIT 7; BIT 0 INTO CARRY +3027 ed97 49 ROLA SET OVERFLOW FLAG +3028 ed98 28 10 BVC LBB61 BRANCH IF EXPONENT TOO LARGE OR SMALL +3029 ed9a 8b 80 ADDA #$80 ADD $80 BIAS TO EXPONENT +3030 ed9c 97 4f STA FP0EXP SAVE NEW EXPONENT +3031 ed9e 27 0c BEQ LBB63 SET FPA0 +3032 eda0 96 62 LDA RESSGN GET MANTISSA SIGN +3033 eda2 97 54 STA FP0SGN SAVE AS MANTISSA SIGN OF FPA0 +3034 eda4 39 RTS +3035 * IF FPA0 = POSITIVE THEN 'OV' ERROR IF FPA0 +3036 * = IS NEGATIVE THEN FPA0 = 0 +3037 eda5 96 54 LBB5C LDA FP0SGN GET MANTISSA SIGN OF FPA0 +3038 eda7 43 COMA CHANGE SIGN OF FPA0 MANTISSA +3039 eda8 20 02 BRA LBB63 +3040 edaa 32 62 LBB61 LEAS 2,S PURGE RETURN ADDRESS FROM STACK +3041 edac 10 2a fe d2 LBB63 LBPL LBA39 ZERO FPA0 MANTISSA SIGN & EXPONENT +3042 edb0 7e ec db LBB67 JMP LBA92 OV' OVERFLOW ERROR +3043 * FAST MULTIPLY BY 10 AND LEAVE RESULT IN FPA0 +3044 edb3 bd ee a8 LBB6A JSR LBC5F TRANSFER FPA0 TO FPA1 +3045 edb6 27 0d BEQ LBB7C BRANCH IF EXPONENT = 0 +3046 edb8 8b 02 ADDA #2 ADD 2 TO EXPONENT (TIMES 4) +3047 edba 25 f4 BCS LBB67 OV' ERROR IF EXPONENT > $FF +3048 edbc 0f 62 CLR RESSGN CLEAR RESULT SIGN BYTE +3049 edbe bd ec 16 JSR LB9CD ADD FPA1 TO FPA0 (TIMES 5) +3050 edc1 0c 4f INC FP0EXP ADD ONE TO EXPONENT (TIMES 10) +3051 edc3 27 eb BEQ LBB67 OV' ERROR IF EXPONENT > $FF +3052 edc5 39 LBB7C RTS +3053 edc6 84 20 00 00 00 LBB7D FCB $84,$20,$00,$00,$00 FLOATING POINT CONSTANT 10 +3054 * DIVIDE FPA0 BY 10 +3055 edcb bd ee a8 LBB82 JSR LBC5F MOVE FPA0 TO FPA1 +3056 edce 8e ed c6 LDX #LBB7D POINT TO FLOATING POINT CONSTANT 10 +3057 edd1 5f CLRB ZERO MANTISSA SIGN BYTE +3058 edd2 d7 62 LBB89 STB RESSGN STORE THE QUOTIENT MANTISSA SIGN BYTE +3059 edd4 bd ee 5d JSR LBC14 UNPACK AN FP NUMBER FROM (X) INTO FPA0 +3060 edd7 8c FCB SKP2 SKIP TWO BYTES +3061 * DIVIDE (X) BY FPA0-LEAVE NORMALIZED QUOTIENT IN FPA0 +3062 edd8 8d 9e LBB8F BSR LBB2F GET FP NUMBER FROM (X) TO FPA1 +3063 +3064 * ARITHMETIC OPERATION (/) JUMPS HERE. DIVIDE FPA1 BY FPA0 (ENTER WITH +3065 * EXPONENT OF FPA1 IN ACCA AND FLAGS SET BY TSTA) +3066 +3067 * DIVIDE FPA1 BY FPA0 +3068 edda 27 73 LBB91 BEQ LBC06 /0' DIVIDE BY ZERO ERROR +3069 eddc 00 4f NEG FP0EXP GET EXPONENT OF RECIPROCAL OF DIVISOR +3070 edde 8d b1 BSR LBB48 CALCULATE EXPONENT OF QUOTIENT +3071 ede0 0c 4f INC FP0EXP INCREMENT EXPONENT +3072 ede2 27 cc BEQ LBB67 OV' OVERFLOW ERROR +3073 ede4 8e 00 13 LDX #FPA2 POINT X TO MANTISSA OF FPA2 - HOLD +3074 * TEMPORARY QUOTIENT IN FPA2 +3075 ede7 c6 04 LDB #4 5 BYTE DIVIDE +3076 ede9 d7 03 STB TMPLOC SAVE BYTE COUNTER +3077 edeb c6 01 LDB #1 SHIFT COUNTER-AND TEMPORARY QUOTIENT BYTE +3078 * COMPARE FPA0 MANTISSA TO FPA1 MANTISSA - +3079 * SET CARRY FLAG IF FPA1 >= FPA0 +3080 eded 96 50 LBBA4 LDA FPA0 * COMPARE THE TWO MS BYTES +3081 edef 91 5d CMPA FPA1 * OF FPA0 AND FPA1 AND +3082 edf1 26 13 BNE LBBBD * BRANCH IF <> +3083 edf3 96 51 LDA FPA0+1 = COMPARE THE NUMBER 2 +3084 edf5 91 5e CMPA FPA1+1 = BYTES AND +3085 edf7 26 0d BNE LBBBD = BRANCH IF <> +3086 edf9 96 52 LDA FPA0+2 * COMPARE THE NUMBER 3 +3087 edfb 91 5f CMPA FPA1+2 * BYTES AND +3088 edfd 26 07 BNE LBBBD * BRANCH IF <> +3089 edff 96 53 LDA FPA0+3 = COMPARE THE LS BYTES +3090 ee01 91 60 CMPA FPA1+3 = AND BRANCH +3091 ee03 26 01 BNE LBBBD = IF <> +3092 ee05 43 COMA SET CARRY FLAG IF FPA0 = FPA1 +3093 ee06 1f a8 LBBBD TFR CC,A SAVE CARRY FLAG STATUS IN ACCA; CARRY +3094 * CLEAR IF FPA0 > FPA1 +3095 ee08 59 ROLB ROTATE CARRY INTO TEMPORARY QUOTIENT BYTE +3096 ee09 24 0a BCC LBBCC CARRY WILL BE SET AFTER 8 SHIFTS +3097 ee0b e7 80 STB ,X+ SAVE TEMPORARY QUOTIENT +3098 ee0d 0a 03 DEC TMPLOC DECREMENT BYTE COUNTER +3099 ee0f 2b 34 BMI LBBFC BRANCH IF DONE +3100 ee11 27 2e BEQ LBBF8 BRANCH IF LAST BYTE +3101 ee13 c6 01 LDB #1 RESET SHIFT COUNTER AND TEMPORARY QUOTIENT BYTE +3102 ee15 1f 8a LBBCC TFR A,CC RESTORE CARRY FLAG AND +3103 ee17 25 0e BCS LBBDE BRANCH IF FPA0 =< FPA1 +3104 ee19 08 60 LBBD0 ASL FPA1+3 * SHIFT FPA1 MANTISSA 1 BIT TO LEFT +3105 ee1b 09 5f ROL FPA1+2 * +3106 ee1d 09 5e ROL FPA1+1 * +3107 ee1f 09 5d ROL FPA1 * +3108 ee21 25 e3 BCS LBBBD BRANCH IF CARRY - ADD ONE TO PARTIAL QUOTIENT +3109 ee23 2b c8 BMI LBBA4 IF MSB OF HIGH ORDER MANTISSA BYTE IS +3110 * SET, CHECK THE MAGNITUDES OF FPA0, FPA1 +3111 ee25 20 df BRA LBBBD CARRY IS CLEAR, CHECK ANOTHER BIT +3112 * SUBTRACT FPA0 FROM FPA1 - LEAVE RESULT IN FPA1 +3113 ee27 96 60 LBBDE LDA FPA1+3 * SUBTRACT THE LS BYTES OF MANTISSA +3114 ee29 90 53 SUBA FPA0+3 * +3115 ee2b 97 60 STA FPA1+3 * +3116 ee2d 96 5f LDA FPA1+2 = THEN THE NEXT BYTE +3117 ee2f 92 52 SBCA FPA0+2 = +3118 ee31 97 5f STA FPA1+2 = +3119 ee33 96 5e LDA FPA1+1 * AND THE NEXT +3120 ee35 92 51 SBCA FPA0+1 * +3121 ee37 97 5e STA FPA1+1 * +3122 ee39 96 5d LDA FPA1 = AND FINALLY, THE MS BYTE OF MANTISSA +3123 ee3b 92 50 SBCA FPA0 = +3124 ee3d 97 5d STA FPA1 = +3125 ee3f 20 d8 BRA LBBD0 GO SHIFT FPA1 +3126 ee41 c6 40 LBBF8 LDB #$40 USE ONLY TWO BITS OF THE LAST BYTE (FIFTH) +3127 ee43 20 d0 BRA LBBCC GO SHIFT THE LAST BYTE +3128 ee45 56 LBBFC RORB * SHIFT CARRY (ALWAYS SET HERE) INTO +3129 ee46 56 RORB * BIT 5 AND MOVE +3130 ee47 56 RORB * BITS 1,0 TO BITS 7,6 +3131 ee48 d7 63 STB FPSBYT SAVE SUB BYTE +3132 ee4a 8d 08 BSR LBC0B MOVE MANTISSA OF FPA2 TO FPA0 +3133 ee4c 7e ec 65 JMP LBA1C NORMALIZE FPA0 +3134 ee4f c6 14 LBC06 LDB #2*10 /0' ERROR +3135 ee51 7e df 03 JMP LAC46 PROCESS THE ERROR +3136 * COPY MANTISSA FROM FPA2 TO FPA0 +3137 ee54 9e 13 LBC0B LDX FPA2 * MOVE TOP 2 BYTES +3138 ee56 9f 50 STX FPA0 * +3139 ee58 9e 15 LDX FPA2+2 = MOVE BOTTOM 2 BYTES +3140 ee5a 9f 52 STX FPA0+2 = +3141 ee5c 39 RTS +3142 * COPY A PACKED FP NUMBER FROM (X) TO FPA0 +3143 ee5d 34 02 LBC14 PSHS A SAVE ACCA +3144 ee5f ec 01 LDD 1,X GET TOP TWO MANTISSA BYTES +3145 ee61 97 54 STA FP0SGN SAVE MS BYTE OF MANTISSA AS MANTISSA SIGN +3146 ee63 8a 80 ORA #$80 UNPACK MS BYTE +3147 ee65 dd 50 STD FPA0 SAVE UNPACKED TOP 2 MANTISSA BYTES +3148 ee67 0f 63 CLR FPSBYT CLEAR MANTISSA SUB BYTE +3149 ee69 e6 84 LDB ,X GET EXPONENT TO ACCB +3150 ee6b ae 03 LDX 3,X * MOVE LAST 2 +3151 ee6d 9f 52 STX FPA0+2 * MANTISSA BYTES +3152 ee6f d7 4f STB FP0EXP SAVE EXPONENT +3153 ee71 35 82 PULS A,PC RESTORE ACCA AND RETURN +3154 +3155 ee73 8e 00 45 LBC2A LDX #V45 POINT X TO MANTISSA OF FPA4 +3156 ee76 20 06 BRA LBC35 MOVE FPA0 TO FPA4 +3157 ee78 8e 00 40 LBC2F LDX #V40 POINT X TO MANTISSA OF FPA3 +3158 ee7b 8c FCB SKP2 SKIP TWO BYTES +3159 ee7c 9e 3b LBC33 LDX VARDES POINT X TO VARIABLE DESCRIPTOR IN VARDES +3160 * PACK FPA0 AND MOVE IT TO ADDRESS IN X +3161 ee7e 96 4f LBC35 LDA FP0EXP * COPY EXPONENT +3162 ee80 a7 84 STA ,X * +3163 ee82 96 54 LDA FP0SGN GET MANTISSA SIGN BIT +3164 ee84 8a 7f ORA #$7F MASK THE BOTTOM 7 BITS +3165 ee86 94 50 ANDA FPA0 AND BIT 7 OF MANTISSA SIGN INTO BIT 7 OF MS BYTE +3166 ee88 a7 01 STA 1,X SAVE MS BYTE +3167 ee8a 96 51 LDA FPA0+1 * MOVE 2ND MANTISSA BYTE +3168 ee8c a7 02 STA 2,X * +3169 ee8e de 52 LDU FPA0+2 = MOVE BOTTOM 2 MANTISSA BYTES +3170 ee90 ef 03 STU 3,X = +3171 ee92 39 RTS +3172 * MOVE FPA1 TO FPA0 RETURN W/MANTISSA SIGN IN ACCA +3173 ee93 96 61 LBC4A LDA FP1SGN * COPY MANTISSA SIGN FROM +3174 ee95 97 54 LBC4C STA FP0SGN * FPA1 TO FPA0 +3175 ee97 9e 5c LDX FP1EXP = COPY EXPONENT + MS BYTE FROM +3176 ee99 9f 4f STX FP0EXP = FPA1 TO FPA0 +3177 ee9b 0f 63 CLR FPSBYT CLEAR MANTISSA SUB BYTE +3178 ee9d 96 5e LDA FPA1+1 * COPY 2ND MANTISSA BYTE +3179 ee9f 97 51 STA FPA0+1 * FROM FPA1 TO FPA0 +3180 eea1 96 54 LDA FP0SGN GET MANTISSA SIGN +3181 eea3 9e 5f LDX FPA1+2 * COPY 3RD AND 4TH MANTISSA BYTE +3182 eea5 9f 52 STX FPA0+2 * FROM FPA1 TO FPA0 +3183 eea7 39 RTS +3184 * TRANSFER FPA0 TO FPA1 +3185 eea8 dc 4f LBC5F LDD FP0EXP * TRANSFER EXPONENT & MS BYTE +3186 eeaa dd 5c STD FP1EXP * +3187 eeac 9e 51 LDX FPA0+1 = TRANSFER MIDDLE TWO BYTES +3188 eeae 9f 5e STX FPA1+1 = +3189 eeb0 9e 53 LDX FPA0+3 * TRANSFER BOTTOM TWO BYTES +3190 eeb2 9f 60 STX FPA1+3 * +3191 eeb4 4d TSTA SET FLAGS ACCORDING TO EXPONENT +3192 eeb5 39 RTS +3193 * CHECK FPA0; RETURN ACCB = 0 IF FPA0 = 0, +3194 * ACCB = $FF IF FPA0 = NEGATIVE, ACCB = 1 IF FPA0 = POSITIVE +3195 eeb6 d6 4f LBC6D LDB FP0EXP GET EXPONENT +3196 eeb8 27 08 BEQ LBC79 BRANCH IF FPA0 = 0 +3197 eeba d6 54 LBC71 LDB FP0SGN GET SIGN OF MANTISSA +3198 eebc 59 LBC73 ROLB BIT 7 TO CARRY +3199 eebd c6 ff LDB #$FF NEGATIVE FLAG +3200 eebf 25 01 BCS LBC79 BRANCH IF NEGATIVE MANTISSA +3201 eec1 50 NEGB ACCB = 1 IF POSITIVE MANTISSA +3202 eec2 39 LBC79 RTS +3203 +3204 * SGN +3205 eec3 8d f1 SGN BSR LBC6D SET ACCB ACCORDING TO SIGN OF FPA0 +3206 * CONVERT A SIGNED NUMBER IN ACCB INTO A FLOATING POINT NUMBER +3207 eec5 d7 50 LBC7C STB FPA0 SAVE ACCB IN FPA0 +3208 eec7 0f 51 CLR FPA0+1 CLEAR NUMBER 2 MANTISSA BYTE OF FPA0 +3209 eec9 c6 88 LDB #$88 EXPONENT REQUIRED IF FPA0 IS TO BE AN INTEGER +3210 eecb 96 50 LBC82 LDA FPA0 GET MS BYTE OF MANTISSA +3211 eecd 80 80 SUBA #$80 SET CARRY IF POSITIVE MANTISSA +3212 eecf d7 4f LBC86 STB FP0EXP SAVE EXPONENT +3213 eed1 dc 74 LDD ZERO * ZERO OUT ACCD AND +3214 eed3 dd 52 STD FPA0+2 * BOTTOM HALF OF FPA0 +3215 eed5 97 63 STA FPSBYT CLEAR SUB BYTE +3216 eed7 97 54 STA FP0SGN CLEAR SIGN OF FPA0 MANTISSA +3217 eed9 7e ec 61 JMP LBA18 GO NORMALIZE FPA0 +3218 +3219 * ABS +3220 eedc 0f 54 ABS CLR FP0SGN FORCE MANTISSA SIGN OF FPA0 POSITIVE +3221 eede 39 RTS +3222 * COMPARE A PACKED FLOATING POINT NUMBER POINTED TO +3223 * BY (X) TO AN UNPACKED FP NUMBER IN FPA0. RETURN +3224 * ZERO FLAG SET AND ACCB = 0, IF EQUAL; ACCB = 1 IF +3225 * FPA0 > (X); ACCB = $FF IF FPA0 < (X) +3226 eedf e6 84 LBC96 LDB ,X CHECK EXPONENT OF (X) +3227 eee1 27 d3 BEQ LBC6D BRANCH IF FPA = 0 +3228 eee3 e6 01 LDB 1,X GET MS BYTE OF MANTISSA OF (X) +3229 eee5 d8 54 EORB FP0SGN EOR WITH SIGN OF FPA0 +3230 eee7 2b d1 BMI LBC71 BRANCH IF SIGNS NOT = +3231 * COMPARE FPA0 WITH FP NUMBER POINTED TO BY (X). +3232 * FPA0 IS NORMALIZED, (X) IS PACKED. +3233 eee9 d6 4f LBCA0 LDB FP0EXP * GET EXPONENT OF +3234 eeeb e1 84 CMPB ,X * FPA0, COMPARE TO EXPONENT OF +3235 eeed 26 1d BNE LBCC3 * (X) AND BRANCH IF <>. +3236 eeef e6 01 LDB 1,X * GET MS BYTE OF (X), KEEP ONLY +3237 eef1 ca 7f ORB #$7F * THE SIGN BIT - 'AND' THE BOTTOM 7 +3238 eef3 d4 50 ANDB FPA0 * BITS OF FPA0 INTO ACCB +3239 eef5 e1 01 CMPB 1,X = COMPARE THE BOTTOM 7 BITS OF THE MANTISSA +3240 eef7 26 13 BNE LBCC3 = MS BYTE AND BRANCH IF <> +3241 eef9 d6 51 LDB FPA0+1 * COMPARE 2ND BYTE +3242 eefb e1 02 CMPB 2,X * OF MANTISSA, +3243 eefd 26 0d BNE LBCC3 * BRANCH IF <> +3244 eeff d6 52 LDB FPA0+2 = COMPARE 3RD BYTE +3245 ef01 e1 03 CMPB 3,X = OF MANTISSA, +3246 ef03 26 07 BNE LBCC3 = BRANCH IF <> +3247 ef05 d6 53 LDB FPA0+3 * SUBTRACT LS BYTE +3248 ef07 e0 04 SUBB 4,X * OF (X) FROM LS BYTE OF +3249 ef09 26 01 BNE LBCC3 * FPA0, BRANCH IF <> +3250 ef0b 39 RTS RETURN IF FP (X) = FPA0 +3251 ef0c 56 LBCC3 RORB SHIFT CARRY TO BIT 7; CARRY SET IF FPA0 < (X) +3252 ef0d d8 54 EORB FP0SGN TOGGLE SIZE COMPARISON BIT IF FPA0 IS NEGATIVE +3253 ef0f 20 ab BRA LBC73 GO SET ACCB ACCORDING TO COMPARISON +3254 * DE-NORMALIZE FPA0 : SHIFT THE MANTISSA UNTIL THE BINARY POINT IS TO THE RIGHT +3255 * OF THE LEAST SIGNIFICANT BYTE OF THE MANTISSA +3256 ef11 d6 4f LBCC8 LDB FP0EXP GET EXPONENT OF FPA0 +3257 ef13 27 3d BEQ LBD09 ZERO MANTISSA IF FPA0 = 0 +3258 ef15 c0 a0 SUBB #$A0 SUBTRACT $A0 FROM FPA0 EXPONENT T THIS WILL YIELD +3259 * THE NUMBER OF SHIFTS REQUIRED TO DENORMALIZE FPA0. WHEN +3260 * THE EXPONENT OF FPA0 IS = ZERO, THEN THE BINARY POINT +3261 * WILL BE TO THE RIGHT OF THE MANTISSA +3262 ef17 96 54 LDA FP0SGN TEST SIGN OF FPA0 MANTISSA +3263 ef19 2a 05 BPL LBCD7 BRANCH IF POSITIVE +3264 ef1b 03 5b COM FPCARY COMPLEMENT CARRY IN BYTE +3265 ef1d bd ec c4 JSR LBA7B NEGATE MANTISSA OF FPA0 +3266 ef20 8e 00 4f LBCD7 LDX #FP0EXP POINT X TO FPA0 +3267 ef23 c1 f8 CMPB #-8 EXPONENT DIFFERENCE < -8? +3268 ef25 2e 06 BGT LBCE4 YES +3269 ef27 bd ec f7 JSR LBAAE SHIFT FPA0 RIGHT UNTIL FPA0 EXPONENT = $A0 +3270 ef2a 0f 5b CLR FPCARY CLEAR CARRY IN BYTE +3271 ef2c 39 RTS +3272 ef2d 0f 5b LBCE4 CLR FPCARY CLEAR CARRY IN BYTE +3273 ef2f 96 54 LDA FP0SGN * GET SIGN OF FPA0 MANTISSA +3274 ef31 49 ROLA * ROTATE IT INTO THE CARRY FLAG +3275 ef32 06 50 ROR FPA0 ROTATE CARRY (MANTISSA SIGN) INTO BIT 7 +3276 * OF LS BYTE OF MANTISSA +3277 ef34 7e ed 03 JMP LBABA DE-NORMALIZE FPA0 +3278 +3279 * INT +3280 * THE INT STATEMENT WILL "DENORMALIZE" FPA0 - THAT IS IT WILL SHIFT THE BINARY POINT +3281 * TO THE EXTREME RIGHT OF THE MANTISSA TO FORCE ITS EXPONENT TO BE $AO. ONCE +3282 * THIS IS DONE THE MANTISSA OF FPA0 WILL CONTAIN THE FOUR LEAST SIGNIFICANT +3283 * BYTES OF THE INTEGER PORTION OF FPA0. AT THE CONCLUSION OF THE DE-NORMALIZATION +3284 * ONLY THE INTEGER PORTION OF FPA0 WILL REMAIN. +3285 * +3286 ef37 d6 4f INT LDB FP0EXP GET EXPONENT OF FPA0 +3287 ef39 c1 a0 CMPB #$A0 LARGEST POSSIBLE INTEGER EXPONENT +3288 ef3b 24 1d BCC LBD11 RETURN IF FPA0 >= 32768 +3289 ef3d 8d d2 BSR LBCC8 SHIFT THE BINARY POINT ONE TO THE RIGHT OF THE +3290 * LS BYTE OF THE FPA0 MANTISSA +3291 ef3f d7 63 STB FPSBYT ACCB = 0: ZERO OUT THE SUB BYTE +3292 ef41 96 54 LDA FP0SGN GET MANTISSA SIGN +3293 ef43 d7 54 STB FP0SGN FORCE MANTISSA SIGN TO BE POSITIVE +3294 ef45 80 80 SUBA #$80 SET CARRY IF MANTISSA +3295 ef47 86 a0 LDA #$A0 * GET DENORMALIZED EXPONENT AND +3296 ef49 97 4f STA FP0EXP * SAVE IT IN FPA0 EXPONENT +3297 ef4b 96 53 LDA FPA0+3 = GET LS BYTE OF FPA0 AND +3298 ef4d 97 01 STA CHARAC = SAVE IT IN CHARAC +3299 ef4f 7e ec 61 JMP LBA18 NORMALIZE FPA0 +3300 +3301 ef52 d7 50 LBD09 STB FPA0 * LOAD MANTISSA OF FPA0 WITH CONTENTS OF ACCB +3302 ef54 d7 51 STB FPA0+1 * +3303 ef56 d7 52 STB FPA0+2 * +3304 ef58 d7 53 STB FPA0+3 * +3305 ef5a 39 LBD11 RTS * +3306 +3307 * CONVERT ASCII STRING TO FLOATING POINT +3308 ef5b 9e 74 LBD12 LDX ZERO (X) = 0 +3309 ef5d 9f 54 STX FP0SGN * ZERO OUT FPA0 & THE SIGN FLAG (COEFCT) +3310 ef5f 9f 4f STX FP0EXP * +3311 ef61 9f 51 STX FPA0+1 * +3312 ef63 9f 52 STX FPA0+2 * +3313 ef65 9f 47 STX V47 INITIALIZE EXPONENT & EXPONENT SIGN FLAG TO ZERO +3314 ef67 9f 45 STX V45 INITIALIZE RIGHT DECIMAL CTR & DECIMAL PT FLAG TO 0 +3315 ef69 25 64 BCS LBD86 IF CARRY SET (NUMERIC CHARACTER), ASSUME ACCA CONTAINS FIRST +3316 * NUMERIC CHAR, SIGN IS POSITIVE AND SKIP THE RAM HOOK +3317 ef6b bd f6 98 JSR XVEC19 CALL EXTENDED BASIC ADD-IN +3318 ef6e 81 2d LBD25 CMPA #'- * CHECK FOR A LEADING MINUS SIGN AND BRANCH +3319 ef70 26 04 BNE LBD2D * IF NO MINUS SIGN +3320 ef72 03 55 COM COEFCT TOGGLE SIGN; 0 = +; FF = - +3321 ef74 20 04 BRA LBD31 INTERPRET THE REST OF THE STRING +3322 ef76 81 2b LBD2D CMPA #'+ * CHECK FOR LEADING PLUS SlGN AND BRANCH +3323 ef78 26 04 BNE LBD35 * IF NOT A PLUS SIGN +3324 ef7a 9d 7c LBD31 JSR GETNCH GET NEXT INPUT CHARACTER FROM BASIC +3325 ef7c 25 51 BCS LBD86 BRANCH IF NUMERIC CHARACTER +3326 ef7e 81 2e LBD35 CMPA #'. DECIMAL POlNT? +3327 ef80 27 28 BEQ LBD61 YES +3328 ef82 81 45 CMPA #'E "E" SHORTHAND FORM (SCIENTIFIC NOTATION)? +3329 ef84 26 28 BNE LBD65 NO +3330 * EVALUATE EXPONENT OF EXPONENTIAL FORMAT +3331 ef86 9d 7c JSR GETNCH GET NEXT INPUT CHARACTER FROM BASIC +3332 ef88 25 64 BCS LBDA5 BRANCH IF NUMERIC +3333 ef8a 81 a7 CMPA #TOK_MINUS MINUS TOKEN? +3334 ef8c 27 0e BEQ LBD53 YES +3335 ef8e 81 2d CMPA #'- ASCII MINUS? +3336 ef90 27 0a BEQ LBD53 YES +3337 ef92 81 a6 CMPA #TOK_PLUS PLUS TOKEN? +3338 ef94 27 08 BEQ LBD55 YES +3339 ef96 81 2b CMPA #'+ ASCII PLUS? +3340 ef98 27 04 BEQ LBD55 YES +3341 ef9a 20 06 BRA LBD59 BRANCH IF NO SIGN FOUND +3342 ef9c 03 48 LBD53 COM V48 SET EXPONENT SIGN FLAG TO NEGATIVE +3343 * STRIP A DECIMAL NUMBER FROM BASIC LINE, CONVERT IT TO BINARY IN V47 +3344 ef9e 9d 7c LBD55 JSR GETNCH GET NEXT INPUT CHARACTER FROM BASIC +3345 efa0 25 4c BCS LBDA5 IF NUMERIC CHARACTER, CONVERT TO BINARY +3346 efa2 0d 48 LBD59 TST V48 * CHECK EXPONENT SIGN FLAG +3347 efa4 27 08 BEQ LBD65 * AND BRANCH IF POSITIVE +3348 efa6 00 47 NEG V47 NEGATE VALUE OF EXPONENT +3349 efa8 20 04 BRA LBD65 +3350 efaa 03 46 LBD61 COM V46 *TOGGLE DECIMAL PT FLAG AND INTERPRET ANOTHER +3351 efac 26 cc BNE LBD31 *CHARACTER IF <> 0 - TERMINATE INTERPRETATION +3352 * IF SECOND DECIMAL POINT +3353 * ADJUST FPA0 FOR THE DECIMAL EXPONENT IN V47 +3354 efae 96 47 LBD65 LDA V47 * GET EXPONENT, SUBTRACT THE NUMBER OF +3355 efb0 90 45 SUBA V45 * PLACES TO THE RIGHT OF DECIMAL POINT +3356 efb2 97 47 STA V47 * AND RESAVE IT. +3357 efb4 27 12 BEQ LBD7F EXIT ROUTINE IF ADJUSTED EXPONENT = ZERO +3358 efb6 2a 09 BPL LBD78 BRANCH IF POSITIVE EXPONENT +3359 efb8 bd ed cb LBD6F JSR LBB82 DIVIDE FPA0 BY 10 +3360 efbb 0c 47 INC V47 INCREMENT EXPONENT COUNTER (MULTIPLY BY 10) +3361 efbd 26 f9 BNE LBD6F KEEP MULTIPLYING +3362 efbf 20 07 BRA LBD7F EXIT ROUTINE +3363 efc1 bd ed b3 LBD78 JSR LBB6A MULTIPLY FPA0 BY 10 +3364 efc4 0a 47 DEC V47 DECREMENT EXPONENT COUNTER (DIVIDE BY 10) +3365 efc6 26 f9 BNE LBD78 KEEP MULTIPLYING +3366 efc8 96 55 LBD7F LDA COEFCT GET THE SIGN FLAG +3367 efca 2a 8e BPL LBD11 RETURN IF POSITIVE +3368 efcc 7e f1 32 JMP LBEE9 TOGGLE MANTISSA SIGN OF FPA0, IF NEGATIVE +3369 *MULTIPLY FPA0 BY TEN AND ADD ACCA TO THE RESULT +3370 efcf d6 45 LBD86 LDB V45 *GET THE RIGHT DECIMAL COUNTER AND SUBTRACT +3371 efd1 d0 46 SUBB V46 *THE DECIMAL POINT FLAG FROM IT. IF DECIMAL POINT +3372 efd3 d7 45 STB V45 *FLAG=0, NOTHING HAPPENS. IF DECIMAL POINT FLAG IS +3373 * -1, THEN RIGHT DECIMAL COUNTER IS INCREMENTED BY ONE +3374 efd5 34 02 PSHS A SAVE NEW DIGIT ON STACK +3375 efd7 bd ed b3 JSR LBB6A MULTIPLY FPA0 BY 10 +3376 efda 35 04 PULS B GET NEW DIGIT BACK +3377 efdc c0 30 SUBB #'0 MASK OFF ASCII +3378 efde 8d 02 BSR LBD99 ADD ACCB TO FPA0 +3379 efe0 20 98 BRA LBD31 GET ANOTHER CHARACTER FROM BASIC +3380 efe2 bd ee 78 LBD99 JSR LBC2F PACK FPA0 AND SAVE IT IN FPA3 +3381 efe5 bd ee c5 JSR LBC7C CONVERT ACCB TO FP NUMBER IN FPA0 +3382 efe8 8e 00 40 LDX #V40 * ADD FPA0 TO +3383 efeb 7e ec 0b JMP LB9C2 * FPA3 +3384 +3385 +3386 efee d6 47 LBDA5 LDB V47 +3387 eff0 58 ASLB TIMES 2 +3388 eff1 58 ASLB TIMES 4 +3389 eff2 db 47 ADDB V47 ADD 1 = TIMES 5 +3390 eff4 58 ASLB TIMES 10 +3391 eff5 80 30 SUBA #'0 *MASK OFF ASCII FROM ACCA, PUSH +3392 eff7 34 04 PSHS B *RESULT ONTO THE STACK AND +3393 eff9 ab e0 ADDA ,S+ ADD lT TO ACCB +3394 effb 97 47 STA V47 SAVE IN V47 +3395 effd 20 9f BRA LBD55 INTERPRET ANOTHER CHARACTER +3396 * +3397 efff 9b 3e bc 1f fd LBDB6 FCB $9B,$3E,$BC,$1F,$FD * 99999999.9 +3398 f004 9e 6e 6b 27 fd LBDBB FCB $9E,$6E,$6B,$27,$FD * 999999999 +3399 f009 9e 6e 6b 28 00 LBDC0 FCB $9E,$6E,$6B,$28,$00 * 1E + 09 +3400 * +3401 f00e 8e de a4 LBDC5 LDX #LABE8-1 POINT X TO " IN " MESSAGE +3402 f011 8d 0c BSR LBDD6 COPY A STRING FROM (X) TO CONSOLE OUT +3403 f013 dc 68 LDD CURLIN GET CURRENT BASIC LINE NUMBER TO ACCD +3404 * CONVERT VALUE IN ACCD INTO A DECIMAL NUMBER +3405 * AND PRINT IT TO CONSOLE OUT +3406 f015 dd 50 LBDCC STD FPA0 SAVE ACCD IN TOP HALF OF FPA0 +3407 f017 c6 90 LDB #$90 REQ’D EXPONENT IF TOP HALF OF ACCD = INTEGER +3408 f019 43 COMA SET CARRY FLAG - FORCE POSITIVE MANTISSA +3409 f01a bd ee cf JSR LBC86 ZERO BOTTOM HALF AND SIGN OF FPA0, THEN +3410 * SAVE EXPONENT AND NORMALIZE IT +3411 f01d 8d 03 BSR LBDD9 CONVERT FP NUMBER TO ASCII STRING +3412 f01f 7e eb e5 LBDD6 JMP LB99C COPY A STRING FROM (X) TO CONSOLE OUT +3413 +3414 * CONVERT FP NUMBER TO ASCII STRING +3415 f022 ce 01 f1 LBDD9 LDU #STRBUF+3 POINT U TO BUFFER WHICH WILL NOT CAUSE +3416 * THE STRING TO BE STORED IN STRING SPACE +3417 f025 86 20 LBDDC LDA #SPACE SPACE = DEFAULT SIGN FOR POSITIVE # +3418 f027 d6 54 LDB FP0SGN GET SIGN OF FPA0 +3419 f029 2a 02 BPL LBDE4 BRANCH IF POSITIVE +3420 f02b 86 2d LDA #'- ASCII MINUS SIGN +3421 f02d a7 c0 LBDE4 STA ,U+ STORE SIGN OF NUMBER +3422 f02f df 64 STU COEFPT SAVE BUFFER POINTER +3423 f031 97 54 STA FP0SGN SAVE SIGN (IN ASCII) +3424 f033 86 30 LDA #'0 ASCII ZERO IF EXPONENT = 0 +3425 f035 d6 4f LDB FP0EXP GET FPA0 EXPONENT +3426 f037 10 27 00 c6 LBEQ LBEB8 BRANCH IF FPA0 = 0 +3427 f03b 4f CLRA BASE 10 EXPONENT=0 FOR FP NUMBER > 1 +3428 f03c c1 80 CMPB #$80 CHECK EXPONENT +3429 f03e 22 08 BHI LBDFF BRANCH IF FP NUMBER > 1 +3430 * IF FPA0 < 1.0, MULTIPLY IT BY 1E+09 TO SPEED UP THE CONVERSION PROCESS +3431 f040 8e f0 09 LDX #LBDC0 POINT X TO FP 1E+09 +3432 f043 bd ed 13 JSR LBACA MULTIPLY FPA0 BY (X) +3433 f046 86 f7 LDA #-9 BASE 10 EXPONENT = -9 +3434 f048 97 45 LBDFF STA V45 BASE 10 EXPONENT +3435 * PSEUDO - NORMALIZE THE FP NUMBER TO A VALUE IN THE RANGE +3436 * OF 999,999,999 RO 99,999,999.9 - THIS IS THE LARGEST +3437 * NUMBER RANGE IN WHICH ALL OF THE DIGITS ARE +3438 * SIGNIFICANT WHICH CAN BE DISPLAYED WITHOUT USING +3439 * SCIENTIFIC NOTATION +3440 f04a 8e f0 04 LBE01 LDX #LBDBB POINT X TO FP 999,999,999 +3441 f04d bd ee e9 JSR LBCA0 COMPARE FPA0 TO 999,999,999 +3442 f050 2e 0f BGT LBE18 BRANCH IF > 999,999,999 +3443 f052 8e ef ff LBE09 LDX #LBDB6 POINT X TO FP 99,999,999.9 +3444 f055 bd ee e9 JSR LBCA0 COMPARE FPA0 TO 99,999,999.9 +3445 f058 2e 0e BGT LBE1F BRANCH IF > 99,999,999.9 (IN RANGE) +3446 f05a bd ed b3 JSR LBB6A MULTIPLY FPA0 BY 10 +3447 f05d 0a 45 DEC V45 SUBTRACT ONE FROM DECIMAL OFFSET +3448 f05f 20 f1 BRA LBE09 PSEUDO - NORMALIZE SOME MORE +3449 f061 bd ed cb LBE18 JSR LBB82 DIVIDE FPA0 BY 10 +3450 f064 0c 45 INC V45 ADD ONE TO BASE 10 EXPONENT +3451 f066 20 e2 BRA LBE01 PSEUDO - NORMALIZE SOME MORE +3452 f068 bd eb fd LBE1F JSR LB9B4 ADD .5 TO FPA0 (ROUND OFF) +3453 f06b bd ef 11 JSR LBCC8 CONVERT FPA0 TO AN INTEGER +3454 f06e c6 01 LDB #1 DEFAULT DECIMAL POINT FLAG (FORCE IMMED DECIMAL PT) +3455 f070 96 45 LDA V45 * GET BASE 10 EXPONENT AND ADD TEN TO IT +3456 f072 8b 0a ADDA #9+1 * (NUMBER ‘NORMALIZED’ TO 9 PLACES & DECIMAL PT) +3457 f074 2b 09 BMI LBE36 BRANCH IF NUMBER < 1.0 +3458 f076 81 0b CMPA #9+2 NINE PLACES MAY BE DISPLAYED WITHOUT +3459 * USING SCIENTIFIC NOTATION +3460 f078 24 05 BCC LBE36 BRANCH IF SCIENTIFIC NOTATION REQUIRED +3461 f07a 4a DECA * SUBTRACT 1 FROM MODIFIED BASE 10 EXPONENT CTR +3462 f07b 1f 89 TFR A,B * AND SAVE IT IN ACCB (DECiMAL POINT FLAG) +3463 f07d 86 02 LDA #2 FORCE EXPONENT = 0 - DON'T USE SCIENTIFIC NOTATION +3464 f07f 4a LBE36 DECA * SUBTRACT TWO (WITHOUT AFFECTING CARRY) +3465 f080 4a DECA * FROM BASE 10 EXPONENT +3466 f081 97 47 STA V47 SAVE EXPONENT - ZERO EXPONENT = DO NOT DISPLAY +3467 * IN SCIENTIFIC NOTATION +3468 f083 d7 45 STB V45 DECIMAL POINT FLAG - NUMBER OF PLACES TO +3469 * LEFT OF DECIMAL POINT +3470 f085 2e 0d BGT LBE4B BRANCH IF >= 1 +3471 f087 de 64 LDU COEFPT POINT U TO THE STRING BUFFER +3472 f089 86 2e LDA #'. * STORE A PERIOD +3473 f08b a7 c0 STA ,U+ * IN THE BUFFER +3474 f08d 5d TSTB CHECK DECIMAL POINT FLAG +3475 f08e 27 04 BEQ LBE4B BRANCH IF NOTHING TO LEFT OF DECIMAL POINT +3476 f090 86 30 LDA #'0 * STORE A ZERO +3477 f092 a7 c0 STA ,U+ * IN THE BUFFER +3478 +3479 * CONVERT FPA0 INTO A STRING OF ASCII DIGITS +3480 f094 8e f1 0e LBE4B LDX #LBEC5 POINT X TO FP POWER OF 10 MANTISSA +3481 f097 c6 80 LDB #0+$80 INITIALIZE DIGIT COUNTER TO 0+$80 +3482 * BIT 7 SET IS USED TO INDICATE THAT THE POWER OF 10 MANTISSA +3483 * IS NEGATIVE. WHEN YOU 'ADD' A NEGATIVE MANTISSA, IT IS +3484 * THE SAME AS SUBTRACTING A POSITIVE ONE AND BIT 7 OF ACCB IS HOW +3485 * THE ROUTINE KNOWS THAT A 'SUBTRACTION' IS OCCURING. +3486 f099 96 53 LBE50 LDA FPA0+3 * ADD MANTISSA LS +3487 f09b ab 03 ADDA 3,X * BYTE OF FPA0 +3488 f09d 97 53 STA FPA0+3 * AND (X) +3489 f09f 96 52 LDA FPA0+2 = ADD MANTISSA +3490 f0a1 a9 02 ADCA 2,X = NUMBER 3 BYTE OF +3491 f0a3 97 52 STA FPA0+2 = FPA0 AND (X) +3492 f0a5 96 51 LDA FPA0+1 * ADD MANTISSA +3493 f0a7 a9 01 ADCA 1,X * NUMBER 2 BYTE OF +3494 f0a9 97 51 STA FPA0+1 * FPA0 AND (X) +3495 f0ab 96 50 LDA FPA0 = ADD MANTISSA +3496 f0ad a9 84 ADCA ,X = MS BYTE OF +3497 f0af 97 50 STA FPA0 = FPA0 AND (X) +3498 f0b1 5c INCB ADD ONE TO DIGIT COUNTER +3499 f0b2 56 RORB ROTATE CARRY INTO BIT 7 +3500 f0b3 59 ROLB *SET OVERFLOW FLAG AND BRANCH IF CARRY = 1 AND +3501 f0b4 28 e3 BVC LBE50 *POSITIVE MANTISSA OR CARRY = 0 AND NEG MANTISSA +3502 f0b6 24 03 BCC LBE72 BRANCH IF NEGATIVE MANTISSA +3503 f0b8 c0 0b SUBB #10+1 * TAKE THE 9’S COMPLEMENT IF +3504 f0ba 50 NEGB * ADDING MANTISSA +3505 f0bb cb 2f LBE72 ADDB #'0-1 ADD ASCII OFFSET TO DIGIT +3506 f0bd 30 04 LEAX 4,X MOVE TO NEXT POWER OF 10 MANTISSA +3507 f0bf 1f 98 TFR B,A SAVE DIGIT IN ACCA +3508 f0c1 84 7f ANDA #$7F MASK OFF BIT 7 (ADD/SUBTRACT FLAG) +3509 f0c3 a7 c0 STA ,U+ STORE DIGIT IN STRING BUFFER +3510 f0c5 0a 45 DEC V45 DECREMENT DECIMAL POINT FLAG +3511 f0c7 26 04 BNE LBE84 BRANCH IF NOT TIME FOR DECIMAL POINT +3512 f0c9 86 2e LDA #'. * STORE DECIMAL POINT IN +3513 f0cb a7 c0 STA ,U+ * STRING BUFFER +3514 f0cd 53 LBE84 COMB TOGGLE BIT 7 (ADD/SUBTRACT FLAG) +3515 f0ce c4 80 ANDB #$80 MASK OFF ALL BUT ADD/SUBTRACT FLAG +3516 f0d0 8c f1 32 CMPX #LBEC5+36 COMPARE X TO END OF MANTISSA TABLE +3517 f0d3 26 c4 BNE LBE50 BRANCH IF NOT AT END OF TABLE +3518 * BLANK TRAILING ZEROS AND STORE EXPONENT IF ANY +3519 f0d5 a6 c2 LBE8C LDA ,-U GET THE LAST CHARACTER; MOVE POINTER BACK +3520 f0d7 81 30 CMPA #'0 WAS IT A ZERO? +3521 f0d9 27 fa BEQ LBE8C IGNORE TRAILING ZEROS IF SO +3522 f0db 81 2e CMPA #'. CHECK FOR DECIMAL POINT +3523 f0dd 26 02 BNE LBE98 BRANCH IF NOT DECIMAL POINT +3524 f0df 33 5f LEAU -1,U STEP OVER THE DECIMAL POINT +3525 f0e1 86 2b LBE98 LDA #'+ ASCII PLUS SIGN +3526 f0e3 d6 47 LDB V47 GET SCIENTIFIC NOTATION EXPONENT +3527 f0e5 27 1c BEQ LBEBA BRANCH IF NOT SCIENTIFIC NOTATION +3528 f0e7 2a 03 BPL LBEA3 BRANCH IF POSITIVE EXPONENT +3529 f0e9 86 2d LDA #'- ASCII MINUS SIGN +3530 f0eb 50 NEGB NEGATE EXPONENT IF NEGATIVE +3531 f0ec a7 42 LBEA3 STA 2,U STORE EXPONENT SIGN IN STRING +3532 f0ee 86 45 LDA #'E * GET ASCII ‘E’ (SCIENTIFIC NOTATION +3533 f0f0 a7 41 STA 1,U * FLAG) AND SAVE IT IN THE STRING +3534 f0f2 86 2f LDA #'0-1 INITIALIZE ACCA TO ASCII ZERO +3535 +3536 +3537 f0f4 4c LBEAB INCA ADD ONE TO 10’S DIGIT OF EXPONENT +3538 f0f5 c0 0a SUBB #10 SUBTRACT 10 FROM ACCB +3539 f0f7 24 fb BCC LBEAB ADD 1 TO 10’S DIGIT IF NO CARRY +3540 f0f9 cb 3a ADDB #'9+1 CONVERT UNITS DIGIT TO ASCII +3541 f0fb ed 43 STD 3,U SAVE EXPONENT IN STRING +3542 f0fd 6f 45 CLR 5,U CLEAR LAST BYTE (TERMINATOR) +3543 f0ff 20 04 BRA LBEBC GO RESET POINTER +3544 f101 a7 c4 LBEB8 STA ,U STORE LAST CHARACTER +3545 f103 6f 41 LBEBA CLR 1,U CLEAR LAST BYTE (TERMINATOR - REQUIRED BY +3546 * PRINT SUBROUTINES) +3547 f105 8e 01 f1 LBEBC LDX #STRBUF+3 RESET POINTER TO START OF BUFFER +3548 f108 39 RTS +3549 * +3550 f109 80 00 00 00 00 LBEC0 FCB $80,$00,$00,$00,$00 FLOATING POINT .5 +3551 * +3552 *** TABLE OF UNNORMALIZED POWERS OF 10 +3553 f10e fa 0a 1f 00 LBEC5 FCB $FA,$0A,$1F,$00 -100000000 +3554 f112 00 98 96 80 LBEC9 FCB $00,$98,$96,$80 10000000 +3555 f116 ff f0 bd c0 LBECD FCB $FF,$F0,$BD,$C0 -1000000 +3556 f11a 00 01 86 a0 LBED1 FCB $00,$01,$86,$A0 100000 +3557 f11e ff ff d8 f0 LBED5 FCB $FF,$FF,$D8,$F0 -10000 +3558 f122 00 00 03 e8 LBED9 FCB $00,$00,$03,$E8 1000 +3559 f126 ff ff ff 9c LBEDD FCB $FF,$FF,$FF,$9C -100 +3560 f12a 00 00 00 0a LBEE1 FCB $00,$00,$00,$0A 10 +3561 f12e ff ff ff ff LBEE5 FCB $FF,$FF,$FF,$FF -1 +3562 * +3563 * +3564 f132 96 4f LBEE9 LDA FP0EXP GET EXPONENT OF FPA0 +3565 f134 27 02 BEQ LBEEF BRANCH IF FPA0 = 0 +3566 f136 03 54 COM FP0SGN TOGGLE MANTISSA SIGN OF FPA0 +3567 f138 39 LBEEF RTS +3568 * EXPAND A POLYNOMIAL OF THE FORM +3569 * AQ+BQ**3+CQ**5+DQ**7.... WHERE Q = FPA0 +3570 * AND THE X REGISTER POINTS TO A TABLE OF +3571 * COEFFICIENTS A,B,C,D.... +3572 f139 9f 64 LBEF0 STX COEFPT SAVE COEFFICIENT TABLE POINTER +3573 f13b bd ee 78 JSR LBC2F MOVE FPA0 TO FPA3 +3574 f13e 8d 05 BSR LBEFC MULTIPLY FPA3 BY FPA0 +3575 f140 8d 08 BSR LBF01 EXPAND POLYNOMIAL +3576 f142 8e 00 40 LDX #V40 POINT X TO FPA3 +3577 f145 7e ed 13 LBEFC JMP LBACA MULTIPLY (X) BY FPA0 +3578 +3579 * CALCULATE THE VALUE OF AN EXPANDED POLYNOMIAL +3580 * EXPRESSION. ENTER WITH (X) POINTING TO A TABLE +3581 * OF COEFFICIENTS, THE FIRST BYTE OF WHICH IS THE +3582 * NUMBER OF (COEFFICIENTS-1) FOLLOWED BY THAT NUMBER +3583 * OF PACKED FLOATING POINT NUMBERS. THE +3584 * POLYNOMIAL IS EVALUATED AS FOLLOWS: VALUE = +3585 * (((FPA0*Y0+Y1)*FPA0+Y2)*FPA0…YN) +3586 f148 9f 64 LBEFF STX COEFPT SAVE COEFFICIENT TABLE POINTER +3587 f14a bd ee 73 LBF01 JSR LBC2A MOVE FPA0 TO FPA4 +3588 f14d 9e 64 LDX COEFPT GET THE COEFFICIENT POINTER +3589 f14f e6 80 LDB ,X+ GET THE TOP OF COEFFICIENT TABLE TO +3590 f151 d7 55 STB COEFCT * USE AND STORE IT IN TEMPORARY COUNTER +3591 f153 9f 64 STX COEFPT SAVE NEW COEFFICIENT POINTER +3592 f155 8d ee LBF0C BSR LBEFC MULTIPLY (X) BY FPA0 +3593 f157 9e 64 LDX COEFPT *GET COEFFICIENT POINTER +3594 f159 30 05 LEAX 5,X *MOVE TO NEXT FP NUMBER +3595 f15b 9f 64 STX COEFPT *SAVE NEW COEFFICIENT POINTER +3596 f15d bd ec 0b JSR LB9C2 ADD (X) AND FPA0 +3597 f160 8e 00 45 LDX #V45 POINT (X) TO FPA4 +3598 f163 0a 55 DEC COEFCT DECREMENT TEMP COUNTER +3599 f165 26 ee BNE LBF0C BRANCH IF MORE COEFFICIENTS LEFT +3600 f167 39 RTS +3601 +3602 * RND +3603 f168 bd ee b6 RND JSR LBC6D TEST FPA0 +3604 f16b 2b 1f BMI LBF45 BRANCH IF FPA0 = NEGATIVE +3605 f16d 27 15 BEQ LBF3B BRANCH IF FPA0 = 0 +3606 f16f 8d 10 BSR LBF38 CONVERT FPA0 TO AN INTEGER +3607 f171 bd ee 78 JSR LBC2F PACK FPA0 TO FPA3 +3608 f174 8d 0e BSR LBF3B GET A RANDOM NUMBER: FPA0 < 1.0 +3609 f176 8e 00 40 LDX #V40 POINT (X) TO FPA3 +3610 f179 8d ca BSR LBEFC MULTIPLY (X) BY FPA0 +3611 f17b 8e ed 0e LDX #LBAC5 POINT (X) TO FP VALUE OF 1.0 +3612 f17e bd ec 0b JSR LB9C2 ADD 1.0 TO FPA0 +3613 f181 7e ef 37 LBF38 JMP INT CONVERT FPA0 TO AN INTEGER +3614 * CALCULATE A RANDOM NUMBER IN THE RANGE 0.0 < X <= 1.0 +3615 f184 9e b1 LBF3B LDX RVSEED+1 * MOVE VARIABLE +3616 f186 9f 50 STX FPA0 * RANDOM NUMBER +3617 f188 9e b3 LDX RVSEED+3 * SEED TO +3618 f18a 9f 52 STX FPA0+2 * FPA0 +3619 f18c be f1 b9 LBF45 LDX RSEED = MOVE FIXED +3620 f18f 9f 5d STX FPA1 = RANDOM NUMBER +3621 f191 be f1 bb LDX RSEED+2 = SEED TO +3622 f194 9f 5f STX FPA1+2 = MANTISSA OF FPA0 +3623 f196 bd ed 19 JSR LBAD0 MULTIPLY FPA0 X FPA1 +3624 f199 dc 8a LDD VAD GET THE TWO LOWEST ORDER PRODUCT BYTES +3625 f19b c3 65 8b ADDD #$658B ADD A CONSTANT +3626 f19e dd b3 STD RVSEED+3 SAVE NEW LOW ORDER VARIABLE RANDOM # SEED +3627 f1a0 dd 52 STD FPA0+2 SAVE NEW LOW ORDER BYTES OF FPA0 MANTISSA +3628 f1a2 dc 88 LDD VAB GET 2 MORE LOW ORDER PRODUCT BYTES +3629 f1a4 c9 b0 ADCB #$B0 ADD A CONSTANT +3630 f1a6 89 05 ADCA #5 ADD A CONSTANT +3631 f1a8 dd b1 STD RVSEED+1 SAVE NEW HIGH ORDER VARIABLE RANDOM # SEED +3632 f1aa dd 50 STD FPA0 SAVE NEW HIGH ORDER FPA0 MANTISSA +3633 f1ac 0f 54 CLR FP0SGN FORCE FPA0 MANTISSA = POSITIVE +3634 f1ae 86 80 LDA #$80 * SET FPA0 BIASED EXPONENT +3635 f1b0 97 4f STA FP0EXP * TO 0 1 < FPA0 < 0 +3636 f1b2 96 15 LDA FPA2+2 GET A BYTE FROM FPA2 (MORE RANDOMNESS) +3637 f1b4 97 63 STA FPSBYT SAVE AS SUB BYTE +3638 f1b6 7e ec 65 JMP LBA1C NORMALIZE FPA0 +3639 * +3640 f1b9 40 e6 RSEED FDB $40E6 *CONSTANT RANDOM NUMBER GENERATOR SEED +3641 f1bb 4d ab FDB $4DAB * +3642 +3643 * SIN +3644 * THE SIN FUNCTION REQUIRES AN ARGUMENT IN RADIANS AND WILL REPEAT ITSELF EVERY +3645 * 2*PI RADIANS. THE ARGUMENT IS DIVIDED BY 2*PI AND ONLY THE FRACTIONAL PART IS +3646 * RETAINED. SINCE THE ARGUMENT WAS DIVIDED BY 2*P1, THE COEFFICIENTS MUST BE +3647 * MULTIPLIED BY THE APPROPRIATE POWER OF 2*PI. +3648 +3649 * SIN IS EVALUATED USING THE TRIGONOMETRIC IDENTITIES BELOW: +3650 * SIN(X)=SIN(PI-X) & -SIN(PI/2-X)=SIN((3*PI)/2+X) +3651 f1bd bd ee a8 SIN JSR LBC5F COPY FPA0 TO FPA1 +3652 f1c0 8e f2 02 LDX #LBFBD POINT (X) TO 2*PI +3653 f1c3 d6 61 LDB FP1SGN *GET MANTISSA SIGN OF FPA1 +3654 f1c5 bd ed d2 JSR LBB89 *AND DIVIDE FPA0 BY 2*PI +3655 f1c8 bd ee a8 JSR LBC5F COPY FPA0 TO FPA1 +3656 f1cb 8d b4 BSR LBF38 CONVERT FPA0 TO AN INTEGER +3657 f1cd 0f 62 CLR RESSGN SET RESULT SIGN = POSITIVE +3658 f1cf 96 5c LDA FP1EXP *GET EXPONENT OF FPA1 +3659 f1d1 d6 4f LDB FP0EXP *GET EXPONENT OF FPA0 +3660 f1d3 bd ec 05 JSR LB9BC *SUBTRACT FPA0 FROM FPA1 +3661 * NOW FPA0 CONTAINS ONLY THE FRACTIONAL PART OF ARGUMENT/2*PI +3662 f1d6 8e f2 07 LDX #LBFC2 POINT X TO FP (.25) +3663 f1d9 bd ec 02 JSR LB9B9 SUBTRACT FPA0 FROM .25 (PI/2) +3664 f1dc 96 54 LDA FP0SGN GET MANTISSA SIGN OF FPA0 +3665 f1de 34 02 PSHS A SAVE IT ON STACK +3666 f1e0 2a 09 BPL LBFA6 BRANCH IF MANTISSA POSITIVE +3667 f1e2 bd eb fd JSR LB9B4 ADD .5 (PI) TO FPA0 +3668 f1e5 96 54 LDA FP0SGN GET SIGN OF FPA0 +3669 f1e7 2b 05 BMI LBFA9 BRANCH IF NEGATIVE +3670 f1e9 03 0a COM RELFLG COM IF +(3*PI)/2 >= ARGUMENT >+ PI/2 (QUADRANT FLAG) +3671 f1eb bd f1 32 LBFA6 JSR LBEE9 TOGGLE MANTISSA SIGN OF FPA0 +3672 f1ee 8e f2 07 LBFA9 LDX #LBFC2 POINT X TO FP (.25) +3673 f1f1 bd ec 0b JSR LB9C2 ADD .25 (PI/2) TO FPA0 +3674 f1f4 35 02 PULS A GET OLD MANTISSA SIGN +3675 f1f6 4d TSTA * BRANCH IF OLD +3676 f1f7 2a 03 BPL LBFB7 * SIGN WAS POSITIVE +3677 f1f9 bd f1 32 JSR LBEE9 TOGGLE MANTISSA SIGN +3678 f1fc 8e f2 0c LBFB7 LDX #LBFC7 POINT X TO TABLE OF COEFFICIENTS +3679 f1ff 7e f1 39 JMP LBEF0 GO CALCULATE POLYNOMIAL VALUE +3680 +3681 f202 83 49 0f da a2 LBFBD FCB $83,$49,$0F,$DA,$A2 6.28318531 (2*PI) +3682 f207 7f 00 00 00 00 LBFC2 FCB $7F,$00,$00,$00,$00 .25 +3683 +3684 +3685 f20c 05 LBFC7 FCB 6-1 SIX COEFFICIENTS +3686 f20d 84 e6 1a 2d 1b LBFC8 FCB $84,$E6,$1A,$2D,$1B * -((2*PI)**11)/11! +3687 f212 86 28 07 fb f8 LBFCD FCB $86,$28,$07,$FB,$F8 * ((2*PI)**9)/9! +3688 f217 87 99 68 89 01 LBFD2 FCB $87,$99,$68,$89,$01 * -((2*PI)**7)/7! +3689 f21c 87 23 35 df e1 LBFD7 FCB $87,$23,$35,$DF,$E1 * ((2*PI)**5)/5! +3690 f221 86 a5 5d e7 28 LBFDC FCB $86,$A5,$5D,$E7,$28 * -((2*PI)**3)/3! +3691 f226 83 49 0f da a2 LBFE1 FCB $83,$49,$0F,$DA,$A2 * +3692 +3693 f22b a1 54 46 8f 13 FCB $A1,$54,$46,$8F,$13 UNUSED GARBAGE BYTES +3694 f230 8f 52 43 89 cd FCB $8F,$52,$43,$89,$CD UNUSED GARBAGE BYTES +3695 * EXTENDED BASIC +3696 +3697 * COS +3698 * THE VALUE OF COS(X) IS DETERMINED BY THE TRIG IDENTITY COS(X)=SIN((PI/2)+X) +3699 f235 8e f2 68 COS LDX #L83AB POINT X TO FP CONSTANT (P1/2) +3700 f238 bd ec 0b JSR LB9C2 ADD FPA0 TO (X) +3701 f23b 7e f1 bd L837E JMP SIN JUMP TO SIN ROUTINE +3702 +3703 * TAN +3704 * THE VALUE OF TAN(X) IS DETERMINED BY THE TRIG IDENTITY TAN(X)=SIN(X)/COS(X) +3705 f23e bd ee 78 TAN JSR LBC2F PACK FPA0 AND MOVE IT TO FPA3 +3706 f241 0f 0a CLR RELFLG RESET QUADRANT FLAG +3707 f243 8d f6 BSR L837E CALCULATE SIN OF ARGUMENT +3708 f245 8e 00 4a LDX #V4A POINT X TO FPA5 +3709 f248 bd ee 7e JSR LBC35 PACK FPA0 AND MOVE IT TO FPA5 +3710 f24b 8e 00 40 LDX #V40 POINT X TO FPA3 +3711 f24e bd ee 5d JSR LBC14 MOVE FPA3 TO FPA0 +3712 f251 0f 54 CLR FP0SGN FORCE FPA0 MANTISSA TO BE POSITIVE +3713 f253 96 0a LDA RELFLG GET THE QUADRANT FLAG - COS NEGATIVE IN QUADS 2,3 +3714 f255 8d 0c BSR L83A6 CALCULATE VALUE OF COS(FPA0) +3715 f257 0d 4f TST FP0EXP CHECK EXPONENT OF FPA0 +3716 f259 10 27 fa 7e LBEQ LBA92 ‘OV’ ERROR IF COS(X)=0 +3717 f25d 8e 00 4a LDX #V4A POINT X TO FPA5 +3718 f260 7e ed d8 L83A3 JMP LBB8F DIVIDE (X) BY FPA0 - SIN(X)/COS(X) +3719 f263 34 02 L83A6 PSHS A SAVE SIGN FLAG ON STACK +3720 f265 7e f1 eb JMP LBFA6 EXPAND POLYNOMIAL +3721 +3722 f268 81 49 0f da a2 L83AB FCB $81,$49,$0F,$DA,$A2 1.57079633 (PI/2) +3723 +3724 * ATN +3725 * A 12 TERM TAYLOR SERIES IS USED TO EVALUATE THE +3726 * ARCTAN EXPRESSION. TWO DIFFERENT FORMULI ARE USED +3727 * TO EVALUATE THE EXPRESSION DEPENDING UPON +3728 * WHETHER OR NOT THE ARGUMENT SQUARED IS > OR < 1.0 +3729 +3730 * IF X**2<1 THEN ATN=X-(X**3)/3+(X**5)/5-(X**7)/7. . . +3731 * IF X**2>=1 THEN ATN=PI/2-(1/X-1/((X**3)*3)+(1/((X**5)*5)-. . .) +3732 +3733 f26d 96 54 ATN LDA FP0SGN * GET THE SIGN OF THE MANTISSA AND +3734 f26f 34 02 PSHS A * SAVE IT ON THE STACK +3735 f271 2a 02 BPL L83B8 BRANCH IF POSITIVE MANTISSA +3736 f273 8d 24 BSR L83DC CHANGE SIGN OF FPA0 +3737 f275 96 4f L83B8 LDA FP0EXP * GET EXPONENT OF FPA0 AND +3738 f277 34 02 PSHS A * SAVE IT ON THE STACK +3739 f279 81 81 CMPA #$81 IS FPAO < 1.0? +3740 f27b 25 05 BLO L83C5 YES +3741 f27d 8e ed 0e LDX #LBAC5 POINT X TO FP CONSTANT 1.0 +3742 f280 8d de BSR L83A3 GET RECIPROCAL OF FPA0 +3743 f282 8e f2 9d L83C5 LDX #L83E0 POINT (X) TO TAYLOR SERIES COEFFICIENTS +3744 f285 bd f1 39 JSR LBEF0 EXPAND POLYNOMIAL +3745 f288 35 02 PULS A GET EXPONENT OF ARGUMENT +3746 f28a 81 81 CMPA #$81 WAS ARGUMENT < 1.0? +3747 f28c 25 06 BLO L83D7 YES +3748 f28e 8e f2 68 LDX #L83AB POINT (X) TO FP NUMBER (PI/2) +3749 f291 bd ec 02 JSR LB9B9 SUBTRACT FPA0 FROM (PI/2) +3750 f294 35 02 L83D7 PULS A * GET SIGN OF INITIAL ARGUMENT MANTISSA +3751 f296 4d TSTA * AND SET FLAGS ACCORDING TO IT +3752 f297 2a 03 BPL L83DF RETURN IF ARGUMENT WAS POSITIVE +3753 f299 7e f1 32 L83DC JMP LBEE9 CHANGE MANTISSA SIGN OF FPA0 +3754 f29c 39 L83DF RTS +3755 * +3756 * TCHEBYSHEV MODIFIED TAYLOR SERIES COEFFICIENTS FOR ARCTANGENT +3757 f29d 0b L83E0 FCB $0B TWELVE COEFFICIENTS +3758 f29e 76 b3 83 bd d3 L83E1 FCB $76,$B3,$83,$BD,$D3 -6.84793912E-04 1/23 +3759 f2a3 79 1e f4 a6 f5 L83E6 FCB $79,$1E,$F4,$A6,$F5 +4.85094216E-03 1/21 +3760 f2a8 7b 83 fc b0 10 L83EB FCB $7B,$83,$FC,$B0,$10 -0.0161117018 +3761 f2ad 7c 0c 1f 67 ca L83F0 FCB $7C,$0C,$1F,$67,$CA 0.0342096381 +3762 f2b2 7c de 53 cb c1 L83F5 FCB $7C,$DE,$53,$CB,$C1 -0.0542791328 +3763 f2b7 7d 14 64 70 4c L83FA FCB $7D,$14,$64,$70,$4C 0.0724571965 +3764 f2bc 7d b7 ea 51 7a L83FF FCB $7D,$B7,$EA,$51,$7A -0.0898023954 +3765 f2c1 7d 63 30 88 7e L8404 FCB $7D,$63,$30,$88,$7E 0.110932413 +3766 f2c6 7e 92 44 99 3a L8409 FCB $7E,$92,$44,$99,$3A -0.142839808 +3767 f2cb 7e 4c cc 91 c7 L840E FCB $7E,$4C,$CC,$91,$C7 0.199999121 +3768 f2d0 7f aa aa aa 13 L8413 FCB $7F,$AA,$AA,$AA,$13 -0.333333316 +3769 f2d5 81 00 00 00 00 L8418 FCB $81,$00,$00,$00,$00 1 +3770 * +3771 *** TCHEBYSHEV MODIFIED TAYLOR SERIES COEFFICIENTS FOR LN(X) +3772 * +3773 f2da 03 L841D FCB 3 FOUR COEFFICIENTS +3774 f2db 7f 5e 56 cb 79 L841E FCB $7F,$5E,$56,$CB,$79 0.434255942 +3775 f2e0 80 13 9b 0b 64 L8423 FCB $80,$13,$9B,$0B,$64 0.576584541 +3776 f2e5 80 76 38 93 16 L8428 FCB $80,$76,$38,$93,$16 0.961800759 +3777 f2ea 82 38 aa 3b 20 L842D FCB $82,$38,$AA,$3B,$20 2.88539007 +3778 +3779 f2ef 80 35 04 f3 34 L8432 FCB $80,$35,$04,$F3,$34 1/SQR(2) +3780 +3781 f2f4 81 35 04 f3 34 L8437 FCB $81,$35,$04,$F3,$34 SQR(2) +3782 +3783 f2f9 80 80 00 00 00 L843C FCB $80,$80,$00,$00,$00 -0.5 +3784 +3785 f2fe 80 31 72 17 f8 L8441 FCB $80,$31,$72,$17,$F8 LN(2) +3786 * +3787 * LOG - NATURAL LOGARITHM (LN) +3788 +3789 * THE NATURAL OR NAPERIAN LOGARITHM IS CALCULATED USING +3790 * MATHEMATICAL IDENTITIES. FPA0 IS OF THE FORM FPA0=A*(2**B) (SCIENTIFIC +3791 * NOTATION). THEREFORE, THE LOG ROUTINE DETERMINES THE VALUE OF +3792 * LN(A*(2**B)). A SERIES OF MATHEMATICAL IDENTITIES WILL EXPAND THIS +3793 * TERM: LN(A*(2**B))=(-1/2+(1/LN(2))*(LN(A*SQR(2)))+B)*LN(2). ALL OF +3794 * THE TERMS OF THE LATTER EXPRESSION ARE CONSTANTS EXCEPT FOR THE +3795 * LN(A*SQR(2)) TERM WHICH IS EVALUATED USING THE TAYLOR SERIES EXPANSION +3796 f303 bd ee b6 LOG JSR LBC6D CHECK STATUS OF FPA0 +3797 f306 10 2f f3 c4 LBLE LB44A ‘FC’ ERROR IF NEGATIVE OR ZERO +3798 f30a 8e f2 ef LDX #L8432 POINT (X) TO FP NUMBER (1/SQR(2)) +3799 f30d 96 4f LDA FP0EXP *GET EXPONENT OF ARGUMENT +3800 f30f 80 80 SUBA #$80 *SUBTRACT OFF THE BIAS AND +3801 f311 34 02 PSHS A *SAVE IT ON THE STACK +3802 f313 86 80 LDA #$80 +3803 f315 97 4f STA FP0EXP +3804 f317 bd ec 0b JSR LB9C2 ADD FPA0 TO (X) +3805 f31a 8e f2 f4 LDX #L8437 POINT X TO SQR(2) +3806 f31d bd ed d8 JSR LBB8F DIVIDE SQR(2) BY FPA0 +3807 f320 8e ed 0e LDX #LBAC5 POINT X TO FP VALUE OF 1.00 +3808 f323 bd ec 02 JSR LB9B9 SUBTRACT FPA0 FROM (X) +3809 * NOW FPA0 = (1-SQR(2)*X)/(1+SQR(2)*X) WHERE X IS ARGUMENT +3810 f326 8e f2 da LDX #L841D POINT X TO TABLE OF COEFFICIENTS +3811 f329 bd f1 39 JSR LBEF0 EXPAND POLYNOMIAL +3812 f32c 8e f2 f9 LDX #L843C POINT X TO FP VALUE OF (-.5) +3813 f32f bd ec 0b JSR LB9C2 ADD FPA0 TO X +3814 f332 35 04 PULS B GET EXPONENT OF ARGUMENT BACK (WITHOUT BIAS) +3815 f334 bd ef e2 JSR LBD99 ADD ACCB TO FPA0 +3816 f337 8e f2 fe LDX #L8441 POINT X TO LN(2) +3817 f33a 7e ed 13 JMP LBACA MULTIPLY FPA0 * LN(2) +3818 +3819 * SQR +3820 f33d bd ee a8 SQR JSR LBC5F MOVE FPA0 TO FPA1 +3821 f340 8e f1 09 LDX #LBEC0 POINT (X) TO FP NUMBER (.5) +3822 f343 bd ee 5d JSR LBC14 COPY A PACKED NUMBER FROM (X) TO FPA0 +3823 +3824 * ARITHMETIC OPERATOR FOR EXPONENTIATION JUMPS +3825 * HERE. THE FORMULA USED TO EVALUATE EXPONENTIATION +3826 * IS A**X=E**(X LN A) = E**(FPA0*LN(FPA1)), E=2.7182818 +3827 f346 27 67 L8489 BEQ EXP DO A NATURAL EXPONENTIATION IF EXPONENT = 0 +3828 f348 4d TSTA *CHECK VALUE BEING EXPONENTIATED +3829 f349 26 03 BNE L8491 *AND BRANCH IF IT IS <> 0 +3830 f34b 7e ec 83 JMP LBA3A FPA0=0 IF RAISING ZERO TO A POWER +3831 f34e 8e 00 4a L8491 LDX #V4A * PACK FPA0 AND SAVE +3832 f351 bd ee 7e JSR LBC35 * IT IN FPA5 (ARGUMENT’S EXPONENT) +3833 f354 5f CLRB ACCB=DEFAULT RESULT SIGN FLAG; 0=POSITIVE +3834 f355 96 61 LDA FP1SGN *CHECK THE SIGN OF ARGUMENT +3835 f357 2a 10 BPL L84AC *BRANCH IF POSITIVE +3836 f359 bd ef 37 JSR INT CONVERT EXPONENT INTO AN INTEGER +3837 f35c 8e 00 4a LDX #V4A POINT X TO FPA5 (ORIGINAL EXPONENT) +3838 f35f 96 61 LDA FP1SGN GET MANTISSA SIGN OF FPA1 (ARGUMENT) +3839 f361 bd ee e9 JSR LBCA0 *COMPARE FPA0 TO (X) AND +3840 f364 26 03 BNE L84AC *BRANCH IF NOT EQUAL +3841 f366 43 COMA TOGGLE FPA1 MANTISSA SIGN - FORCE POSITIVE +3842 f367 d6 01 LDB CHARAC GET LS BYTE OF INTEGER VALUE OF EXPONENT (RESULT SIGN FLAG) +3843 f369 bd ee 95 L84AC JSR LBC4C COPY FPA1 TO FPA0; ACCA = MANTISSA SIGN +3844 f36c 34 04 PSHS B PUT RESULT SIGN FLAG ON THE STACK +3845 f36e bd f3 03 JSR LOG +3846 f371 8e 00 4a LDX #V4A POINT (X) TO FPA5 +3847 f374 bd ed 13 JSR LBACA MULTIPLY FPA0 BY FPA5 +3848 f377 8d 36 BSR EXP CALCULATE E**(FPA0) +3849 f379 35 02 PULS A * GET RESULT SIGN FLAG FROM THE STACK +3850 f37b 46 RORA * AND BRANCH IF NEGATIVE +3851 f37c 10 25 fd b2 LBCS LBEE9 CHANGE SIGN OF FPA0 MANTISSA +3852 f380 39 RTS +3853 +3854 * CORRECTION FACTOR FOR EXPONENTIAL FUNCTION +3855 f381 81 38 aa 3b 29 L84C4 FCB $81,$38,$AA,$3B,$29 1.44269504 ( CF ) +3856 * +3857 * TCHEBYSHEV MODIFIED TAYLOR SERIES COEFFICIENTS FOR E**X +3858 * +3859 f386 07 L84C9 FCB 7 EIGHT COEFFICIENTS +3860 f387 71 34 58 3e 56 L84CA FCB $71,$34,$58,$3E,$56 2.14987637E-05: 1/(7!*(CF**7)) +3861 f38c 74 16 7e b3 1b L84CF FCB $74,$16,$7E,$B3,$1B 1.4352314E-04 : 1/(6!*(CF**6)) +3862 f391 77 2f ee e3 85 L84D4 FCB $77,$2F,$EE,$E3,$85 1.34226348E-03: 1/(5!*(CF**5)) +3863 f396 7a 1d 84 1c 2a L84D9 FCB $7A,$1D,$84,$1C,$2A 9.61401701E-03: 1/(4!*(CF**4)) +3864 f39b 7c 63 59 58 0a L84DE FCB $7C,$63,$59,$58,$0A 0.0555051269 +3865 f3a0 7e 75 fd e7 c6 L84E3 FCB $7E,$75,$FD,$E7,$C6 0.240226385 +3866 f3a5 80 31 72 18 10 L84E8 FCB $80,$31,$72,$18,$10 0.693147186 +3867 f3aa 81 00 00 00 00 L84ED FCB $81,$00,$00,$00,$00 1 +3868 * +3869 * EXP ( E**X) +3870 * THE EXPONENTIAL FUNCTION IS EVALUATED BY FIRST MULTIPLYING THE +3871 * ARGUMENT BY A CORRECTION FACTOR (CF). AFTER THIS IS DONE, AN +3872 * ARGUMENT >= 127 WILL YIELD A ZERO RESULT (NO UNDERFLOW) FOR A +3873 * NEGATIVE ARGUMENT OR AN 'OV' (OVERFLOW) ERROR FOR A POSITIVE +3874 * ARGUMENT. THE POLYNOMIAL COEFFICIENTS ARE MODIFIED TO REFLECT +3875 * THE CF MULTIPLICATION AT THE START OF THE EVALUATION PROCESS. +3876 +3877 f3af 8e f3 81 EXP LDX #L84C4 POINT X TO THE CORRECTION FACTOR +3878 f3b2 bd ed 13 JSR LBACA MULTIPLY FPA0 BY (X) +3879 f3b5 bd ee 78 JSR LBC2F PACK FPA0 AND STORE IT IN FPA3 +3880 f3b8 96 4f LDA FP0EXP *GET EXPONENT OF FPA0 AND +3881 f3ba 81 88 CMPA #$88 *COMPARE TO THE MAXIMUM VALUE +3882 f3bc 25 03 BLO L8504 BRANCH IF FPA0 < 128 +3883 f3be 7e ed a5 L8501 JMP LBB5C SET FPA0 = 0 OR ‘OV’ ERROR +3884 f3c1 bd ef 37 L8504 JSR INT CONVERT FPA0 TO INTEGER +3885 f3c4 96 01 LDA CHARAC GET LS BYTE OF INTEGER +3886 f3c6 8b 81 ADDA #$81 * WAS THE ARGUMENT =127, IF SO +3887 f3c8 27 f4 BEQ L8501 * THEN ‘OV’ ERROR; THIS WILL ALSO ADD THE $80 BIAS +3888 * * REQUIRED WHEN THE NEW EXPONENT IS CALCULATED BELOW +3889 f3ca 4a DECA DECREMENT ONE FROM THE EXPONENT, BECAUSE $81, NOT $80 WAS USED ABOVE +3890 f3cb 34 02 PSHS A SAVE EXPONENT OF INTEGER PORTION ON STACK +3891 f3cd 8e 00 40 LDX #V40 POINT (X) TO FPA3 +3892 f3d0 bd ec 02 JSR LB9B9 SUBTRACT FPA0 FROM (X) - GET FRACTIONAL PART OF ARGUMENT +3893 f3d3 8e f3 86 LDX #L84C9 POINT X TO COEFFICIENTS +3894 f3d6 bd f1 48 JSR LBEFF EVALUATE POLYNOMIAL FOR FRACTIONAL PART +3895 f3d9 0f 62 CLR RESSGN FORCE THE MANTISSA TO BE POSITIVE +3896 f3db 35 02 PULS A GET INTEGER EXPONENT FROM STACK +3897 f3dd bd ed 91 JSR LBB48 * CALCULATE EXPONENT OF NEW FPA0 BY ADDING THE EXPONENTS OF THE +3898 * * INTEGER AND FRACTIONAL PARTS +3899 f3e0 39 RTS +3900 +3901 * FIX +3902 f3e1 bd ee b6 FIX JSR LBC6D CHECK STATUS OF FPA0 +3903 f3e4 2b 03 BMI L852C BRANCH IF FPA0 = NEGATIVE +3904 f3e6 7e ef 37 L8529 JMP INT CONVERT FPA0 TO INTEGER +3905 f3e9 03 54 L852C COM FP0SGN TOGGLE SIGN OF FPA0 MANTISSA +3906 f3eb 8d f9 BSR L8529 CONVERT FPA0 TO INTEGER +3907 f3ed 7e f1 32 JMP LBEE9 TOGGLE SIGN OF FPA0 +3908 +3909 * EDIT +3910 f3f0 bd f8 1e EDIT JSR L89AE GET LINE NUMBER FROM BASIC +3911 f3f3 32 62 LEAS $02,S PURGE RETURN ADDRESS OFF OF THE STACK +3912 f3f5 86 01 L8538 LDA #$01 ‘LIST’ FLAG +3913 f3f7 97 98 STA VD8 SET FLAG TO LIST LINE +3914 f3f9 bd df a2 JSR LAD01 GO FIND THE LINE NUMBER IN PROGRAM +3915 f3fc 10 25 ed 7f LBCS LAED2 ERROR #7 ‘UNDEFINED LINE #' +3916 f400 bd ea 3b JSR LB7C2 GO UNCRUNCH LINE INTO BUFFER AT LINBUF+1 +3917 f403 1f 20 TFR Y,D PUT ABSOLUTE ADDRESS OF END OF LINE TO ACCD +3918 f405 83 00 f5 SUBD #LINBUF+2 SUBTRACT OUT THE START OF LINE +3919 f408 d7 97 STB VD7 SAVE LENGTH OF LINE +3920 f40a dc 2b L854D LDD BINVAL GET THE HEX VALUE OF LINE NUMBER +3921 f40c bd f0 15 JSR LBDCC LIST THE LINE NUMBER ON THE SCREEN +3922 f40f bd eb f5 JSR LB9AC PRINT A SPACE +3923 f412 8e 00 f4 LDX #LINBUF+1 POINT X TO BUFFER +3924 f415 d6 98 LDB VD8 * CHECK TO SEE IF LINE IS TO BE +3925 f417 26 25 BNE L8581 * LISTED TO SCREEN - BRANCH IF IT IS +3926 f419 5f L855C CLRB RESET DIGIT ACCUMULATOR - DEFAULT VALUE +3927 f41a bd f5 44 L855D JSR L8687 GET KEY STROKE +3928 f41d bd fc e9 JSR L90AA SET CARRY IF NOT NUMERIC +3929 f420 25 0b BLO L8570 BRANCH IF NOT NUMERIC +3930 f422 80 30 SUBA #'0' MASK OFF ASCII +3931 f424 34 02 PSHS A SAVE IT ON STACK +3932 f426 86 0a LDA #10 NUMBER BEING CONVERTED IS BASE 10 +3933 f428 3d MUL MULTIPLY ACCUMULATED VALUE BY BASE (10) +3934 f429 eb e0 ADDB ,S+ ADD DIGIT TO ACCUMULATED VALUE +3935 f42b 20 ed BRA L855D CHECK FOR ANOTHER DIGIT +3936 f42d c0 01 L8570 SUBB #$01 * REPEAT PARAMETER IN ACCB; IF IT +3937 f42f c9 01 ADCB #$01 *IS 0, THEN MAKE IT ‘1’ +3938 f431 81 41 CMPA #'A' ABORT? +3939 f433 26 05 BNE L857D NO +3940 f435 bd eb a5 JSR LB958 PRINT CARRIAGE RETURN TO SCREEN +3941 f438 20 bb BRA L8538 RESTART EDIT PROCESS - CANCEL ALL CHANGES +3942 f43a 81 4c L857D CMPA #'L' LIST? +3943 f43c 26 0b BNE L858C NO +3944 f43e 8d 31 L8581 BSR L85B4 LIST THE LINE +3945 f440 0f 98 CLR VD8 RESET THE LIST FLAG TO ‘NO LIST’ +3946 f442 bd eb a5 JSR LB958 PRINT CARRIAGE RETURN +3947 f445 20 c3 BRA L854D GO INTERPRET ANOTHER EDIT COMMAND +3948 f447 32 62 L858A LEAS $02,S PURGE RETURN ADDRESS OFF OF THE STACK +3949 f449 81 0d L858C CMPA #CR ENTER KEY? +3950 f44b 26 0d BNE L859D NO +3951 f44d 8d 22 BSR L85B4 ECHO THE LINE TO THE SCREEN +3952 f44f bd eb a5 L8592 JSR LB958 PRINT CARRIAGE RETURN +3953 f452 8e 00 f4 LDX #LINBUF+1 * RESET BASIC’S INPUT POINTER +3954 f455 9f 83 STX CHARAD * TO THE LINE INPUT BUFFER +3955 f457 7e df 4b JMP LACA8 GO PUT LINE BACK IN PROGRAM +3956 f45a 81 45 L859D CMPA #'E' EXIT? +3957 f45c 27 f1 BEQ L8592 YES - SAME AS ENTER EXCEPT NO ECHO +3958 f45e 81 51 CMPA #'Q' QUIT? +3959 f460 26 06 BNE L85AB NO +3960 f462 bd eb a5 JSR LB958 PRINT CARRIAGE RETURN TO SCREEN +3961 f465 7e df 22 JMP LAC73 GO TO COMMAND LEVEL - MAKE NO CHANGES +3962 f468 8d 02 L85AB BSR L85AF INTERPRET THE REMAINING COMMANDS AS SUBROUTINES +3963 f46a 20 ad BRA L855C GO INTERPRET ANOTHER EDIT COMMAND +3964 f46c 81 20 L85AF CMPA #SPACE SPACE BAR? +3965 f46e 26 10 BNE L85C3 NO +3966 f470 8c L85B3 FCB SKP2 SKIP TWO BYTES +3967 * DISPLAY THE NEXT ACCB BYTES OF THE LINE IN THE BUFFER TO THE SCREEN +3968 * +3969 f471 c6 f9 L85B4 LDB #LBUFMX-1 250 BYTES MAX IN BUFFER +3970 f473 a6 84 L85B6 LDA ,X GET A CHARACTER FROM BUFFER +3971 f475 27 08 BEQ L85C2 EXIT IF IT’S A 0 +3972 f477 bd db 14 JSR PUTCHR SEND CHAR TO CONSOLE OUT +3973 f47a 30 01 LEAX $01,X MOVE POINTER UP ONE +3974 f47c 5a DECB DECREMENT CHARACTER COUNTER +3975 f47d 26 f4 BNE L85B6 LOOP IF NOT DONE +3976 f47f 39 L85C2 RTS +3977 f480 81 44 L85C3 CMPA #'D' DELETE? +3978 f482 26 48 BNE L860F NO +3979 f484 6d 84 L85C7 TST ,X * CHECK FOR END OF LINE +3980 f486 27 f7 BEQ L85C2 * AND BRANCH IF SO +3981 f488 8d 04 BSR L85D1 REMOVE A CHARACTER +3982 f48a 5a DECB DECREMENT REPEAT PARAMETER +3983 f48b 26 f7 BNE L85C7 BRANCH IF NOT DONE +3984 f48d 39 RTS +3985 * REMOVE ONE CHARACTER FROM BUFFER +3986 f48e 0a 97 L85D1 DEC VD7 DECREMENT LENGTH OF BUFFER +3987 f490 31 1f LEAY $-01,X POINT Y TO ONE BEFORE CURRENT BUFFER POINTER +3988 f492 31 21 L85D5 LEAY $01,Y INCREMENT TEMPORARY BUFFER POINTER +3989 f494 a6 21 LDA $01,Y GET NEXT CHARACTER +3990 f496 a7 a4 STA ,Y PUT IT IN CURRENT POSITION +3991 f498 26 f8 BNE L85D5 BRANCH IF NOT END OF LINE +3992 f49a 39 RTS +3993 f49b 81 49 L85DE CMPA #'I' INSERT? +3994 f49d 27 13 BEQ L85F5 YES +3995 f49f 81 58 CMPA #'X' EXTEND? +3996 f4a1 27 0d BEQ L85F3 YES +3997 f4a3 81 48 CMPA #'H' HACK? +3998 f4a5 26 5c BNE L8646 NO +3999 f4a7 6f 84 CLR ,X TURN CURRENT BUFFER POINTER INTO END OF LINE FLAG +4000 f4a9 1f 10 TFR X,D PUT CURRENT BUFFER POINTER IN ACCD +4001 f4ab 83 00 f5 SUBD #LINBUF+2 SUBTRACT INITIAL POINTER POSITION +4002 f4ae d7 97 STB VD7 SAVE NEW BUFFER LENGTH +4003 f4b0 8d bf L85F3 BSR L85B4 DISPLAY THE LINE ON THE SCREEN +4004 f4b2 bd f5 44 L85F5 JSR L8687 GET A KEYSTROKE +4005 f4b5 81 0d CMPA #CR ENTER KEY? +4006 f4b7 27 8e BEQ L858A YES - INTERPRET ANOTHER COMMAND - PRINT LINE +4007 f4b9 81 1b CMPA #ESC ESCAPE? +4008 f4bb 27 25 BEQ L8625 YES - RETURN TO COMMAND LEVEL - DON’T PRINT LINE +4009 f4bd 81 08 CMPA #BS BACK SPACE? +4010 f4bf 26 22 BNE L8626 NO +4011 f4c1 8c 00 f4 CMPX #LINBUF+1 COMPARE POINTER TO START OF BUFFER +4012 f4c4 27 ec BEQ L85F5 DO NOT ALLOW BS IF AT START +4013 f4c6 8d 45 BSR L8650 MOVE POINTER BACK ONE, BS TO SCREEN +4014 f4c8 8d c4 BSR L85D1 REMOVE ONE CHARACTER FROM BUFFER +4015 f4ca 20 e6 BRA L85F5 GET INSERT SUB COMMAND +4016 f4cc 81 43 L860F CMPA #'C' CHANGE? +4017 f4ce 26 cb BNE L85DE NO +4018 f4d0 6d 84 L8613 TST ,X CHECK CURRENT BUFFER CHARACTER +4019 f4d2 27 0e BEQ L8625 BRANCH IF END OF LINE +4020 f4d4 bd f5 44 JSR L8687 GET A KEYSTROKE +4021 f4d7 25 02 BLO L861E BRANCH IF LEGITIMATE KEY +4022 f4d9 20 f5 BRA L8613 TRY AGAIN IF ILLEGAL KEY +4023 f4db a7 80 L861E STA ,X+ INSERT NEW CHARACTER INTO BUFFER +4024 f4dd 8d 37 BSR L8659 SEND NEW CHARACTER TO SCREEN +4025 f4df 5a DECB DECREMENT REPEAT PARAMETER +4026 f4e0 26 ee BNE L8613 BRANCH IF NOT DONE +4027 f4e2 39 L8625 RTS +4028 f4e3 d6 97 L8626 LDB VD7 GET LENGTH OF LINE +4029 f4e5 c1 f9 CMPB #LBUFMX-1 COMPARE TO MAXIMUM LENGTH +4030 f4e7 26 02 BNE L862E BRANCH IF NOT AT MAXIMUM +4031 f4e9 20 c7 BRA L85F5 IGNORE INPUT IF LINE AT MAXIMUM LENGTH +4032 f4eb 34 10 L862E PSHS X SAVE CURRENT BUFFER POINTER +4033 f4ed 6d 80 L8630 TST ,X+ * SCAN THE LINE UNTIL END OF +4034 f4ef 26 fc BNE L8630 * LINE (0) IS FOUND +4035 f4f1 e6 82 L8634 LDB ,-X DECR TEMP LINE POINTER AND GET A CHARACTER +4036 f4f3 e7 01 STB $01,X PUT CHARACTER BACK DOWN ONE SPOT +4037 f4f5 ac e4 CMPX ,S HAVE WE REACHED STARTING POINT? +4038 f4f7 26 f8 BNE L8634 NO - KEEP GOING +4039 f4f9 32 62 LEAS $02,S PURGE BUFFER POINTER FROM STACK +4040 f4fb a7 80 STA ,X+ INSERT NEW CHARACTER INTO THE LINE +4041 f4fd 8d 17 BSR L8659 SEND A CHARACTER TO CONSOLE OUT +4042 f4ff 0c 97 INC VD7 ADD ONE TO BUFFER LENGTH +4043 f501 20 af BRA L85F5 GET INSERT SUB COMMAND +4044 f503 81 08 L8646 CMPA #BS BACKSPACE? +4045 f505 26 12 BNE L865C NO +4046 f507 8d 04 L864A BSR L8650 MOVE POINTER BACK 1, SEND BS TO SCREEN +4047 f509 5a DECB DECREMENT REPEAT PARAMETER +4048 f50a 26 fb BNE L864A LOOP UNTIL DONE +4049 f50c 39 RTS +4050 f50d 8c 00 f4 L8650 CMPX #LINBUF+1 COMPARE POINTER TO START OF BUFFER +4051 f510 27 d0 BEQ L8625 DO NOT ALLOW BS IF AT START +4052 f512 30 1f LEAX $-01,X MOVE POINTER BACK ONE +4053 f514 86 08 LDA #BS BACK SPACE +4054 f516 7e db 14 L8659 JMP PUTCHR SEND TO CONSOLE OUT +4055 f519 81 4b L865C CMPA #'K' KILL? +4056 f51b 27 05 BEQ L8665 YES +4057 f51d 80 53 SUBA #'S' SEARCH? +4058 f51f 27 01 BEQ L8665 YES +4059 f521 39 RTS +4060 f522 34 02 L8665 PSHS A SAVE KILL/SEARCH FLAG ON STACK +4061 f524 8d 1e BSR L8687 * GET A KEYSTROKE (TARGET CHARACTER) +4062 f526 34 02 PSHS A * AND SAVE IT ON STACK +4063 f528 a6 84 L866B LDA ,X GET CURRENT BUFFER CHARACTER +4064 f52a 27 16 BEQ L8685 AND RETURN IF END OF LINE +4065 f52c 6d 61 TST $01,S CHECK KILL/SEARCH FLAG +4066 f52e 26 06 BNE L8679 BRANCH IF KILL +4067 f530 8d e4 BSR L8659 SEND A CHARACTER TO CONSOLE OUT +4068 f532 30 01 LEAX $01,X INCREMENT BUFFER POINTER +4069 f534 20 03 BRA L867C CHECK NEXT INPUT CHARACTER +4070 f536 bd f4 8e L8679 JSR L85D1 REMOVE ONE CHARACTER FROM BUFFER +4071 f539 a6 84 L867C LDA ,X GET CURRENT INPUT CHARACTER +4072 f53b a1 e4 CMPA ,S COMPARE TO TARGET CHARACTER +4073 f53d 26 e9 BNE L866B BRANCH IF NO MATCH +4074 f53f 5a DECB DECREMENT REPEAT PARAMETER +4075 f540 26 e6 BNE L866B BRANCH IF NOT DONE +4076 f542 35 a0 L8685 PULS Y,PC THE Y PULL WILL CLEAN UP THE STACK FOR THE 2 PSHS A +4077 * +4078 * GET A KEYSTRKE +4079 f544 bd db 00 L8687 JSR LA171 CALL CONSOLE IN : DEV NBR=SCREEN +4080 f547 81 7f CMPA #$7F GRAPHIC CHARACTER? +4081 f549 24 f9 BCC L8687 YES - GET ANOTHER CHAR +4082 f54b 81 5f CMPA #$5F SHIFT UP ARROW (QUIT INSERT) +4083 f54d 26 02 BNE L8694 NO +4084 f54f 86 1b LDA #ESC REPLACE W/ESCAPE CODE +4085 f551 81 0d L8694 CMPA #CR ENTER KEY +4086 f553 27 0e BEQ L86A6 YES +4087 f555 81 1b CMPA #ESC ESCAPE? +4088 f557 27 0a BEQ L86A6 YES +4089 f559 81 08 CMPA #BS BACKSPACE? +4090 f55b 27 06 BEQ L86A6 YES +4091 f55d 81 20 CMPA #SPACE SPACE +4092 f55f 25 e3 BLO L8687 GET ANOTHER CHAR IF CONTROL CHAR +4093 f561 1a 01 ORCC #$01 SET CARRY +4094 f563 39 L86A6 RTS +4095 +4096 * TRON +4097 f564 86 TRON FCB SKP1LD SKIP ONE BYTE AND LDA #$4F +4098 +4099 * TROFF +4100 f565 4f TROFF CLRA TROFF FLAG +4101 f566 97 8c STA TRCFLG TRON/TROFF FLAG:0=TROFF, <> 0=TRON +4102 f568 39 RTS +4103 +4104 * POS +4105 +4106 f569 86 00 POS LDA #0 GET DEVICE NUMBER +4107 f56b d6 79 LDB LPTPOS GET PRINT POSITION +4108 f56d 1d LA5E8 SEX CONVERT ACCB TO 2 DIGIT SIGNED INTEGER +4109 f56e 7e e7 78 JMP GIVABF CONVERT ACCD TO FLOATING POINT +4110 +4111 +4112 * VARPTR +4113 f571 bd e4 f3 VARPT JSR LB26A SYNTAX CHECK FOR ‘(‘ +4114 f574 dc 1f LDD ARYEND GET ADDR OF END OF ARRAYS +4115 f576 34 06 PSHS B,A SAVE IT ON STACK +4116 f578 bd e5 db JSR LB357 GET VARIABLE DESCRIPTOR +4117 f57b bd e4 f0 JSR LB267 SYNTAX CHECK FOR ‘)‘ +4118 f57e 35 06 PULS A,B GET END OF ARRAYS ADDR BACK +4119 f580 1e 10 EXG X,D SWAP END OF ARRAYS AND VARIABLE DESCRIPTOR +4120 f582 9c 1f CMPX ARYEND COMPARE TO NEW END OF ARRAYS +4121 f584 26 51 BNE L8724 ‘FC’ ERROR IF VARIABLE WAS NOT DEFINED PRIOR TO CALLING VARPTR +4122 f586 7e e7 78 JMP GIVABF CONVERT VARIABLE DESCRIPTOR INTO A FP NUMBER +4123 +4124 * MID$(OLDSTRING,POSITION,LENGTH)=REPLACEMENT +4125 f589 9d 7c L86D6 JSR GETNCH GET INPUT CHAR FROM BASIC +4126 f58b bd e4 f3 JSR LB26A SYNTAX CHECK FOR ‘(‘ +4127 f58e bd e5 db JSR LB357 * GET VARIABLE DESCRIPTOR ADDRESS AND +4128 f591 34 10 PSHS X * SAVE IT ON THE STACK +4129 f593 ec 02 LDD $02,X POINT ACCD TO START OF OLDSTRING +4130 f595 10 93 21 CMPD FRETOP COMPARE TO START OF CLEARED SPACE +4131 f598 23 04 BLS L86EB BRANCH IF <= +4132 f59a 93 27 SUBD MEMSIZ SUBTRACT OUT TOP OF CLEARED SPACE +4133 f59c 23 12 BLS L86FD BRANCH IF STRING IN STRING SPACE +4134 f59e e6 84 L86EB LDB ,X GET LENGTH OF OLDSTRING +4135 f5a0 bd e7 f1 JSR LB56D RESERVE ACCB BYTES IN STRING SPACE +4136 f5a3 34 10 PSHS X SAVE RESERVED SPACE STRING ADDRESS ON STACK +4137 f5a5 ae 62 LDX $02,S POINT X TO OLDSTRING DESCRIPTOR +4138 f5a7 bd e8 c7 JSR LB643 MOVE OLDSTRING INTO STRING SPACE +4139 f5aa 35 50 PULS X,U * GET OLDSTRING DESCRIPTOR ADDRESS AND RESERVED STRING +4140 f5ac af 42 STX $02,U * ADDRESS AND SAVE RESERVED ADDRESS AS OLDSTRING ADDRESS +4141 f5ae 34 40 PSHS U SAVE OLDSTRING DESCRIPTOR ADDRESS +4142 f5b0 bd e9 bc L86FD JSR LB738 SYNTAX CHECK FOR COMMA AND EVALUATE LENGTH EXPRESSION +4143 f5b3 34 04 PSHS B SAVE POSITION PARAMETER ON STACK +4144 f5b5 5d TSTB * CHECK POSITION PARAMETER AND BRANCH +4145 f5b6 27 1f BEQ L8724 * IF START OF STRING +4146 f5b8 c6 ff LDB #$FF DEFAULT REPLACEMENT LENGTH = $FF +4147 f5ba 81 29 CMPA #')' * CHECK FOR END OF MID$ STATEMENT AND +4148 f5bc 27 03 BEQ L870E * BRANCH IF AT END OF STATEMENT +4149 f5be bd e9 bc JSR LB738 SYNTAX CHECK FOR COMMA AND EVALUATE LENGTH EXPRESSION +4150 f5c1 34 04 L870E PSHS B SAVE LENGTH PARAMETER ON STACK +4151 f5c3 bd e4 f0 JSR LB267 SYNTAX CHECK FOR ‘)‘ +4152 f5c6 c6 ae LDB #TOK_EQUALS TOKEN FOR = +4153 f5c8 bd e4 f8 JSR LB26F SYNTAX CHECK FOR “=‘ +4154 f5cb 8d 2e BSR L8748 EVALUATE REPLACEMENT STRING +4155 f5cd 1f 13 TFR X,U SAVE REPLACEMENT STRING ADDRESS IN U +4156 f5cf ae 62 LDX $02,S POINT X TO OLOSTRING DESCRIPTOR ADDRESS +4157 f5d1 a6 84 LDA ,X GET LENGTH OF OLDSTRING +4158 f5d3 a0 61 SUBA $01,S SUBTRACT POSITION PARAMETER +4159 f5d5 24 03 BCC L8727 INSERT REPLACEMENT STRING INTO OLDSTRING +4160 f5d7 7e e6 ce L8724 JMP LB44A ‘FC’ ERROR IF POSITION > LENGTH OF OLDSTRING +4161 f5da 4c L8727 INCA * NOW ACCA = NUMBER OF CHARACTERS TO THE RIGHT +4162 * * (INCLUSIVE) OF THE POSITION PARAMETER +4163 f5db a1 e4 CMPA ,S +4164 f5dd 24 02 BCC L872E BRANCH IF NEW STRING WILL FIT IN OLDSTRING +4165 f5df a7 e4 STA ,S IF NOT, USE AS MUCH OF LENGTH PARAMETER AS WILL FIT +4166 f5e1 a6 61 L872E LDA $01,S GET POSITION PARAMETER +4167 f5e3 1e 89 EXG A,B ACCA=LENGTH OF REPL STRING, ACCB=POSITION PARAMETER +4168 f5e5 ae 02 LDX $02,X POINT X TO OLDSTRING ADDRESS +4169 f5e7 5a DECB * BASIC’S POSITION PARAMETER STARTS AT 1; THIS ROUTINE +4170 * * WANTS IT TO START AT ZERO +4171 f5e8 3a ABX POINT X TO POSITION IN OLDSTRING WHERE THE REPLACEMENT WILL GO +4172 f5e9 4d TSTA * IF THE LENGTH OF THE REPLACEMENT STRING IS ZERO +4173 f5ea 27 0d BEQ L8746 * THEN RETURN +4174 f5ec a1 e4 CMPA ,S +4175 f5ee 23 02 BLS L873F ADJUSTED LENGTH PARAMETER, THEN BRANCH +4176 f5f0 a6 e4 LDA ,S OTHERWISE USE AS MUCH ROOM AS IS AVAILABLE +4177 f5f2 1f 89 L873F TFR A,B SAVE NUMBER OF BYTES TO MOVE IN ACCB +4178 f5f4 1e 31 EXG U,X SWAP SOURCE AND DESTINATION POINTERS +4179 f5f6 bd dc ae JSR LA59A MOVE (B) BYTES FROM (X) TO (U) +4180 f5f9 35 96 L8746 PULS A,B,X,PC +4181 f5fb bd e3 df L8748 JSR LB156 EVALUATE EXPRESSION +4182 f5fe 7e e8 d8 JMP LB654 *‘TM’ ERROR IF NUMERIC; RETURN WITH X POINTING +4183 * *TO STRING, ACCB = LENGTH +4184 +4185 * STRING +4186 f601 bd e4 f3 STRING JSR LB26A SYNTAX CHECK FOR ‘(’ +4187 f604 bd e9 8f JSR LB70B EVALUATE EXPRESSION; ERROR IF > 255 +4188 f607 34 04 PSHS B SAVE LENGTH OF STRING +4189 f609 bd e4 f6 JSR LB26D SYNTAX CHECK FOR COMMA +4190 f60c bd e3 df JSR LB156 EVALUATE EXPRESSION +4191 f60f bd e4 f0 JSR LB267 SYNTAX CHECK FOR ‘)‘ +4192 f612 96 06 LDA VALTYP GET VARIABLE TYPE +4193 f614 26 05 BNE L8768 BRANCH IF STRING +4194 f616 bd e9 92 JSR LB70E CONVERT FPA0 INTO AN INTEGER IN ACCB +4195 f619 20 03 BRA L876B SAVE THE STRING IN STRING SPACE +4196 f61b bd e9 28 L8768 JSR LB6A4 GET FIRST BYTE OF STRING +4197 f61e 34 04 L876B PSHS B SAVE FIRST BYTE OF EXPRESSION +4198 f620 e6 61 LDB $01,S GET LENGTH OF STRING +4199 f622 bd e7 93 JSR LB50F RESERVE ACCB BYTES IN STRING SPACE +4200 f625 35 06 PULS A,B GET LENGTH OF STRING AND CHARACTER +4201 f627 27 05 BEQ L877B BRANCH IF NULL STRING +4202 f629 a7 80 L8776 STA ,X+ SAVE A CHARACTER IN STRING SPACE +4203 f62b 5a DECB DECREMENT LENGTH +4204 f62c 26 fb BNE L8776 BRANCH IF NOT DONE +4205 f62e 7e e9 1f L877B JMP LB69B PUT STRING DESCRIPTOR ONTO STRING STACK +4206 +4207 * INSTR +4208 f631 bd e4 f3 INSTR JSR LB26A SYNTAX CHECK FOR ‘(‘ +4209 f634 bd e3 df JSR LB156 EVALUATE EXPRESSION +4210 f637 c6 01 LDB #$01 DEFAULT POSITION = 1 (SEARCH START) +4211 f639 34 04 PSHS B SAVE START +4212 f63b 96 06 LDA VALTYP GET VARIABLE TYPE +4213 f63d 26 10 BNE L879C BRANCH IF STRING +4214 f63f bd e9 92 JSR LB70E CONVERT FPA0 TO INTEGER IN ACCB +4215 f642 e7 e4 STB ,S SAVE START SEARCH VALUE +4216 f644 27 91 BEQ L8724 BRANCH IF START SEARCH AT ZERO +4217 f646 bd e4 f6 JSR LB26D SYNTAX CHECK FOR COMMA +4218 f649 bd e3 df JSR LB156 EVALUATE EXPRESSION - SEARCH STRING +4219 f64c bd e3 cf JSR LB146 ‘TM’ ERROR IF NUMERIC +4220 f64f 9e 52 L879C LDX FPA0+2 SEARCH STRING DESCRIPTOR ADDRESS +4221 f651 34 10 PSHS X SAVE ON THE STACK +4222 f653 bd e4 f6 JSR LB26D SYNTAX CHECK FOR COMMA +4223 f656 bd f5 fb JSR L8748 EVALUATE TARGET STRING EXPRESSION +4224 f659 34 14 PSHS X,B SAVE ADDRESS AND LENGTH ON STACK +4225 f65b bd e4 f0 JSR LB267 SYNTAX CHECK FOR ')' +4226 f65e ae 63 LDX $03,S * LOAD X WITH SEARCH STRING DESCRIPTOR ADDRESS +4227 f660 bd e8 dd JSR LB659 * AND GET THE LENGTH ANDADDRESS OF SEARCH STRING +4228 f663 34 04 PSHS B SAVE LENGTH ON STACK +4229 * +4230 * AT THIS POINT THE STACK HAS THE FOLLOWING INFORMATION +4231 * ON IT: 0,S-SEARCH LENGTH; 1,S-TARGET LENGTH; 2 3,S-TARGET +4232 * ADDRESS; 4 5,S-SEARCH DESCRIPTOR ADDRESS; 6,S-SEARCH POSITION +4233 f665 e1 66 CMPB $06,S COMPARE LENGTH OF SEARCH STRING TO START +4234 f667 25 23 BLO L87D9 POSITION; RETURN 0 IF LENGTH < START +4235 f669 a6 61 LDA $01,S GET LENGTH OF TARGET STRING +4236 f66b 27 1c BEQ L87D6 BRANCH IF TARGET STRING = NULL +4237 f66d e6 66 LDB $06,S GET START POSITION +4238 f66f 5a DECB MOVE BACK ONE +4239 f670 3a ABX POINT X TO POSITION IN SEARCH STRING WHERE SEARCHING WILL START +4240 f671 31 84 L87BE LEAY ,X POINT Y TO SEARCH POSITION +4241 f673 ee 62 LDU $02,S POINT U TO START OF TARGET +4242 f675 e6 61 LDB $01,S LOAD ACCB WITH LENGTH OF TARGET +4243 f677 a6 e4 LDA ,S LOAD ACCA WITH LENGTH OF SEARCH +4244 f679 a0 66 SUBA $06,S SUBTRACT SEARCH POSITION FROM SEARCH LENGTH +4245 f67b 4c INCA ADD ONE +4246 f67c a1 61 CMPA $01,S COMPARE TO TARGET LENGTH +4247 f67e 25 0c BLO L87D9 RETURN 0 IF TARGET LENGTH > WHAT’S LEFT OF SEARCH STRING +4248 f680 a6 80 L87CD LDA ,X+ GET A CHARACTER FROM SEARCH STRING +4249 f682 a1 c0 CMPA ,U+ COMPARE IT TO TARGET STRING +4250 f684 26 0c BNE L87DF BRANCH IF NO MATCH +4251 f686 5a DECB DECREMENT TARGET LENGTH +4252 f687 26 f7 BNE L87CD CHECK ANOTHER CHARACTER +4253 f689 e6 66 L87D6 LDB $06,S GET MATCH POSITION +4254 f68b 21 L87D8 FCB SKP1 SKIP NEXT BYTE +4255 f68c 5f L87D9 CLRB MATCH ADDRESS = 0 +4256 f68d 32 67 LEAS $07,S CLEAN UP THE STACK +4257 f68f 7e e7 77 JMP LB4F3 CONVERT ACCB TO FP NUMBER +4258 f692 6c 66 L87DF INC $06,S INCREMENT SEARCH POSITION +4259 f694 30 21 LEAX $01,Y MOVE X TO NEXT SEARCH POSITION +4260 f696 20 d9 BRA L87BE KEEP LOOKING FOR A MATCH +4261 +4262 * EXTENDED BASIC RVEC19 HOOK CODE +4263 f698 81 26 XVEC19 CMPA #'&' * +4264 f69a 26 5c BNE L8845 * RETURN IF NOT HEX OR OCTAL VARIABLE +4265 f69c 32 62 LEAS $02,S PURGE RETURN ADDRESS FROM STACK +4266 * PROCESS A VARIABLE PRECEEDED BY A ‘&‘ (&H,&O) +4267 f69e 0f 52 L87EB CLR FPA0+2 * CLEAR BOTTOM TWO +4268 f6a0 0f 53 CLR FPA0+3 * BYTES OF FPA0 +4269 f6a2 8e 00 52 LDX #FPA0+2 BYTES 2,3 OF FPA0 = (TEMPORARY ACCUMULATOR) +4270 f6a5 9d 7c JSR GETNCH GET A CHARACTER FROM BASIC +4271 f6a7 81 4f CMPA #'O' +4272 f6a9 27 12 BEQ L880A YES +4273 f6ab 81 48 CMPA #'H' +4274 f6ad 27 23 BEQ L881F YES +4275 f6af 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +4276 f6b1 20 0c BRA L880C DEFAULT TO OCTAL (&O) +4277 f6b3 81 38 L8800 CMPA #'8' +4278 f6b5 10 22 ee 47 LBHI LB277 +4279 f6b9 c6 03 LDB #$03 BASE 8 MULTIPLIER +4280 f6bb 8d 2a BSR L8834 ADD DIGIT TO TEMPORARY ACCUMULATOR +4281 * EVALUATE AN &O VARIABLE +4282 f6bd 9d 7c L880A JSR GETNCH GET A CHARACTER FROM BASIC +4283 f6bf 25 f2 L880C BLO L8800 BRANCH IF NUMERIC +4284 f6c1 0f 50 L880E CLR FPA0 * CLEAR 2 HIGH ORDER +4285 f6c3 0f 51 CLR FPA0+1 * BYTES OF FPA0 +4286 f6c5 0f 06 CLR VALTYP SET VARXABLE TYPE TO NUMERIC +4287 f6c7 0f 63 CLR FPSBYT ZERO OUT SUB BYTE OF FPA0 +4288 f6c9 0f 54 CLR FP0SGN ZERO OUT MANTISSA SIGN OF FPA0 +4289 f6cb c6 a0 LDB #$A0 * SET EXPONENT OF FPA0 +4290 f6cd d7 4f STB FP0EXP * +4291 f6cf 7e ec 65 JMP LBA1C GO NORMALIZE FPA0 +4292 * EVALUATE AN &H VARIABLE +4293 f6d2 9d 7c L881F JSR GETNCH GET A CHARACTER FROM BASIC +4294 f6d4 25 0b BLO L882E BRANCH IF NUMERIC +4295 f6d6 bd e6 26 JSR LB3A2 SET CARRY IF NOT ALPHA +4296 f6d9 25 e6 BLO L880E BRANCH IF NOT ALPHA OR NUMERIC +4297 f6db 81 47 CMPA #'G' CHECK FOR LETTERS A-F +4298 f6dd 24 e2 BCC L880E BRANCH IF >= G (ILLEGAL HEX LETTER) +4299 f6df 80 07 SUBA #7 SUBTRACT ASCII DIFFERENCE BETWEEN A AND 9 +4300 f6e1 c6 04 L882E LDB #$04 BASE 16 DIGIT MULTIPLIER = 2**4 +4301 f6e3 8d 02 BSR L8834 ADD DIGIT TO TEMPORARY ACCUMULATOR +4302 f6e5 20 eb BRA L881F KEEP EVALUATING VARIABLE +4303 f6e7 68 01 L8834 ASL $01,X * MULTIPLY TEMPORARY +4304 f6e9 69 84 ROL ,X * ACCUMULATOR BY TWO +4305 f6eb 10 25 f5 ec LBCS LBA92 ‘OV' OVERFLOW ERROR +4306 f6ef 5a DECB DECREMENT SHIFT COUNTER +4307 f6f0 26 f5 BNE L8834 MULTIPLY TEMPORARY ACCUMULATOR AGAIN +4308 f6f2 80 30 SUBA #'0' MASK OFF ASCII +4309 f6f4 ab 01 ADDA $01,X * ADD DIGIT TO TEMPORARY +4310 f6f6 a7 01 STA $01,X * ACCUMULATOR AND SAVE IT +4311 f6f8 39 L8845 RTS +4312 +4313 f6f9 35 40 XVEC15 PULS U PULL RETURN ADDRESS AND SAVE IN U REGISTER +4314 f6fb 0f 06 CLR VALTYP SET VARIABLE TYPE TO NUMERIC +4315 f6fd 9e 83 LDX CHARAD CURRENT INPUT POINTER TO X +4316 f6ff 9d 7c JSR GETNCH GET CHARACTER FROM BASIC +4317 f701 81 26 CMPA #'&' HEX AND OCTAL VARIABLES ARE PRECEEDED BY & +4318 f703 27 99 BEQ L87EB PROCESS A ‘&‘ VARIABLE +4319 f705 81 b0 CMPA #TOK_FN TOKEN FOR FN +4320 f707 27 5e BEQ L88B4 PROCESS FN CALL +4321 f709 81 ff CMPA #$FF CHECK FOR SECONDARY TOKEN +4322 f70b 26 08 BNE L8862 NOT SECONDARY +4323 f70d 9d 7c JSR GETNCH GET CHARACTER FROM BASIC +4324 f70f 81 83 CMPA #TOK_USR TOKEN FOR USR +4325 f711 10 27 00 ab LBEQ L892C PROCESS USR CALL +4326 f715 9f 83 L8862 STX CHARAD RESTORE BASIC’S INPUT POINTER +4327 f717 6e c4 JMP ,U RETURN TO CALLING ROUTINE +4328 f719 9e 68 L8866 LDX CURLIN GET CURRENT LINE NUMBER +4329 f71b 30 01 LEAX $01,X IN DIRECT MODE? +4330 f71d 26 d9 BNE L8845 RETURN IF NOT IN DIRECT MODE +4331 f71f c6 16 LDB #2*11 ‘ILLEGAL DIRECT STATEMENT’ ERROR +4332 f721 7e df 03 L886E JMP LAC46 PROCESS ERROR +4333 +4334 f724 ae 9f 00 83 DEF LDX [CHARAD] GET TWO INPUT CHARS +4335 f728 8c ff 83 CMPX #TOK_FF_USR TOKEN FOR USR +4336 f72b 10 27 00 74 LBEQ L890F BRANCH IF DEF USR +4337 f72f 8d 23 BSR L88A1 GET DESCRIPTOR ADDRESS FOR FN VARIABLE NAME +4338 f731 8d e6 BSR L8866 DON’T ALLOW DEF FN IF IN DIRECT MODE +4339 f733 bd e4 f3 JSR LB26A SYNTAX CHECK FOR ‘(‘ +4340 f736 c6 80 LDB #$80 * GET THE FLAG TO INDICATE ARRAY VARIABLE SEARCH DISABLE +4341 f738 d7 08 STB ARYDIS * AND SAVE IT IN THE ARRAY DISABLE FLAG +4342 f73a bd e5 db JSR LB357 GET VARIABLE DESCRIPTOR +4343 f73d 8d 25 BSR L88B1 ‘TM’ ERROR IF STRING +4344 f73f bd e4 f0 JSR LB267 SYNTAX CHECK FOR ‘)‘ +4345 f742 c6 ae LDB #TOK_EQUALS TOKEN FOR ‘=‘ +4346 f744 bd e4 f8 JSR LB26F DO A SYNTAX CHECK FOR = +4347 f747 9e 4b LDX V4B GET THE ADDRESS OF THE FN NAME DESCRIPTOR +4348 f749 dc 83 LDD CHARAD * GET THE CURRENT INPUT POINTER ADDRESS AND +4349 f74b ed 84 STD ,X * SAVE IT IN FIRST 2 BYTES OF THE DESCRIPTOR +4350 f74d dc 39 LDD VARPTR = GET THE DESCRIPTOR ADDRESS OF THE ARGUMENT +4351 f74f ed 02 STD $02,X = VARIABLE AND SAVE IT IN THE DESCRIPTOR OF THE FN NAME +4352 f751 7e e1 8d JMP DATA MOVE INPUT POINTER TO END OF LINE OR SUBLINE +4353 f754 c6 b0 L88A1 LDB #TOK_FN TOKEN FOR FN +4354 f756 bd e4 f8 JSR LB26F DO A SYNTAX CHECK FOR FN +4355 f759 c6 80 LDB #$80 * GET THE FLAG TO INDICATE ARRAY VARIABLE SEARCH DISABLE FLAG +4356 f75b d7 08 STB ARYDIS * AND SAVE IT IN ARRAY VARIABLE FLAG +4357 f75d 8a 80 ORA #$80 SET BIT 7 OF CURRENT INPUT CHARACTER TO INDICATE AN FN VARIABLE +4358 f75f bd e5 e0 JSR LB35C * GET THE DESCRIPTOR ADDRESS OF THIS +4359 f762 9f 4b STX V4B * VARIABLE AND SAVE IT IN V4B +4360 f764 7e e3 cc L88B1 JMP LB143 ‘TM’ ERROR IF STRING VARIABLE +4361 * EVALUATE AN FN CALL +4362 f767 8d eb L88B4 BSR L88A1 * GET THE DESCRIPTOR OF THE FN NAME +4363 f769 34 10 PSHS X * VARIABLE AND SAVE IT ON THE STACK +4364 f76b bd e4 eb JSR LB262 SYNTAX CHECK FOR ‘(‘ & EVALUATE EXPR +4365 f76e 8d f4 BSR L88B1 ‘TM’ ERROR IF STRING VARIABLE +4366 f770 35 40 PULS U POINT U TO FN NAME DESCRIPTOR +4367 f772 c6 32 LDB #2*25 ‘UNDEFINED FUNCTION CALL’ ERROR +4368 f774 ae 42 LDX $02,U POINT X TO ARGUMENT VARIABLE DESCRIPTOR +4369 f776 27 a9 BEQ L886E BRANCH TO ERROR HANDLER +4370 f778 10 9e 83 LDY CHARAD SAVE CURRENT INPUT POINTER IN Y +4371 f77b ee c4 LDU ,U * POINT U TO START OF FN FORMULA AND +4372 f77d df 83 STU CHARAD * SAVE IT IN INPUT POINTER +4373 f77f a6 04 LDA $04,X = GET FP VALUE OF +4374 f781 34 02 PSHS A = ARGUMENT VARIABLE, CURRENT INPUT +4375 f783 ec 84 LDD ,X = POINTER, AND ADDRESS OF START +4376 f785 ee 02 LDU $02,X = OF FN FORMULA AND SAVE +4377 f787 34 76 PSHS U,Y,X,B,A = THEM ON THE STACK +4378 f789 bd ee 7e JSR LBC35 PACK FPA0 AND SAVE IT IN (X) +4379 f78c bd e3 ca L88D9 JSR LB141 EVALUATE FN EXPRESSION +4380 f78f 35 76 PULS A,B,X,Y,U RESTORE REGISTERS +4381 f791 ed 84 STD ,X * GET THE FP +4382 f793 ef 02 STU $02,X * VALUE OF THE ARGUMENT +4383 f795 35 02 PULS A * VARIABLE OFF OF THE +4384 f797 a7 04 STA $04,X * STACK AND RE-SAVE IT +4385 f799 9d 82 JSR GETCCH GET FINAL CHARACTER OF THE FN FORMULA +4386 f79b 10 26 ed 61 LBNE LB277 ‘SYNTAX’ ERROR IF NOT END OF LINE +4387 f79f 10 9f 83 STY CHARAD RESTORE INPUT POINTER +4388 f7a2 39 L88EF RTS +4389 +4390 +4391 +4392 * DEF USR +4393 f7a3 9d 7c L890F JSR GETNCH SKIP PAST SECOND BYTE OF DEF USR TOKEN +4394 f7a5 8d 09 BSR L891C GET FN NUMBER +4395 f7a7 34 10 PSHS X SAVE FN EXEC ADDRESS STORAGE LOC +4396 f7a9 8d 2d BSR L8944 CALCULATE EXEC ADDRESS +4397 f7ab 35 40 PULS U GET FN EXEC ADDRESS STORAGE LOC +4398 f7ad af c4 STX ,U SAVE EXEC ADDRESS +4399 f7af 39 RTS +4400 f7b0 5f L891C CLRB DEFAULT TO USR0 IF NO ARGUMENT +4401 f7b1 9d 7c JSR GETNCH GET A CHARACTER FROM BASIC +4402 f7b3 24 06 BCC L8927 BRANCH IF NOT NUMERIC +4403 f7b5 80 30 SUBA #'0' MASK OFF ASCII +4404 f7b7 1f 89 TFR A,B SAVE USR NUMBER IN ACCB +4405 f7b9 9d 7c JSR GETNCH GET A CHARACTER FROM BASIC +4406 f7bb 9e 8d L8927 LDX USRADR GET ADDRESS OF STORAGE LOCs FOR USR ADDRESS +4407 f7bd 58 ASLB X2 - 2 BYTES/USR ADDRESS +4408 f7be 3a ABX ADD OFFSET TO START ADDRESS OF STORAGE LOCs +4409 f7bf 39 RTS +4410 * PROCESS A USR CALL +4411 f7c0 8d ee L892C BSR L891C GET STORAGE LOC OF EXEC ADDRESS FOR USR N +4412 f7c2 ae 84 LDX ,X * GET EXEC ADDRESS AND +4413 f7c4 34 10 PSHS X * PUSH IT ONTO STACK +4414 f7c6 bd e4 eb JSR LB262 SYNTAX CHECK FOR ‘(‘ & EVALUATE EXPR +4415 f7c9 8e 00 4f LDX #FP0EXP POINT X TO FPA0 +4416 f7cc 96 06 LDA VALTYP GET VARIABLE TYPE +4417 f7ce 27 07 BEQ L8943 BRANCH IF NUMERIC, STRING IF <> 0 +4418 f7d0 bd e8 db JSR LB657 GET LENGTH & ADDRESS OF STRING VARIABLE +4419 f7d3 9e 52 LDX FPA0+2 GET POINTER TO STRING DESCRIPTOR +4420 f7d5 96 06 LDA VALTYP GET VARIABLE TYPE +4421 f7d7 39 L8943 RTS JUMP TO USR ROUTINE (PSHS X ABOVE) +4422 f7d8 c6 ae L8944 LDB #TOK_EQUALS TOKEN FOR ‘=‘ +4423 f7da bd e4 f8 JSR LB26F DO A SYNTAX CHECK FOR = +4424 f7dd 7e e9 c1 JMP LB73D EVALUATE EXPRESSION, RETURN VALUE IN X +4425 +4426 +4427 +4428 * DEL +4429 f7e0 10 27 ee ea DEL LBEQ LB44A FC’ ERROR IF NO ARGUMENT +4430 f7e4 bd e2 14 JSR LAF67 CONVERT A DECIMAL BASiC NUMBER TO BINARY +4431 f7e7 bd df a2 JSR LAD01 FIND RAM ADDRESS OF START OF A BASIC LINE +4432 f7ea 9f 93 STX VD3 SAVE RAM ADDRESS OF STARTING LINE NUMBER +4433 f7ec 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +4434 f7ee 27 10 BEQ L8990 BRANCH IF END OF LINE +4435 f7f0 81 a7 CMPA #TOK_MINUS TOKEN FOR ‘-' +4436 f7f2 26 3b BNE L89BF TERMINATE COMMAND IF LINE NUMBER NOT FOLLOWED BY ‘-‘ +4437 f7f4 9d 7c JSR GETNCH GET A CHARACTER FROM BASIC +4438 f7f6 27 04 BEQ L898C IF END OF LINE, USE DEFAULT ENDING LINE NUMBER +4439 f7f8 8d 24 BSR L89AE * CONVERT ENDING LINE NUMBER TO BINARY +4440 f7fa 20 04 BRA L8990 * AND SAVE IT IN BINVAL +4441 f7fc 86 ff L898C LDA #$FF = USE $FFXX AS DEFAULT ENDING +4442 f7fe 97 2b STA BINVAL = LINE NUMBER - SAVE IT IN BINVAL +4443 f800 de 93 L8990 LDU VD3 POINT U TO STARTING LINE NUMBER ADDRESS +4444 f802 8c L8992 FCB SKP2 SKIP TWO BYTES +4445 f803 ee c4 L8993 LDU ,U POINT U TO START OF NEXT LINE +4446 f805 ec c4 LDD ,U CHECK FOR END OF PROGRAM +4447 f807 27 06 BEQ L899F BRANCH IF END OF PROGRAM +4448 f809 ec 42 LDD $02,U LOAD ACCD WITH THIS LINE’S NUMBER +4449 f80b 93 2b SUBD BINVAL SUBTRACT ENDING LINE NUMBER ADDRESS +4450 f80d 23 f4 BLS L8993 BRANCH IF = < ENDING LINE NUMBER +4451 f80f 9e 93 L899F LDX VD3 GET STARTING LINE NUMBER +4452 f811 8d 15 BSR L89B8 MOVE (U) TO (X) UNTIL END OF PROGRAM +4453 f813 bd df c2 JSR LAD21 RESET BASIC’S INPUT POINTER AND ERASE VARIABLES +4454 f816 9e 93 LDX VD3 GET STARTING LINE NUMBER ADDRESS +4455 f818 bd df 92 JSR LACF1 RECOMPUTE START OF NEXT LINE ADDRESSES +4456 f81b 7e df 22 JMP LAC73 JUMP TO BASIC’S MAIN COMMAND LOOP +4457 f81e bd e2 14 L89AE JSR LAF67 GO GET LINE NUMBER CONVERTED TO BINARY +4458 f821 7e dc b7 JMP LA5C7 MAKE SURE THERE’S NO MORE ON THIS LINE +4459 f824 a6 c0 L89B4 LDA ,U+ GET A BYTE FROM (U) +4460 f826 a7 80 STA ,X+ MOVE THE BYTE TO (X) +4461 f828 11 93 1b L89B8 CMPU VARTAB COMPARE TO END OF BASIC +4462 f82b 26 f7 BNE L89B4 BRANCH IF NOT AT END +4463 f82d 9f 1b STX VARTAB SAVE (X) AS NEW END OF BASIC +4464 f82f 39 L89BF RTS +4465 +4466 +4467 f830 bd f7 19 L89C0 JSR L8866 ‘BS’ ERROR IF IN DIRECT MODE +4468 f833 9d 7c JSR GETNCH GET A CHAR FROM BASIC +4469 f835 81 22 L89D2 CMPA #'"' CHECK FOR PROMPT STRING +4470 f837 26 0b BNE L89E1 BRANCH IF NO PROMPT STRING +4471 f839 bd e4 cd JSR LB244 STRIP OFF PROMPT STRING & PUT IT ON STRING STACK +4472 f83c c6 3b LDB #';' * +4473 f83e bd e4 f8 JSR LB26F * DO A SYNTAX CHECK FOR; +4474 f841 bd eb e8 JSR LB99F REMOVE PROMPT STRING FROM STRING STACK & SEND TO CONSOLE OUT +4475 f844 32 7e L89E1 LEAS $-02,S RESERVE TWO STORAGE SLOTS ON STACK +4476 f846 bd e2 c9 JSR LB035 INPUT A LINE FROM CURRENT INPUT DEVICE +4477 f849 32 62 LEAS $02,S CLEAN UP THE STACK +4478 f84b bd e5 db JSR LB357 SEARCH FOR A VARIABLE +4479 f84e 9f 3b STX VARDES SAVE POINTER TO VARIABLE DESCRIPTOR +4480 f850 bd e3 cf JSR LB146 ‘TM’ ERROR IF VARIABLE TYPE = NUMERIC +4481 f853 8e 00 f3 LDX #LINBUF POINT X TO THE STRING BUFFER WHERE THE INPUT STRING WAS STORED +4482 f856 4f CLRA TERMINATOR CHARACTER 0 (END OF LINE) +4483 f857 bd e7 a0 JSR LB51A PARSE THE INPUT STRING AND STORE IT IN THE STRING SPACE +4484 f85a 7e e2 51 JMP LAFA4 REMOVE DESCRIPTOR FROM STRING STACK +4485 f85d bd e2 14 L89FC JSR LAF67 STRIP A DECIMAL NUMBER FROM BASIC INPUT LINE +4486 f860 9e 2b LDX BINVAL GET BINARY VALUE +4487 f862 39 RTS +4488 f863 9e 91 L8A02 LDX VD1 GET CURRENT OLD NUMBER BEING RENUMBERED +4489 f865 9f 2b L8A04 STX BINVAL SAVE THE LINE NUMBER BEING SEARCHED FOR +4490 f867 7e df a2 JMP LAD01 GO FIND THE LINE NUMBER IN BASIC PROGRAM +4491 +4492 * RENUM +4493 f86a bd df c7 RENUM JSR LAD26 ERASE VARIABLES +4494 f86d cc 00 0a LDD #10 DEFAULT LINE NUMBER INTERVAL +4495 f870 dd 95 STD VD5 SAVE DEFAULT RENUMBER START LINE NUMBER +4496 f872 dd 8f STD VCF SAVE DEFAULT INTERVAL +4497 f874 5f CLRB NOW ACCD = 0 +4498 f875 dd 91 STD VD1 DEFAULT LINE NUMBER OF WHERE TO START RENUMBERING +4499 f877 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +4500 f879 24 06 BCC L8A20 BRANCH IF NOT NUMERIC +4501 f87b 8d e0 BSR L89FC CONVERT DECIMAL NUMBER IN BASIC PROGRAM TO BINARY +4502 f87d 9f 95 STX VD5 SAVE LINE NUMBER WHERE RENUMBERING STARTS +4503 f87f 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +4504 f881 27 1b L8A20 BEQ L8A3D BRANCH IF END OF LINE +4505 f883 bd e4 f6 JSR LB26D SYNTAX CHECK FOR COMMA +4506 f886 24 06 BCC L8A2D BRANCH IF NEXT CHARACTER NOT NUMERIC +4507 f888 8d d3 BSR L89FC CONVERT DECIMAL NUMBER IN BASIC PROGRAM TO BINARY +4508 f88a 9f 91 STX VD1 SAVE NEW RENUMBER LINE +4509 f88c 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +4510 f88e 27 0e L8A2D BEQ L8A3D BRANCH IF END OF LINE +4511 f890 bd e4 f6 JSR LB26D SYNTAX CHECK FOR COMMA +4512 f893 24 06 BCC L8A3A BRANCH IF NEXT CHARACTER NOT NUMERIC +4513 f895 8d c6 BSR L89FC CONVERT DECIMAL NUMBER IN BASIC PROGRAM TO BINARY +4514 f897 9f 8f STX VCF SAVE NEW INTERVAL +4515 f899 27 49 BEQ L8A83 ‘FC' ERROR +4516 f89b bd dc b7 L8A3A JSR LA5C7 CHECK FOR MORE CHARACTERS ON LINE - ‘SYNTAX’ ERROR IF ANY +4517 f89e 8d c3 L8A3D BSR L8A02 GO GET ADDRESS OF OLD NUMBER BEING RENUMBERED +4518 f8a0 9f 93 STX VD3 SAVE ADDRESS +4519 f8a2 9e 95 LDX VD5 GET NEXT RENUMBERED LINE NUMBER TO USE +4520 f8a4 8d bf BSR L8A04 FIND THE LINE NUMBER IN THE BASIC PROGRAM +4521 f8a6 9c 93 CMPX VD3 COMPARE TO ADDRESS OF OLD LINE NUMBER +4522 f8a8 25 3a BLO L8A83 ‘FC’ ERROR IF NEW ADDRESS < OLD ADDRESS +4523 f8aa 8d 1c BSR L8A67 MAKE SURE RENUMBERED LINE NUMBERS WILL BE IN RANGE +4524 f8ac bd f9 3e JSR L8ADD CONVERT ASCII LINE NUMBERS TO ‘EXPANDED’ BINARY +4525 f8af bd df 90 JSR LACEF RECALCULATE NEXT LINE RAM ADDRESSES +4526 f8b2 8d af BSR L8A02 GET RAM ADDRESS OF FIRST LINE TO BE RENUMBERED +4527 f8b4 9f 93 STX VD3 SAVE IT +4528 f8b6 8d 3a BSR L8A91 MAKE SURE LINE NUMBERS EXIST +4529 f8b8 8d 0f BSR L8A68 INSERT NEW LINE NUMBERS IN LINE HEADERS +4530 f8ba 8d 36 BSR L8A91 INSERT NEW LINE NUMBERS IN PROGRAM STATEMENTS +4531 f8bc bd f9 d9 JSR L8B7B CONVERT PACKED BINARY LINE NUMBERS TO ASCII +4532 f8bf bd df c7 JSR LAD26 ERASE VARIABLES +4533 f8c2 bd df 90 JSR LACEF RECALCULATE NEXT LINE RAM ADDRESS +4534 f8c5 7e df 22 JMP LAC73 GO BACK TO BASIC’S MAIN LOOP +4535 f8c8 86 L8A67 FCB SKP1LD SKIP ONE BYTE - LDA #$4F +4536 f8c9 4f L8A68 CLRA NEW LINE NUMBER FLAG - 0; INSERT NEW LINE NUMBERS +4537 f8ca 97 98 STA VD8 SAVE NEW LINE NUMBER FLAG; 0 = INSERT NEW NUMBERS +4538 f8cc 9e 93 LDX VD3 GET ADDRESS OF OLD LINE NUMBER BEING RENUMBERED +4539 f8ce dc 95 LDD VD5 GET THE CURRENT RENUMBERED LINE NUMBER +4540 f8d0 8d 15 BSR L8A86 RETURN IF END OF PROGRAM +4541 f8d2 0d 98 L8A71 TST VD8 CHECK NEW LINE NUMBER FLAG +4542 f8d4 26 02 BNE L8A77 BRANCH IF NOT INSERTING NEW LINE NUMBERS +4543 f8d6 ed 02 STD $02,X STORE THE NEW LINE NUMBER IN THE BASIC PROGRAM +4544 f8d8 ae 84 L8A77 LDX ,X POINT X TO THE NEXT LINE IN BASIC +4545 f8da 8d 0b BSR L8A86 RETURN IF END OF PROGRAM +4546 f8dc d3 8f ADDD VCF ADD INTERVAL TO CURRENT RENUMBERED LINE NUMBER +4547 f8de 25 04 BLO L8A83 ‘FC’ ERROR IF LINE NUMBER > $FFFF +4548 f8e0 81 fa CMPA #MAXLIN LARGEST LINE NUMBER = $F9FF +4549 f8e2 25 ee BLO L8A71 BRANCH IF LEGAL LINE NUMBER +4550 f8e4 7e e6 ce L8A83 JMP LB44A ‘FC’ ERROR IF LINE NUMBER MS BYTE > $F9 +4551 * TEST THE TWO BYTES POINTED TO BY (X). +4552 * NORMAL RETURN IF <> 0. IF = 0 (END OF +4553 * PROGRAM) RETURN IS PULLED OFF STACK AND +4554 * YOU RETURN TO PREVIOUS SUBROUTINE CALL. +4555 f8e7 34 06 L8A86 PSHS B,A SAVE ACCD +4556 f8e9 ec 84 LDD ,X TEST THE 2 BYTES POINTED TO BY X +4557 f8eb 35 06 PULS A,B RESTORE ACCD +4558 f8ed 26 02 BNE L8A90 BRANCH IF NOT END OF PROGRAM +4559 f8ef 32 62 LEAS $02,S PURGE RETURN ADDRESS FROM STACK +4560 f8f1 39 L8A90 RTS +4561 f8f2 9e 19 L8A91 LDX TXTTAB GET START OF BASIC PROGRAM +4562 f8f4 30 1f LEAX $-01,X MOVE POINTER BACK ONE +4563 f8f6 30 01 L8A95 LEAX $01,X MOVE POINTER UP ONE +4564 f8f8 8d ed BSR L8A86 RETURN IF END OF PROGRAM +4565 f8fa 30 03 L8A99 LEAX $03,X SKIP OVER NEXT LINE ADDRESS AND LINE NUMBER +4566 f8fc 30 01 L8A9B LEAX $01,X MOVE POINTER TO NEXT CHARACTER +4567 f8fe a6 84 LDA ,X CHECK CURRENT CHARACTER +4568 f900 27 f4 BEQ L8A95 BRANCH IF END OF LINE +4569 f902 9f 0f STX TEMPTR SAVE CURRENT POINTER +4570 f904 4a DECA = +4571 f905 27 0c BEQ L8AB2 =BRANCH IF START OF PACKED NUMERIC LINE +4572 f907 4a DECA * +4573 f908 27 2a BEQ L8AD3 *BRANCH IF LINE NUMBER EXISTS +4574 f90a 4a DECA = +4575 f90b 26 ef BNE L8A9B =MOVE TO NEXT CHARACTER IF > 3 +4576 f90d 86 03 L8AAC LDA #$03 * SET 1ST BYTE = 3 TO INDICATE LINE +4577 f90f a7 80 STA ,X+ * NUMBER DOESN’T CURRENTLY EXIST +4578 f911 20 e7 BRA L8A99 GO GET ANOTHER CHARACTER +4579 f913 ec 01 L8AB2 LDD $01,X GET MS BYTE OF LINE NUMBER +4580 f915 6a 02 DEC $02,X DECREMENT ZERO CHECK BYTE +4581 f917 27 01 BEQ L8AB9 BRANCH IF MS BYTE <> 0 +4582 f919 4f CLRA CLEAR MS BYTE +4583 f91a e6 03 L8AB9 LDB $03,X GET LS BYTE OF LINE NUMBER +4584 f91c 6a 04 DEC $04,X DECREMENT ZERO CHECK FLAG +4585 f91e 27 01 BEQ L8AC0 BRANCH IF IS BYTE <> 0 +4586 f920 5f CLRB CLEAR LS BYTE +4587 f921 ed 01 L8AC0 STD $01,X SAVE BINARY LINE NUMBER +4588 f923 dd 2b STD BINVAL SAVE TRIAL LINE NUMBER +4589 f925 bd df a2 JSR LAD01 FIND RAM ADDRESS OF A BASIC LINE NUMBER +4590 f928 9e 0f L8AC7 LDX TEMPTR GET BACK POINTER TO START OF PACKED LINE NUMBER +4591 f92a 25 e1 BLO L8AAC BRANCH IF NO LINE NUMBER MATCH FOUND +4592 f92c dc 47 LDD V47 GET START ADDRESS OF LINE NUMBER +4593 f92e 6c 80 INC ,X+ * SET 1ST BYTE = 2, TO INDICATE LINE NUMBER EXISTS IF CHECKING FOR +4594 * * EXISTENCE OF LINE NUMBER, SET IT = 1 IF INSERTING LINE NUMBERS +4595 +4596 f930 ed 84 STD ,X SAVE RAM ADDRESS OF CORRECT LINE NUMBER +4597 f932 20 c6 BRA L8A99 GO GET ANOTHER CHARACTER +4598 f934 6f 84 L8AD3 CLR ,X CLEAR CARRY FLAG AND 1ST BYTE +4599 f936 ae 01 LDX $01,X POINT X TO RAM ADDRESS OF CORRECT LINE NUMBER +4600 f938 ae 02 LDX $02,X PUT CORRECT LINE NUMBER INTO (X) +4601 f93a 9f 47 STX V47 SAVE IT TEMPORARILY +4602 f93c 20 ea BRA L8AC7 GO INSERT IT INTO BASIC LINE +4603 f93e 9e 19 L8ADD LDX TXTTAB GET BEGINNING OF BASIC PROGRAM +4604 f940 20 04 BRA L8AE5 +4605 f942 9e 83 L8AE1 LDX CHARAD *GET CURRENT INPUT POINTER +4606 f944 30 01 LEAX $01,X *AND BUMP IT ONE +4607 f946 8d 9f L8AE5 BSR L8A86 RETURN IF END OF PROGRAM +4608 f948 30 02 LEAX $02,X SKIP PAST NEXT LINE ADDRESS +4609 f94a 30 01 L8AE9 LEAX $01,X ADVANCE POINTER BY ONE +4610 f94c 9f 83 L8AEB STX CHARAD SAVE NEW BASIC INPUT POINTER +4611 f94e 9d 7c L8AED JSR GETNCH GET NEXT CHARACTER FROM BASIC +4612 f950 4d L8AEF TSTA CHECK THE CHARACTER +4613 f951 27 ef BEQ L8AE1 BRANCH IF END OF LINE +4614 f953 2a f9 BPL L8AED BRANCH IF NOT A TOKEN +4615 f955 9e 83 LDX CHARAD GET CURRENT INPUT POINTER +4616 f957 81 ff CMPA #$FF IS THIS A SECONDARY TOKEN? +4617 f959 27 ef BEQ L8AE9 YES - IGNORE IT +4618 f95b 81 a2 CMPA #TOK_THEN TOKEN FOR THEN? +4619 f95d 27 12 BEQ L8B13 YES +4620 f95f 81 84 CMPA #TOK_ELSE TOKEN FOR ELSE? +4621 f961 27 0e BEQ L8B13 YES +4622 f963 81 81 CMPA #TOK_GO TOKEN FOR GO? +4623 f965 26 e7 BNE L8AED NO +4624 f967 9d 7c JSR GETNCH GET A CHARACTER FROM BASIC +4625 f969 81 a0 CMPA #TOK_TO TOKEN FOR TO? +4626 f96b 27 04 BEQ L8B13 YES +4627 f96d 81 a1 CMPA #TOK_SUB TOKEN FOR SUB? +4628 f96f 26 db BNE L8AEB NO +4629 f971 9d 7c L8B13 JSR GETNCH GET A CHARACTER FROM BASIC +4630 f973 25 04 BLO L8B1B BRANCH IF NUMERIC +4631 f975 9d 82 L8B17 JSR GETCCH GET CURRENT BASIC INPUT CHARRACTER +4632 f977 20 d7 BRA L8AEF KEEP CHECKING THE LINE +4633 f979 9e 83 L8B1B LDX CHARAD GET CURRENT INPUT ADDRESS +4634 f97b 34 10 PSHS X SAVE IT ON THE STACK +4635 f97d bd e2 14 JSR LAF67 CONVERT DECIMAL BASIC NUMBER TO BINARY +4636 f980 9e 83 LDX CHARAD GET CURRENT INPUT POINTER +4637 f982 a6 82 L8B24 LDA ,-X GET PREVIOUS INPUT CHARACTER +4638 f984 bd fc e9 JSR L90AA CLEAR CARRY IF NUMERIC INPUT VALUE +4639 f987 25 f9 BLO L8B24 BRANCH IF NON-NUMERIC +4640 f989 30 01 LEAX $01,X MOVE POINTER UP ONE +4641 f98b 1f 10 TFR X,D NOW ACCD POINTS TO ONE PAST END OF LINE NUMBER +4642 f98d e0 61 SUBB $01,S SUBTRACT PRE-NUMERIC POINTER LS BYTE +4643 f98f c0 05 SUBB #$05 MAKE SURE THERE ARE AT LEAST 5 CHARACTERS IN THE NUMERIC LINE +4644 * +4645 f991 27 20 BEQ L8B55 BRANCH IF EXACTLY 5 +4646 f993 25 0a BLO L8B41 BRANCH IF < 5 +4647 f995 33 84 LEAU ,X TRANSFER X TO U +4648 f997 50 NEGB NEGATE B +4649 f998 30 85 LEAX B,X MOVE X BACK B BYTES +4650 f99a bd f8 28 JSR L89B8 *MOVE BYTES FROM (U) TO (X) UNTIL +4651 * *U = END OF BASIC; (I) = NEW END OF BASIC +4652 f99d 20 14 BRA L8B55 +4653 * FORCE FIVE BYTES OF SPACE FOR THE LINE NUMBER +4654 f99f 9f 47 L8B41 STX V47 SAVE END OF NUMERIC VALUE +4655 f9a1 9e 1b LDX VARTAB GET END OF BASIC PROGRAM +4656 f9a3 9f 43 STX V43 SAVE IT +4657 f9a5 50 NEGB NEGATE B +4658 f9a6 30 85 LEAX B,X ADD IT TO END OF NUMERIC POiNTER +4659 f9a8 9f 41 STX V41 SAVE POINTER +4660 f9aa 9f 1b STX VARTAB STORE END OF BASIC PROGRAM +4661 f9ac bd de db JSR LAC1E ACCD = TOP OF ARRAYS - CHECK FOR ENOUGH ROOM +4662 f9af 9e 45 LDX V45 * GET AND SAVE THE +4663 f9b1 9f 83 STX CHARAD * NEW CURRENT INPUT POINTER +4664 f9b3 35 10 L8B55 PULS X RESTORE POINTER TO START OF NUMERIC VALUE +4665 f9b5 86 01 LDA #$01 NEW LINE NUMBER FLAG +4666 f9b7 a7 84 STA ,X * SAVE NEW LINE FLAG +4667 f9b9 a7 02 STA $02,X * +4668 f9bb a7 04 STA $04,X * +4669 f9bd d6 2b LDB BINVAL GET MS BYTE OF BINARY LINE NUMBER +4670 f9bf 26 04 BNE L8B67 BRANCH IF IT IS NOT ZERO +4671 f9c1 c6 01 LDB #$01 SAVE A 1 IF BYTE IS 0; OTHERWISE, BASIC WILL +4672 * THINK IT IS THE END OF A LINE +4673 f9c3 6c 02 INC $02,X IF 2,X = 2, THEN PREVIOUS BYTE WAS A ZERO +4674 f9c5 e7 01 L8B67 STB $01,X SAVE MS BYTE OF BINARY LINE NUMBER +4675 f9c7 d6 2c LDB BINVAL+1 GET IS BYTE OF BINARY LINE NUMBER +4676 f9c9 26 04 BNE L8B71 BRANCH IF NOT A ZERO BYTE +4677 f9cb c6 01 LDB #$01 SAVE A 1 IF BYTE IS A 0 +4678 f9cd 6c 04 INC $04,X IF 4,X = 2, THEN PREVIOUS BYTE WAS A 0 +4679 f9cf e7 03 L8B71 STB $03,X SAVE LS BYTE OF BINARY LINE NUMBER +4680 f9d1 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +4681 f9d3 81 2c CMPA #',' IS IT A COMMA? +4682 f9d5 27 9a BEQ L8B13 YES - PROCESS ANOTHER NUMERIC VALUE +4683 f9d7 20 9c BRA L8B17 NO - GO GET AND PROCESS AN INPUT CHARACTER +4684 f9d9 9e 19 L8B7B LDX TXTTAB POINT X TO START OF BASIC PROGRAM +4685 f9db 30 1f LEAX $-01,X MOVE POINTER BACK ONE +4686 f9dd 30 01 L8B7F LEAX $01,X MOVE POINTER UP ONE +4687 f9df ec 02 LDD $02,X GET ADDRESS OF NEXT LINE +4688 f9e1 dd 68 STD CURLIN SAVE IT IN CURLIN +4689 f9e3 bd f8 e7 JSR L8A86 RETURN IF END OF PROGRAM +4690 f9e6 30 03 LEAX $03,X SKIP OVER ADDRESS OF NEXT LINE AND 1ST BYTE OF LINE NUMBER +4691 f9e8 30 01 L8B8A LEAX $01,X MOVE POINTER UP ONE +4692 f9ea a6 84 L8B8C LDA ,X GET CURRENT CHARACTER +4693 f9ec 27 ef BEQ L8B7F BRANCH IF END OF LINE +4694 f9ee 4a DECA INPUT CHARACTER = 1? - VALID LINE NUMBER +4695 f9ef 27 1b BEQ L8BAE YES +4696 f9f1 80 02 SUBA #$02 INPUT CHARACTER 3? - UL LINE NUMBER +4697 f9f3 26 f3 BNE L8B8A NO +4698 f9f5 34 10 PSHS X SAVE CURRENT POSITION OF INPUT POINTER +4699 f9f7 8e fa 36 LDX #L8BD9-1 POINT X TO ‘UL’ MESSAGE +4700 f9fa bd eb e5 JSR LB99C PRINT STRING TO THE SCREEN +4701 f9fd ae e4 LDX ,S GET INPUT POINTER +4702 f9ff ec 01 LDD $01,X GET THE UNDEFINED LINE NUMBER +4703 fa01 bd f0 15 JSR LBDCC CONVERT NUMBER IN ACCD TO DECIMAL AND DISPLAY IT +4704 fa04 bd f0 0e JSR LBDC5 PRINT ‘IN XXXX’ XXXX = CURRENT LINE NUMBER +4705 fa07 bd eb a5 JSR LB958 SEND A CR TO CONSOLE OUT +4706 fa0a 35 10 PULS X GET INPUT POINTER BACK +4707 fa0c 34 10 L8BAE PSHS X SAVE CURRENT POSITION OF INPUT POINTER +4708 fa0e ec 01 LDD $01,X LOAD ACCD WITH BINARY VALUE OF LINE NUMBER +4709 fa10 dd 52 STD FPA0+2 SAVE IN BOTTOM 2 BYTES OF FPA0 +4710 fa12 bd f6 c1 JSR L880E ADJUST REST OF FPA0 AS AN INTEGER +4711 fa15 bd f0 22 JSR LBDD9 CONVERT FPA0 TO ASCII, STORE IN LINE NUMBER +4712 fa18 35 40 PULS U LOAD U WITH PREVIOUS ADDRESS OF INPUT POINTER +4713 fa1a c6 05 LDB #$05 EACH EXPANDED LINE NUMBER USES 5 BYTES +4714 fa1c 30 01 L8BBE LEAX $01,X MOVE POINTER FORWARD ONE +4715 fa1e a6 84 LDA ,X GET AN ASCII BYTE +4716 fa20 27 05 BEQ L8BC9 BRANCH IF END OF NUMBER +4717 fa22 5a DECB DECREMENT BYTE COUNTER +4718 fa23 a7 c0 STA ,U+ STORE ASCII NUMBER IN BASIC LINE +4719 fa25 20 f5 BRA L8BBE CHECK FOR ANOTHER DIGIT +4720 fa27 30 c4 L8BC9 LEAX ,U TRANSFER NEW LINE POINTER TO (X) +4721 fa29 5d TSTB DOES THE NEW LINE NUMBER REQUIRE 5 BYTES? +4722 fa2a 27 be BEQ L8B8C YES - GO GET ANOTHER INPUT CHARACTER +4723 fa2c 31 c4 LEAY ,U SAVE NEW LINE POINTER IN Y +4724 fa2e 33 c5 LEAU B,U POINT U TO END OF 5 BYTE PACKED LINE NUMBER BLOCK +4725 fa30 bd f8 28 JSR L89B8 MOVE BYTES FROM (U) TO (X) UNTIL END OF PROGRAM +4726 fa33 30 a4 LEAX ,Y LOAD (X) WITH NEW LINE POINTER +4727 fa35 20 b3 BRA L8B8C GO GET ANOTHER INPUT CHARACTER +4728 +4729 fa37 55 4c 20 L8BD9 FCC "UL " UNKNOWN LINE NUMBER MESSAGE +4730 fa3a 00 FCB 0 +4731 +4732 +4733 fa3b bd e9 c4 HEXDOL JSR LB740 CONVERT FPA0 INTO A POSITIVE 2 BYTE INTEGER +4734 fa3e 8e 01 f0 LDX #STRBUF+2 POINT TO TEMPORARY BUFFER +4735 fa41 c6 04 LDB #$04 CONVERT 4 NIBBLES +4736 fa43 34 04 L8BE5 PSHS B SAVE NIBBLE COUNTER +4737 fa45 5f CLRB CLEAR CARRY FLAG +4738 fa46 86 04 LDA #$04 4 SHIFTS +4739 fa48 08 53 L8BEA ASL FPA0+3 * SHIFT BOTTOM TWO BYTES OF +4740 fa4a 09 52 ROL FPA0+2 * FPA0 LEFT ONE BIT (X2) +4741 fa4c 59 ROLB IF OVERFLOW, ACCB <> 0 +4742 fa4d 4a DECA * DECREMENT SHIFT COUNTER AND +4743 fa4e 26 f8 BNE L8BEA * BRANCH IF NOT DONE +4744 fa50 5d TSTB CHECK FOR OVERFLOW +4745 fa51 26 0a BNE L8BFF BRANCH IF OVERFLOW +4746 fa53 a6 e4 LDA ,S * GET NIBBLE COUNTER, +4747 fa55 4a DECA * DECREMENT IT AND +4748 fa56 27 05 BEQ L8BFF * BRANCH IF DONE +4749 fa58 8c 01 f0 CMPX #STRBUF+2 DO NOT DO A CONVERSION UNTIL A NON-ZERO +4750 fa5b 27 0c BEQ L8C0B BYTE IS FOUND - LEADING ZERO SUPPRESSION +4751 fa5d cb 30 L8BFF ADDB #'0' ADD IN ASCII ZERO +4752 fa5f c1 39 CMPB #'9' COMPARE TO ASCII 9 +4753 fa61 23 02 BLS L8C07 BRANCH IF < 9 +4754 fa63 cb 07 ADDB #7 ADD ASCII OFFSET IF HEX LETTER +4755 fa65 e7 80 L8C07 STB ,X+ STORE HEX VALUE AND ADVANCE POINTER +4756 fa67 6f 84 CLR ,X CLEAR NEXT BYTE - END OF STRING FLAG +4757 fa69 35 04 L8C0B PULS B * GET NIBBLE COUNTER, +4758 fa6b 5a DECB * DECREMENT IT AND +4759 fa6c 26 d5 BNE L8BE5 * BRANCH IF NOT DONE +4760 fa6e 32 62 LEAS $02,S PURGE RETURN ADDRESS OFF OF STACK +4761 fa70 8e 01 ef LDX #STRBUF+1 RESET POINTER +4762 fa73 7e e7 9c JMP LB518 SAVE STRING ON STRING STACK +4763 * PROCESS EXCLAMATION POINT +4764 fa76 86 01 L8E37 LDA #$01 * SET SPACES +4765 fa78 97 99 STA VD9 * COUNTER = 1 +4766 * PROCESS STRING ITEM - LIST +4767 fa7a 5a L8E3B DECB DECREMENT FORMAT STRING LENGTH COUNTER +4768 fa7b bd fc 17 JSR L8FD8 SEND A '+' TO CONSOLE OUT IF VDA <>0 +4769 fa7e 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +4770 fa80 10 27 00 93 LBEQ L8ED8 EXIT PRINT USING IF END OF LINE +4771 fa84 d7 93 STB VD3 SAVE REMAINDER FORMAT STRING LENGTH +4772 fa86 bd e3 df JSR LB156 EVALUATE EXPRESSION +4773 fa89 bd e3 cf JSR LB146 ‘TM’ ERROR IF NUMERIC VARIABLE +4774 fa8c 9e 52 LDX FPA0+2 * GET ITEM - LIST DESCRIPTOR ADDRESS +4775 fa8e 9f 4d STX V4D * AND SAVE IT IN V4D +4776 fa90 d6 99 LDB VD9 GET SPACES COUNTER +4777 fa92 bd e9 31 JSR LB6AD PUT ACCB BYTES INTO STRING SPACE & PUT DESCRIPTOR ON STRING STACK +4778 fa95 bd eb e8 JSR LB99F PRINT THE FORMATTED STRING TO CONSOLE OUT +4779 * PAD FORMAT STRING WITH SPACES IF ITEM - LIST STRING < FORMAT STRING LENGTH +4780 fa98 9e 52 LDX FPA0+2 POINT X TO FORMATTED STRING DESCRIPTOR ADDRESS +4781 fa9a d6 99 LDB VD9 GET SPACES COUNTER +4782 fa9c e0 84 SUBB ,X SUBTRACT LENGTH OF FORMATTED STRING +4783 fa9e 5a L8E5F DECB DECREMENT DIFFERENCE +4784 fa9f 10 2b 01 4f LBMI L8FB3 GO INTERPRET ANOTHER ITEM - LIST +4785 faa3 bd eb f5 JSR LB9AC PAD FORMAT STRING WITH A SPACE +4786 faa6 20 f6 BRA L8E5F KEEP PADDING +4787 * PERCENT SIGN - PROCESS A %SPACES% COMMAND +4788 faa8 d7 93 L8E69 STB VD3 * SAVE THE CURRENT FORMAT STRING +4789 faaa 9f 0f STX TEMPTR * COUNTER AND POINTER +4790 faac 86 02 LDA #$02 INITIAL SPACES COUNTER = 2 +4791 faae 97 99 STA VD9 SAVE IN SPACES COUNTER +4792 fab0 a6 84 L8E71 LDA ,X GET A CHARACTER FROM FORMAT STRING +4793 fab2 81 25 CMPA #'%' COMPARE TO TERMINATOR CHARACTER +4794 fab4 27 c4 BEQ L8E3B BRANCH IF END OF SPACES COMMAND +4795 fab6 81 20 CMPA #' ' BLANK +4796 fab8 26 07 BNE L8E82 BRANCH IF ILLEGAL CHARACTER +4797 faba 0c 99 INC VD9 ADD ONE TO SPACES COUNTER +4798 fabc 30 01 LEAX $01,X MOVE FORMAT POINTER UP ONE +4799 fabe 5a DECB DECREMENT LENGTH COUNTER +4800 fabf 26 ef BNE L8E71 BRANCH IF NOT END OF FORMAT STRING +4801 fac1 9e 0f L8E82 LDX TEMPTR * RESTORE CURRENT FORMAT STRING COUNTER +4802 fac3 d6 93 LDB VD3 * AND POINTER TO POSITION BEFORE SPACES COMMAND +4803 fac5 86 25 LDA #'%' SEND A ‘%’ TO CONSOLE OUT AS A DEBUGGING AID +4804 * ERROR PROCESSOR - ILLEGAL CHARACTER OR BAD SYNTAX IN FORMAT STRING +4805 fac7 bd fc 17 L8E88 JSR L8FD8 SEND A ‘+' TO CONSOLE OUT IF VDA <> 0 +4806 faca bd db 14 JSR PUTCHR SEND CHARACTER TO CONSOLE OUT +4807 facd 20 29 BRA L8EB9 GET NEXT CHARACTER IN FORMAT STRING +4808 +4809 * PRINT RAM HOOK +4810 facf 81 b1 XVEC9 CMPA #TOK_USING USING TOKEN +4811 fad1 27 01 BEQ L8E95 BRANCH IF PRINT USING +4812 fad3 39 RTS +4813 +4814 * PRINT USING +4815 * VDA IS USED AS A STATUS BYTE: BIT 6 = COMMA FORCE +4816 * BIT 5=LEADING ASTERISK FORCE; BIT 4 = FLOATING $ FORCE +4817 * BIT 3 = PRE SIGN FORCE; BIT 2 = POST SIGN FORCE; BIT 0 = EXPONENTIAL FORCE +4818 fad4 32 62 L8E95 LEAS $02,S PURGE RETURN ADDRESS OFF THE STACK +4819 fad6 bd e3 e1 JSR LB158 EVALUATE FORMAT STRING +4820 fad9 bd e3 cf JSR LB146 ‘TM’ ERROR IF VARIABLE TYPE = NUMERIC +4821 fadc c6 3b LDB #';' CHECK FOR ITEM LIST SEPARATOR +4822 fade bd e4 f8 JSR LB26F SYNTAX CHECK FOR ; +4823 fae1 9e 52 LDX FPA0+2 * GET FORMAT STRING DESCRIPTOR ADDRESS +4824 fae3 9f 95 STX VD5 * AND SAVE IT IN VD5 +4825 fae5 20 06 BRA L8EAE GO PROCESS FORMAT STRING +4826 fae7 96 97 L8EA8 LDA VD7 *CHECK NEXT PRINT ITEM FLAG AND +4827 fae9 27 08 BEQ L8EB4 *‘FC’ ERROR IF NO FURTHER PRINT ITEMS +4828 faeb 9e 95 LDX VD5 RESET FORMAT STRING POINTER TO START OF STRING +4829 faed 0f 97 L8EAE CLR VD7 RESET NEXT PRINT ITEM FLAG +4830 faef e6 84 LDB ,X GET LENGTH OF FORMAT STRING +4831 faf1 26 03 BNE L8EB7 INTERPRET FORMAT STRING IF LENGTH > 0 +4832 faf3 7e e6 ce L8EB4 JMP LB44A ‘FC’ ERROR IF FORMAT STRING = NULL +4833 faf6 ae 02 L8EB7 LDX $02,X POINT X TO START OF FORMAT STRING +4834 * INTERPRET THE FORMAT STRING +4835 faf8 0f 9a L8EB9 CLR VDA CLEAR THE STATUS BYTE +4836 fafa 0f 99 L8EBB CLR VD9 CLEAR LEFT DIGIT COUNTER +4837 fafc a6 80 LDA ,X+ GET A CHARACTER FROM FORMAT STRING +4838 fafe 81 21 CMPA #'!' EXCLAMATION POINT? +4839 fb00 10 27 ff 72 LBEQ L8E37 YES - STRING TYPE FORMAT +4840 fb04 81 23 CMPA #'#' NUMBER SIGN? (DIGIT LOCATOR) +4841 fb06 27 5b BEQ L8F24 YES - NUMERIC TYPE FORMAT +4842 fb08 5a DECB DECREMENT FORMAT STRING LENGTH +4843 fb09 26 16 BNE L8EE2 BRANCH IF NOT DONE +4844 fb0b bd fc 17 JSR L8FD8 SEND A ‘+‘ TO CONSOLE OUT IF VDA <> 0 +4845 fb0e bd db 14 JSR PUTCHR SEND CHARACTER TO CONSOLE OUT +4846 fb11 9d 82 L8ED2 JSR GETCCH GET CURRENT CHARACTER FROM BASIC +4847 fb13 26 d2 BNE L8EA8 BRANCH IF NOT END OF LINE +4848 fb15 96 97 LDA VD7 GET NEXT PRINT ITEM FLAG +4849 fb17 26 03 L8ED8 BNE L8EDD BRANCH IF MORE PRINT ITEMS +4850 fb19 bd eb a5 JSR LB958 SEND A CARRIAGE RETURN TO CONSOLE OUT +4851 fb1c 9e 95 L8EDD LDX VD5 POINT X TO FORMAT STRING DESCRIPTOR +4852 fb1e 7e e8 dd JMP LB659 RETURN ADDRESS AND LENGTH OF FORMAT STRING - EXIT PRINT USING +4853 fb21 81 2b L8EE2 CMPA #'+' CHECK FOR ‘+‘ (PRE-SIGN FORCE) +4854 fb23 26 09 BNE L8EEF NO PLUS +4855 fb25 bd fc 17 JSR L8FD8 SEND A ‘+' TO CONSOLE OUT IF VDA <> 0 +4856 fb28 86 08 LDA #$08 * LOAD THE STATUS BYTE WITH 8; +4857 fb2a 97 9a STA VDA * PRE-SIGN FORCE FLAG +4858 fb2c 20 cc BRA L8EBB INTERPRET THE REST OF THE FORMAT STRING +4859 fb2e 81 2e L8EEF CMPA #'.' DECIMAL POINT? +4860 fb30 27 4e BEQ L8F41 YES +4861 fb32 81 25 CMPA #'%' PERCENT SIGN? +4862 fb34 10 27 ff 70 LBEQ L8E69 YES +4863 fb38 a1 84 CMPA ,X COMPARE THE PRESENT FORMAT STRING INPUT +4864 * CHARACTER TO THE NEXT ONE IN THE STRING +4865 fb3a 26 8b L8EFB BNE L8E88 NO MATCH - ILLEGAL CHARACTER +4866 * TWO CONSECUTIVE EQUAL CHARACTERS IN FORMAT STRING +4867 fb3c 81 24 CMPA #'$' DOLLAR SIGN? +4868 fb3e 27 19 BEQ L8F1A YES - MAKE THE DOLLAR SIGN FLOAT +4869 fb40 81 2a CMPA #'*' ASTERISK? +4870 fb42 26 f6 BNE L8EFB NO - ILLEGAL CHARACTER +4871 fb44 96 9a LDA VDA * GRAB THE STATUS BYTE AND BET BIT 5 +4872 fb46 8a 20 ORA #$20 * TO INDICATE THAT THE OUTPUT WILL +4873 fb48 97 9a STA VDA * BE LEFT PADDED WITH ASTERISKS +4874 fb4a c1 02 CMPB #2 * CHECK TO SEE IF THE $$ ARE THE LAST TWO +4875 fb4c 25 11 BLO L8F20 * CHARACTERS IN THE FORMAT STRING AND BRANCH IF SO +4876 fb4e a6 01 LDA $01,X GET THE NEXT CHARACTER AFTER ** +4877 fb50 81 24 CMPA #'$' CHECK FOR **$ +4878 fb52 26 0b BNE L8F20 CHECK FOR MORE CHARACTERS +4879 fb54 5a DECB DECREMENT STRING LENGTH COUNTER +4880 fb55 30 01 LEAX $01,X MOVE FORMAT STRING POINTER UP ONE +4881 fb57 0c 99 INC VD9 ADD ONE TO LEFT DIGIT COUNTER - FOR ASTERISK PAD AND +4882 * FLOATING DOLLAR SIGN COMBINATION +4883 fb59 96 9a L8F1A LDA VDA * GET THE STATUS BYTE AND SET +4884 fb5b 8a 10 ORA #$10 * BIT 4 TO INDICATE A +4885 fb5d 97 9a STA VDA * FLOATING DOLLAR SIGN +4886 fb5f 30 01 L8F20 LEAX $01,X MOVE FORMAT STRING POINTER UP ONE +4887 fb61 0c 99 INC VD9 ADD ONE TO LEFT DIGIT (FLOATING $ OR ASTERISK PAD) +4888 * PROCESS CHARACTERS TO THE LEFT OF THE DECIMAL POINT IN THE FORMAT STRING +4889 fb63 0f 98 L8F24 CLR VD8 CLEAR THE RIGHT DIGIT COUNTER +4890 fb65 0c 99 L8F26 INC VD9 ADD ONE TO LEFT DIGIT COUNTER +4891 fb67 5a DECB DECREMENT FORMAT STRING LENGTH COUNTER +4892 fb68 27 49 BEQ L8F74 BRANCH IF END OF FORMAT STRING +4893 fb6a a6 80 LDA ,X+ GET THE NEXT FORMAT CHARACTER +4894 fb6c 81 2e CMPA #'.' DECIMAL POINT? +4895 fb6e 27 1e BEQ L8F4F YES +4896 fb70 81 23 CMPA #'#' NUMBER SIGN? +4897 fb72 27 f1 BEQ L8F26 YES +4898 fb74 81 2c CMPA #',' COMMA? +4899 fb76 26 21 BNE L8F5A NO +4900 fb78 96 9a LDA VDA * GET THE STATUS BYTE +4901 fb7a 8a 40 ORA #$40 * AND SET BIT 6 WHICH IS THE +4902 fb7c 97 9a STA VDA * COMMA SEPARATOR FLAG +4903 fb7e 20 e5 BRA L8F26 PROCESS MORE CHARACTERS TO LEFT OF DECIMAL POINT +4904 * PROCESS DECIMAL POINT IF NO DIGITS TO LEFT OF IT +4905 fb80 a6 84 L8F41 LDA ,X GET NEXT FORMAT CHARACTER +4906 fb82 81 23 CMPA #'#' IS IT A NUMBER SIGN? +4907 fb84 10 26 ff 3f LBNE L8E88 NO +4908 fb88 86 01 LDA #1 * SET THE RIGHT DIGIT COUNTER TO 1 - +4909 fb8a 97 98 STA VD8 * ALLOW ONE SPOT FOR DECIMAL POINT +4910 fb8c 30 01 LEAX $01,X MOVE FORMAT POINTER UP ONE +4911 * PROCESS DIGITS TO RIGHT OF DECIMAL POINT +4912 fb8e 0c 98 L8F4F INC VD8 ADD ONE TO RIGHT DIGIT COUNTER +4913 fb90 5a DECB DECREMENT FORMAT LENGTH COUNTER +4914 fb91 27 20 BEQ L8F74 BRANCH IF END OF FORMAT STRING +4915 fb93 a6 80 LDA ,X+ GET A CHARACTER FROM FORMAT STRING +4916 fb95 81 23 CMPA #'#' IS IT NUMBER SIGN? +4917 fb97 27 f5 BEQ L8F4F YES - KEEP CHECKING +4918 * CHECK FOR EXPONENTIAL FORCE +4919 fb99 81 5e L8F5A CMPA #$5E CHECK FOR UP ARROW +4920 fb9b 26 16 BNE L8F74 NO UP ARROW +4921 fb9d a1 84 CMPA ,X IS THE NEXT CHARACTER AN UP ARROW? +4922 fb9f 26 12 BNE L8F74 NO +4923 fba1 a1 01 CMPA $01,X AND THE NEXT CHARACTER? +4924 fba3 26 0e BNE L8F74 NO +4925 fba5 a1 02 CMPA $02,X HOW ABOUT THE 4TH CHARACTER? +4926 fba7 26 0a BNE L8F74 NO, ALSO +4927 fba9 c1 04 CMPB #4 * CHECK TO SEE IF THE 4 UP ARROWS ARE IN THE +4928 fbab 25 06 BLO L8F74 * FORMAT STRING AND BRANCH IF NOT +4929 fbad c0 04 SUBB #4 * MOVE POINTER UP 4 AND SUBTRACT +4930 fbaf 30 04 LEAX $04,X * FOUR FROM LENGTH +4931 fbb1 0c 9a INC VDA INCREMENT STATUS BYTE - EXPONENTIAL FORM +4932 +4933 * CHECK FOR A PRE OR POST - SIGN FORCE AT END OF FORMAT STRING +4934 fbb3 30 1f L8F74 LEAX $-01,X MOVE POINTER BACK ONE +4935 fbb5 0c 99 INC VD9 ADD ONE TO LEFT DIGIT COUNTER FOR PRE-SIGN FORCE +4936 fbb7 96 9a LDA VDA * PRE-SIGN +4937 fbb9 85 08 BITA #$08 * FORCE AND +4938 fbbb 26 18 BNE L8F96 * BRANCH IF SET +4939 fbbd 0a 99 DEC VD9 DECREMENT LEFT DIGIT — NO PRE-SIGN FORCE +4940 fbbf 5d TSTB * CHECK LENGTH COUNTER AND BRANCH +4941 fbc0 27 13 BEQ L8F96 * IF END OF FORMAT STRING +4942 fbc2 a6 84 LDA ,X GET NEXT FORMAT STRING CHARACTER +4943 fbc4 80 2d SUBA #'-' CHECK FOR MINUS SIGN +4944 fbc6 27 06 BEQ L8F8F BRANCH IF MINUS SIGN +4945 fbc8 81 fe CMPA #$FE * WAS CMPA #('+')-('-') +4946 fbca 26 09 BNE L8F96 BRANCH IF NO PLUS SIGN +4947 fbcc 86 08 LDA #$08 GET THE PRE-SIGN FORCE FLAG +4948 fbce 8a 04 L8F8F ORA #$04 ‘OR’ IN POST-SIGN FORCE FLAG +4949 fbd0 9a 9a ORA VDA ‘OR’ IN THE STATUS BYTE +4950 fbd2 97 9a STA VDA SAVE THE STATUS BYTE +4951 fbd4 5a DECB DECREMENT FORMAT STRING LENGTH +4952 +4953 * EVALUATE NUMERIC ITEM-LIST +4954 fbd5 9d 82 L8F96 JSR GETCCH GET CURRENT CHARACTER +4955 fbd7 10 27 ff 3c LBEQ L8ED8 BRANCH IF END OF LINE +4956 fbdb d7 93 STB VD3 SAVE FORMAT STRING LENGTH WHEN FORMAT EVALUATION ENDED +4957 fbdd bd e3 ca JSR LB141 EVALUATE EXPRESSION +4958 fbe0 96 99 LDA VD9 GET THE LEFT DIGIT COUNTER +4959 fbe2 9b 98 ADDA VD8 ADD IT TO THE RIGHT DIGIT COUNTER +4960 fbe4 81 11 CMPA #17 * +4961 fbe6 10 22 ea e4 LBHI LB44A *‘FC’ ERROR IF MORE THAN 16 DIGITS AND DECIMAL POiNT +4962 fbea bd fc 24 JSR L8FE5 CONVERT ITEM-LIST TO FORMATTED ASCII STRING +4963 fbed 30 1f LEAX $-01,X MOVE BUFFER POINTER BACK ONE +4964 fbef bd eb e5 JSR LB99C DISPLAY THE FORMATTED STRING TO CONSOLE OUT +4965 fbf2 0f 97 L8FB3 CLR VD7 RESET NEXT PRINT ITEM FLAG +4966 fbf4 9d 82 JSR GETCCH GET CURRENT INPUT CHARACTER +4967 fbf6 27 0d BEQ L8FC6 BRANCH IF END OF LINE +4968 fbf8 97 97 STA VD7 SAVE CURRENT CHARACTER (<>0) IN NEXT PRINT ITEM FLAG +4969 fbfa 81 3b CMPA #';' * CHECK FOR ; - ITEM-LIST SEPARATOR AND +4970 fbfc 27 05 BEQ L8FC4 * BRANCH IF SEMICOLON +4971 fbfe bd e4 f6 JSR LB26D SYNTAX CHECK FOR COMMA +4972 fc01 20 02 BRA L8FC6 PROCESS NEXT PRINT ITEM +4973 fc03 9d 7c L8FC4 JSR GETNCH GET NEXT INPUT CHARACTER +4974 fc05 9e 95 L8FC6 LDX VD5 GET FORMAT STRING DESCRIPTOR ADDRESS +4975 fc07 e6 84 LDB ,X GET LENGTH OF FORMAT STRING +4976 fc09 d0 93 SUBB VD3 SUBTRACT AMOUNT OF FORMAT STRING LEFT AFTER LAST PRINT ITEM +4977 fc0b ae 02 LDX $02,X *GET FORMAT STRING START ADDRESS AND ADVANCE +4978 fc0d 3a ABX *POINTER TO START OF UNUSED FORMAT STRING +4979 fc0e d6 93 LDB VD3 * GET AMOUNT OF UNUSED FORMAT STRING +4980 fc10 10 26 fe e4 LBNE L8EB9 * REINTERPRET FORMAT STRING FROM THAT POINT +4981 fc14 7e fb 11 JMP L8ED2 REINTERPRET FORMAT STRING FROM THE START IF ENTIRELY +4982 * USED ON LAST PRINT ITEM +4983 +4984 * PRINT A ‘+‘ TO CONSOLE OUT IF THE STATUS BYTE <> 0 +4985 fc17 34 02 L8FD8 PSHS A RESTORE ACCA AND RETURN +4986 fc19 86 2b LDA #'+' GET ASCII PLUS SIGN +4987 fc1b 0d 9a TST VDA * CHECK THE STATUS BYTE AND +4988 fc1d 27 03 BEQ L8FE3 * RETURN IF = 0 +4989 fc1f bd db 14 JSR PUTCHR SEND A CHARACTER TO CONSOLE OUT +4990 fc22 35 82 L8FE3 PULS A,PC RETURN ACCA AND RETURN +4991 +4992 * CONVERT ITEM-LIST TO DECIMAL ASCII STRING +4993 fc24 ce 01 f2 L8FE5 LDU #STRBUF+4 POINT U TO STRING BUFFER +4994 fc27 c6 20 LDB #SPACE BLANK +4995 fc29 96 9a LDA VDA * GET THE STATUS FLAG AND +4996 fc2b 85 08 BITA #$08 * CHECK FOR A PRE-SIGN FORCE +4997 fc2d 27 02 BEQ L8FF2 * BRANCH IF NO PRE-SIGN FORCE +4998 fc2f c6 2b LDB #'+' PLUS SIGN +4999 fc31 0d 54 L8FF2 TST FP0SGN CHECK THE SIGN OF FPA0 +5000 fc33 2a 04 BPL L8FFA BRANCH IF POSITIVE +5001 fc35 0f 54 CLR FP0SGN FORCE FPA0 SIGN TO BE POSITIVE +5002 fc37 c6 2d LDB #'-' MINUS SIGN +5003 fc39 e7 c0 L8FFA STB ,U+ SAVE THE SIGN IN BUFFER +5004 fc3b c6 30 LDB #'0' * PUT A ZERO INTO THE BUFFER +5005 fc3d e7 c0 STB ,U+ * +5006 fc3f 84 01 ANDA #$01 * CHECK THE EXPONENTIAL FORCE FLAG IN +5007 fc41 10 26 01 07 LBNE L910D * THE STATUS BYTE - BRANCH IF ACTIVE +5008 fc45 8e f0 09 LDX #LBDC0 POINT X TO FLOATING POINT 1E + 09 +5009 fc48 bd ee e9 JSR LBCA0 COMPARE FPA0 TO (X) +5010 fc4b 2b 15 BMI L9023 BRANCH IF FPA0 < 1E+09 +5011 fc4d bd f0 22 JSR LBDD9 CONVERT FP NUMBER TO ASCII STRING +5012 fc50 a6 80 L9011 LDA ,X+ * ADVANCE POINTER TO END OF +5013 fc52 26 fc BNE L9011 * ASCII STRING (ZERO BYTE) +5014 fc54 a6 82 L9015 LDA ,-X MOVE THE +5015 fc56 a7 01 STA $01,X ENTIRE STRING +5016 fc58 8c 01 f1 CMPX #STRBUF+3 UP ONE +5017 fc5b 26 f7 BNE L9015 BYTE +5018 fc5d 86 25 LDA #'%' * INSERT A % SIGN AT START OF +5019 fc5f a7 84 STA ,X * STRING - OVERFLOW ERROR +5020 fc61 39 RTS +5021 +5022 fc62 96 4f L9023 LDA FP0EXP GET EXPONENT OF FPA0 +5023 fc64 97 47 STA V47 AND SAVE IT IN V74 +5024 fc66 27 03 BEQ L902C BRANCH IF FPA0 = 0 +5025 fc68 bd fe 0c JSR L91CD CONVERT FPA0 TO NUMBER WITH 9 SIGNIFICANT +5026 * PLACES TO LEFT OF DECIMAL POINT +5027 fc6b 96 47 L902C LDA V47 GET BASE 10 EXPONENT OFFSET +5028 fc6d 10 2b 00 81 LBMI L90B3 BRANCH IF FPA0 < 100,000,000 +5029 fc71 40 NEGA * CALCULATE THE NUMBER OF LEADING ZEROES TO INSERT - +5030 fc72 9b 99 ADDA VD9 * SUBTRACT BASE 10 EXPONENT OFFSET AND 9 (FPA0 HAS +5031 fc74 80 09 SUBA #$09 * 9 PLACES TO LEFT OF EXPONENT) FROM LEFT DIGIT COUNTER +5032 fc76 bd fd 29 JSR L90EA PUT ACCA ZEROES IN STRING BUFFER +5033 fc79 bd fe a2 JSR L9263 INITIALIZE DECIMAL POINT AND COMMA COUNTERS +5034 fc7c bd fe 41 JSR L9202 CONVERT FPA0 TO DECIMAL ASCII IN THE STRING BUFFER +5035 fc7f 96 47 LDA V47 * GET BASE 10 EXPONENT AND PUT THAT MANY +5036 fc81 bd fe c0 JSR L9281 * ZEROES IN STRING BUFFER - STOP AT DECIMAL POINT +5037 fc84 96 47 LDA V47 WASTED INSTRUCTION - SERVES NO PURPOSE +5038 fc86 bd fe 88 JSR L9249 CHECK FOR DECIMAL POINT +5039 fc89 96 98 LDA VD8 GET THE RIGHT DIGIT COUNTER +5040 fc8b 26 02 BNE L9050 BRANCH IF RIGHT DIGlT COUNTER <> 0 +5041 fc8d 33 5f LEAU $-01,U * MOVE BUFFER POINTER BACK ONE - DELETE +5042 * * DECIMAL POINT IF NO RIGHT DIGITS SPECiFIED +5043 fc8f 4a L9050 DECA SUBTRACT ONE (DECIMAL POINT) +5044 fc90 bd fd 29 JSR L90EA PUT ACCA ZEROES INTO BUFFER (TRAILING ZEROES) +5045 fc93 bd fd c4 L9054 JSR L9185 INSERT ASTERISK PADDING, FLOATING $, AND POST-SIGN +5046 fc96 4d TSTA WAS THERE A POST-SIGN? +5047 fc97 27 06 BEQ L9060 NO +5048 fc99 c1 2a CMPB #'*' IS THE FIRST CHARACTER AN $? +5049 fc9b 27 02 BEQ L9060 YES +5050 fc9d e7 c0 STB ,U+ STORE THE POST-SIGN +5051 fc9f 6f c4 L9060 CLR ,U CLEAR THE LAST CHARACTER IN THE BUFFER +5052 * +5053 * REMOVE ANY EXTRA BLANKS OR ASTERISKS FROM THE +5054 * STRING BUFFER TO THE LEFT OF THE DECIMAL POINT +5055 fca1 8e 01 f1 LDX #STRBUF+3 POINT X TO THE START OF THE BUFFER +5056 fca4 30 01 L9065 LEAX $01,X MOVE BUFFER POINTER UP ONE +5057 fca6 9f 0f STX TEMPTR SAVE BUFFER POINTER IN TEMPTR +5058 fca8 96 3a LDA VARPTR+1 * GET ADDRESS OF DECIMAL POINT IN BUFFER, SUBTRACT +5059 fcaa 90 10 SUBA TEMPTR+1 * CURRENT POSITION AND SUBTRACT LEFT DIGIT COUNTER - +5060 fcac 90 99 SUBA VD9 * THE RESULT WILL BE ZERO WHEN TEMPTR+1 IS POINTING +5061 * * TO THE FIRST DIGIT OF THE FORMAT STRING +5062 fcae 27 38 BEQ L90A9 RETURN IF NO DIGITS TO LEFT OF THE DECiMAL POINT +5063 fcb0 a6 84 LDA ,X GET THE CURRENT BUFFER CHARACTER +5064 fcb2 81 20 CMPA #SPACE SPACE? +5065 fcb4 27 ee BEQ L9065 YES - ADVANCE POINTER +5066 fcb6 81 2a CMPA #'*' ASTERISK? +5067 fcb8 27 ea BEQ L9065 YES - ADVANCE POINTER +5068 fcba 4f CLRA A ZERO ON THE STACK IS END OF DATA POINTER +5069 fcbb 34 02 L907C PSHS A PUSH A CHARACTER ONTO THE STACK +5070 fcbd a6 80 LDA ,X+ GET NEXT CHARACTER FROM BUFFER +5071 fcbf 81 2d CMPA #'-' MINUS SIGN? +5072 fcc1 27 f8 BEQ L907C YES +5073 fcc3 81 2b CMPA #'+' PLUS SIGN? +5074 fcc5 27 f4 BEQ L907C YES +5075 fcc7 91 00 CMPA $'$' DOLLAR SIGN? +5076 fcc9 27 f0 BEQ L907C YES +5077 fccb 81 30 CMPA #'0' ZERO? +5078 fccd 26 0e BNE L909E NO - ERROR +5079 fccf a6 01 LDA $01,X GET CHARACTER FOLLOWING ZERO +5080 fcd1 8d 16 BSR L90AA CLEAR CARRY IF NUMERIC +5081 fcd3 25 08 BLO L909E BRANCH IF NOT A NUMERIC CHARACTER - ERROR +5082 fcd5 35 02 L9096 PULS A * PULL A CHARACTER OFF OF THE STACK +5083 fcd7 a7 82 STA ,-X * AND PUT IT BACK IN THE STRING BUFFER +5084 fcd9 26 fa BNE L9096 * KEEP GOING UNTIL ZERO FLAG +5085 fcdb 20 c7 BRA L9065 KEEP CLEANING UP THE INPUT BUFFER +5086 fcdd 35 02 L909E PULS A +5087 fcdf 4d TSTA * THE STACK AND EXIT WHEN +5088 fce0 26 fb BNE L909E * ZERO FLAG FOUND +5089 fce2 9e 0f LDX TEMPTR GET THE STRING BUFFER START POINTER +5090 fce4 86 25 LDA #'%' * PUT A % SIGN BEFORE THE ERROR POSITION TO +5091 fce6 a7 82 STA ,-X * INDICATE AN ERROR +5092 fce8 39 L90A9 RTS +5093 * +5094 * CLEAR CARRY IF NUMERIC +5095 fce9 81 30 L90AA CMPA #'0' ASCII ZERO +5096 fceb 25 04 BLO L90B2 RETURN IF ACCA < ASCII 0 +5097 fced 80 3a SUBA #$3A * #'9'+1 +5098 fcef 80 c6 SUBA #$C6 * #-('9'+1) CARRY CLEAR IF NUMERIC +5099 fcf1 39 L90B2 RTS +5100 * +5101 * PROCESS AN ITEM-LIST WHICH IS < 100,000,000 +5102 fcf2 96 98 L90B3 LDA VD8 GET RIGHT DIGIT COUNTER +5103 fcf4 27 01 BEQ L90B8 BRANCH IF NO FORMATTED DIGITS TO THE RIGHT OF DECIMAL PT +5104 fcf6 4a DECA SUBTRACT ONE FOR DECIMAL POINT +5105 fcf7 9b 47 L90B8 ADDA V47 *ADD THE BASE 10 EXPONENT OFFSET - ACCA CONTAINS THE +5106 * *NUMBER OF SHIFTS REQUIRED TO ADJUST FPA0 TO THE SPECIFIED +5107 * *NUMBER OF DlGITS TO THE RIGHT OF THE DECIMAL POINT +5108 fcf9 2b 01 BMI L90BD IF ACCA >= 0 THEN NO SHIFTS ARE REQUIRED +5109 fcfb 4f CLRA FORCE SHIFT COUNTER = 0 +5110 fcfc 34 02 L90BD PSHS A SAVE INITIAL SHIFT COUNTER ON THE STACK +5111 fcfe 2a 0a L90BF BPL L90CB EXIT ROUTINE IF POSITIVE +5112 fd00 34 02 PSHS A SAVE SHIFT COUNTER ON STACK +5113 fd02 bd ed cb JSR LBB82 DIVIDE FPA0 BY 10 - SHIFT ONE DIGIT TO RIGHT +5114 fd05 35 02 PULS A GET SHIFT COUNTER FROM THE STACK +5115 fd07 4c INCA BUMP SHIFT COUNTER UP BY ONE +5116 fd08 20 f4 BRA L90BF CHECK FOR FURTHER DIVISION +5117 fd0a 96 47 L90CB LDA V47 * GET BASE 10 EXPONENT OFFSET, ADD INITIAL SHIFT COUNTER +5118 fd0c a0 e0 SUBA ,S+ * AND SAVE NEW BASE 10 EXPONENT OFFSET - BECAUSE +5119 fd0e 97 47 STA V47 * FPA0 WAS SHIFTED ABOVE +5120 fd10 8b 09 ADDA #$09 * ADD NINE (SIGNIFICANT PLACES) AND BRANCH IF THERE ARE NO +5121 fd12 2b 19 BMI L90EE * ZEROES TO THE LEFT OF THE DECIMAL POINT IN THIS PRINT ITEM +5122 fd14 96 99 LDA VD9 *DETERMINE HOW MANY FILLER ZEROES TO THE LEFT OF THE DECIMAL +5123 fd16 80 09 SUBA #$09 *POINT. GET THE NUMBER OF FORMAT PLACES TO LEFT OF DECIMAL +5124 fd18 90 47 SUBA V47 *POINT, SUBTRACT THE BASE 10 EXPONENT OFFSET AND THE CONSTANT 9 +5125 fd1a 8d 0d BSR L90EA *(UNNORMALIZATION)-THEN OUTPUT THAT MANY ZEROES TO THE BUFFER +5126 fd1c bd fe a2 JSR L9263 INITIALIZE DECIMAL POINT AND COMMA COUNTERS +5127 fd1f 20 1d BRA L90FF PROCESS THE REMAINDER OF THE PRINT ITEM +5128 * +5129 * PUT (ACCA+1) ASCII ZEROES IN BUFFER +5130 fd21 34 02 L90E2 PSHS A SAVE ZERO COUNTER +5131 fd23 86 30 LDA #'0' * INSERT A ZERO INTO +5132 fd25 a7 c0 STA ,U+ * THE BUFFER +5133 fd27 35 02 PULS A RESTORE ZERO COUNTER +5134 +5135 * PUT ACCA ASCII ZEROES INTO THE BUFFER +5136 fd29 4a L90EA DECA DECREMENT ZERO COUNTER +5137 fd2a 2a f5 BPL L90E2 BRANCH IF NOT DONE +5138 fd2c 39 RTS +5139 +5140 fd2d 96 99 L90EE LDA VD9 * GET THE LEFT DIGIT COUNTER AND PUT +5141 fd2f 8d f8 BSR L90EA * THAT MANY ZEROES IN THE STRiNG BUFFER +5142 fd31 bd fe 8c JSR L924D PUT THE DECIMAL POINT IN THE STRING BUFFER +5143 fd34 86 f7 LDA #-9 *DETERMINE HOW MANY FILLER ZEROES BETWEEN THE DECIMAL POINT +5144 fd36 90 47 SUBA V47 *AND SIGNIFICANT DATA. SUBTRACT BASE 10 EXPONENT FROM -9 +5145 fd38 8d ef BSR L90EA *(UNNORMALIZATION) AND OUTPUT THAT MANY ZEROES TO BUFFER +5146 fd3a 0f 45 CLR V45 CLEAR THE DECIMAL POINT COUNTER - SUPPRESS THE DECIMAL POINT +5147 fd3c 0f 97 CLR VD7 CLEAR THE COMMA COUNTER - SUPPRESS COMMAS +5148 fd3e bd fe 41 L90FF JSR L9202 DECODE FPA0 INTO A DECIMAL ASCII STRING +5149 fd41 96 98 LDA VD8 GET THE RIGHT DIGIT COUNTER +5150 fd43 26 02 BNE L9108 BRANCH IF RIGHT DIGIT COUNTER <> 0 +5151 fd45 de 39 LDU VARPTR RESET BUFFER PTR TO THE DECIMAL POINT IF NO DIGITS TO RIGHT +5152 fd47 9b 47 L9108 ADDA V47 *ADD BASE 10 EXPONENT - A POSITIVE ACCA WILL CAUSE THAT MANY +5153 * *FILLER ZEROES TO BE OUTPUT TO THE RIGHT OF LAST SIGNIFICANT DATA +5154 * *SIGNIFICANT DATA +5155 fd49 16 ff 43 LBRA L9050 INSERT LEADING ASTERISKS, FLOATING DOLLAR SIGN, ETC +5156 * +5157 * FORCE THE NUMERIC OUTPUT FORMAT TO BE EXPONENTIAL FORMAT +5158 fd4c 96 4f L910D LDA FP0EXP * GET EXPONENT OF FPA0 AND +5159 fd4e 34 02 PSHS A * SAVE IT ON THE STACK +5160 fd50 27 03 BEQ L9116 BRANCH IF FPA0 = 0 +5161 fd52 bd fe 0c JSR L91CD *CONVERT FPA0 INTO A NUMBER WITH 9 SIGNIFICANT +5162 * *DIGITS TO THE LEFT OF THE DECIMAL POINT +5163 fd55 96 98 L9116 LDA VD8 GET THE RIGHT DIGIT COUNTER +5164 fd57 27 01 BEQ L911B BRANCH IF NO FORMATTED DIGITS TO THE RIGHT +5165 fd59 4a DECA SUBTRACT ONE FOR THE DECIMAL POINT +5166 fd5a 9b 99 L911B ADDA VD9 ADD TO THE LEFT DIGIT COUNTER +5167 fd5c 7f 01 f1 CLR STRBUF+3 CLEAR BUFFER BYTE AS TEMPORARY STORAGE LOCATION +5168 fd5f d6 9a LDB VDA * GET THE STATUS BYTE FOR A +5169 fd61 c4 04 ANDB #$04 * POST-BYTE FORCE; BRANCH IF +5170 fd63 26 03 BNE L9129 * A POST-BYTE FORCE +5171 fd65 73 01 f1 COM STRBUF+3 TOGGLE BUFFER BYTE TO -1 IF NO POST-BYTE FORCE +5172 fd68 bb 01 f1 L9129 ADDA STRBUF+3 SUBTRACT 1 IF NO POST BYTE FORCE +5173 fd6b 80 09 SUBA #$09 *SUBTRACT 9 (DUE TO THE CONVERSION TO 9 +5174 * *SIGNIFICANT DIGITS TO LEFT OF DECIMAL POINT) +5175 fd6d 34 02 PSHS A * SAVE SHIFT COUNTER ON THE STACK - ACCA CONTAINS THE NUMBER +5176 * OF SHIFTS REQUIRED TO ADJUST FPA0 FOR THE NUMBER OF +5177 * FORMATTED PLACES TO THE RIGHT OF THE DECIMAL POINT. +5178 fd6f 2a 0a L9130 BPL L913C NO MORE SHIFTS WHEN ACCA >= 0 +5179 fd71 34 02 PSHS A SAVE SHIFT COUNTER +5180 fd73 bd ed cb JSR LBB82 DIVIDE FPA0 BY 10 - SHIFT TO RIGHT ONE +5181 fd76 35 02 PULS A RESTORE THE SHIFT COUNTER +5182 fd78 4c INCA ADD 1 TO SHIFT COUNTER +5183 fd79 20 f4 BRA L9130 CHECK FOR FURTHER SHIFTING (DIVISION) +5184 fd7b a6 e4 L913C LDA ,S *GET THE INITIAL VALUE OF THE SHIFT COUNTER +5185 fd7d 2b 01 BMI L9141 *AND BRANCH IF SHIFTING HAS TAKEN PLACE +5186 fd7f 4f CLRA RESET ACCA IF NO SHIFTING HAS TAKEN PLACE +5187 fd80 40 L9141 NEGA *CALCULATE THE POSITION OF THE DECIMAL POINT BY +5188 fd81 9b 99 ADDA VD9 *NEGATING SHIFT COUNTER, ADDING THE LEFT DIGIT COUNTER +5189 fd83 4c INCA *PLUS ONE AND THE POST-BYTE POSlTION, IF USED +5190 fd84 bb 01 f1 ADDA STRBUF+3 * +5191 fd87 97 45 STA V45 SAVE DECIMAL POINT COUNTER +5192 fd89 0f 97 CLR VD7 CLEAR COMMA COUNTER - NO COMMAS INSERTED +5193 fd8b bd fe 41 JSR L9202 CONVERT FPA0 INTO ASCII DECIMAL STRING +5194 fd8e 35 02 PULS A * GET THE INITIAL VALUE OF SHIFT COUNTER AND +5195 fd90 bd fe c0 JSR L9281 * INSERT THAT MANY ZEROES INTO THE BUFFER +5196 fd93 96 98 LDA VD8 *GET THE RIGHT DIGIT COUNTER AND BRANCH +5197 fd95 26 02 BNE L915A *IF NOT ZERO +5198 fd97 33 5f LEAU $-01,U MOVE BUFFER POINTER BACK ONE +5199 +5200 * CALCULATE VALUE OF EXPONENT AND PUT IN STRING BUFFER +5201 fd99 e6 e0 L915A LDB ,S+ GET ORIGINAL EXPONENT OF FPA0 +5202 fd9b 27 09 BEQ L9167 BRANCH IF EXPONENT = 0 +5203 fd9d d6 47 LDB V47 GET BASE 10 EXPONENT +5204 fd9f cb 09 ADDB #$09 ADD 9 FOR 9 SIGNIFICANT DIGIT CONVERSION +5205 fda1 d0 99 SUBB VD9 SUBTRACT LEFT DIGIT COUNTER +5206 fda3 f0 01 f1 SUBB STRBUF+3 ADD ONE TO EXPONENT IF POST-SIGN FORCE +5207 fda6 86 2b L9167 LDA #'+' PLUS SIGN +5208 fda8 5d TSTB TEST EXPONENT +5209 fda9 2a 03 BPL L916F BRANCH IF POSITIVE EXPONENT +5210 fdab 86 2d LDA #'-' MINUS SIGN +5211 fdad 50 NEGB CONVERT EXPONENT TO POSITIVE NUMBER +5212 fdae a7 41 L916F STA $01,U PUT SIGN OF EXPONENT IN STRING BUFFER +5213 fdb0 86 45 LDA #'E' * PUT AN ‘E’ (EXPONENTIATION FLAG) IN +5214 fdb2 a7 c1 STA ,U++ * BUFFER AND SKIP OVER THE SIGN +5215 fdb4 86 2f LDA #$2F * WAS LDA #'0'-1 +5216 *CONVERT BINARY EXPONENT IN ACCB TO ASCII VALUE IN ACCA +5217 fdb6 4c L9177 INCA ADD ONE TO TENS DIGIT COUNTER +5218 fdb7 c0 0a SUBB #10 *SUBTRACT 10 FROM EXPONENT AND ADD ONE TO TENS +5219 fdb9 24 fb BCC L9177 * DIGIT IF NO CARRY. TENS DIGIT DONE IF THERE IS A CARRY +5220 fdbb cb 3a ADDB #$3A WAS ADDB #'9'+1 +5221 fdbd ed c1 STD ,U++ SAVE EXPONENT IN BUFFER +5222 fdbf 6f c4 CLR ,U CLEAR FINAL BYTE IN BUFFER - PRINT TERMINATOR +5223 fdc1 7e fc 93 JMP L9054 INSERT ASTERISK PADDING, FLOATING DOLLAR SIGN, ETC. +5224 +5225 * INSERT ASTERISK PADDING, FLOATING $ AND PRE-SIGN +5226 fdc4 8e 01 f2 L9185 LDX #STRBUF+4 POINT X TO START OF PRINT ITEM BUFFER +5227 fdc7 e6 84 LDB ,X * GET SIGN BYTE OF ITEM-LIST BUFFER +5228 fdc9 34 04 PSHS B * AND SAVE IT ON THE STACK +5229 fdcb 86 20 LDA #SPACE DEFAULT PAD WITH BLANKS +5230 fdcd d6 9a LDB VDA * GET STATUS BYTE AND CHECK FOR +5231 fdcf c5 20 BITB #$20 * ASTERISK LEFT PADDING +5232 fdd1 35 04 PULS B GET SIGN BYTE AGAIN +5233 fdd3 27 08 BEQ L919E BRANCH IF NO PADDING +5234 fdd5 86 2a LDA #'*' PAD WITH ASTERISK +5235 fdd7 c1 20 CMPB #SPACE WAS THE FIRST BYTE A BLANK (POSITIVE)? +5236 fdd9 26 02 BNE L919E NO +5237 fddb 1f 89 TFR A,B TRANSFER PAD CHARACTER TO ACCB +5238 fddd 34 04 L919E PSHS B SAVE FIRST CHARACTER ON STACK +5239 fddf a7 80 L91A0 STA ,X+ STORE PAD CHARACTER IN BUFFER +5240 fde1 e6 84 LDB ,X GET NEXT CHARACTER IN BUFFER +5241 fde3 27 10 BEQ L91B6 INSERT A ZERO IF END OF BUFFER +5242 fde5 c1 45 CMPB #'E' * CHECK FOR AN ‘E’ AND +5243 fde7 27 0c BEQ L91B6 * PUT A ZERO BEFORE IT +5244 fde9 c1 30 CMPB #'0' * REPLACE LEADING ZEROES WITH +5245 fdeb 27 f2 BEQ L91A0 * PAD CHARACTERS +5246 fded c1 2c CMPB #',' * REPLACE LEADING COMMAS +5247 fdef 27 ee BEQ L91A0 * WITH PAD CHARACTERS +5248 fdf1 c1 2e CMPB #'.' * CHECK FOR DECIMAL POINT +5249 fdf3 26 04 BNE L91BA * AND DON’T PUT A ZERO BEFORE IT +5250 fdf5 86 30 L91B6 LDA #'0' * REPLACE PREVIOUS CHARACTER +5251 fdf7 a7 82 STA ,-X * WITH A ZERO +5252 fdf9 96 9a L91BA LDA VDA * GET STATUS BYTE, CHECK +5253 fdfb 85 10 BITA #$10 * FOR FLOATING $ +5254 fdfd 27 04 BEQ L91C4 * BRANCH IF NO FLOATING $ +5255 fdff c6 24 LDB #'$' * STORE A $ IN +5256 fe01 e7 82 STB ,-X * BUFFER +5257 fe03 84 04 L91C4 ANDA #$04 CHECK PRE-SIGN FLAG +5258 fe05 35 04 PULS B GET SIGN CHARACTER +5259 fe07 26 02 BNE L91CC RETURN IF POST-SIGN REQUIRED +5260 fe09 e7 82 STB ,-X STORE FIRST CHARACTER +5261 fe0b 39 L91CC RTS +5262 * +5263 * CONVERT FPA0 INTO A NUMBER OF THE FORM - NNN,NNN,NNN X 10**M. +5264 * THE EXPONENT M WILL BE RETURNED IN V47 (BASE 10 EXPONENT). +5265 fe0c 34 40 L91CD PSHS U SAVE BUFFER POINTER +5266 fe0e 4f CLRA INITIAL EXPONENT OFFSET = 0 +5267 fe0f 97 47 L91D0 STA V47 SAVE EXPONENT OFFSET +5268 fe11 d6 4f LDB FP0EXP GET EXPONENT OF FPA0 +5269 fe13 c1 80 CMPB #$80 * COMPARE TO EXPONENT OF .5 +5270 fe15 22 11 BHI L91E9 * AND BRANCH IF FPA0 > = 1.0 +5271 +5272 * IF FPA0 < 1.0, MULTIPLY IT BY 1E+09 UNTIL IT IS >= 1 +5273 fe17 8e f0 09 LDX #LBDC0 POINT X TO FP NUMBER (1E+09) +5274 fe1a bd ed 13 JSR LBACA MULTIPLY FPA0 BY 1E+09 +5275 fe1d 96 47 LDA V47 GET EXPONENT OFFSET +5276 fe1f 80 09 SUBA #$09 SUBTRACT 9 (BECAUSE WE MULTIPLIED BY 1E+09 ABOVE) +5277 fe21 20 ec BRA L91D0 CHECK TO SEE IF > 1.0 +5278 fe23 bd ed cb L91E4 JSR LBB82 DIVIDE FPA0 BY 10 +5279 fe26 0c 47 INC V47 INCREMENT EXPONENT OFFSET +5280 fe28 8e f0 04 L91E9 LDX #LBDBB POINT X TO FP NUMBER (999,999,999) +5281 fe2b bd ee e9 JSR LBCA0 COMPARE FPA0 TO X +5282 fe2e 2e f3 BGT L91E4 BRANCH IF FPA0 > 999,999,999 +5283 fe30 8e ef ff L91F1 LDX #LBDB6 POINT X TO FP NUMBER (99,999,999.9) +5284 fe33 bd ee e9 JSR LBCA0 COMPARE FPA0 TO X +5285 fe36 2e 07 BGT L9200 RETURN IF 999,999,999 > FPA0 > 99,999,999.9 +5286 fe38 bd ed b3 JSR LBB6A MULTIPLY FPA0 BY 10 +5287 fe3b 0a 47 DEC V47 DECREMENT EXPONENT OFFSET +5288 fe3d 20 f1 BRA L91F1 KEEP UNNORMALIZING +5289 fe3f 35 c0 L9200 PULS U,PC RESTORE BUFFER POINTER AND RETURN +5290 * +5291 * CONVERT FPA0 INTO AN INTEGER, THEN DECODE IT +5292 * INTO A DECIMAL ASCII STRING IN THE BUFFER +5293 fe41 34 40 L9202 PSHS U SAVE BUFFER POINTER +5294 fe43 bd eb fd JSR LB9B4 ADD .5 TO FPA0 (ROUND OFF) +5295 fe46 bd ef 11 JSR LBCC8 CONVERT FPA0 TO INTEGER FORMAT +5296 fe49 35 40 PULS U RESTORE BUFFER POINTER +5297 * +5298 * CONVERT FPA0 INTO A DECIMAL ASCII STRING +5299 fe4b 8e f1 0e LDX #LBEC5 POINT X TO UNNORMALIZED POWERS OF 10 +5300 fe4e c6 80 LDB #$80 INITIALIZE DIGIT COUNTER TO 0 + $80. +5301 * BIT 7 SET IS USED TO INDICATE THAT THE POWER OF 10 MANTISSA +5302 * IS NEGATIVE. WHEN YOU ‘ADD’ A NEGATIVE MANTISSA, IT IS +5303 * THE SAME AS SUBTRACTING A POSITIVE ONE AND BIT 7 OF ACCB +5304 * IS HOW THIS ROUTINE KNOWS THAT A ‘SUBTRACTION’ IS OCCURRING. +5305 fe50 8d 36 L9211 BSR L9249 CHECK FOR COMMA INSERTION +5306 fe52 96 53 L9213 LDA FPA0+3 * ‘ADD’ A POWER OF 10 MANTISSA TO FPA0. +5307 fe54 ab 03 ADDA $03,X * IF THE MANTISSA IS NEGATIVE, A SUBTRACTION +5308 fe56 97 53 STA FPA0+3 * WILL BE WHAT REALLY TAKES PLACE. +5309 fe58 96 52 LDA FPA0+2 * +5310 fe5a a9 02 ADCA $02,X * +5311 fe5c 97 52 STA FPA0+2 * +5312 fe5e 96 51 LDA FPA0+1 * +5313 fe60 a9 01 ADCA $01,X * +5314 fe62 97 51 STA FPA0+1 * +5315 fe64 96 50 LDA FPA0 * +5316 fe66 a9 84 ADCA ,X * +5317 fe68 97 50 STA FPA0 * +5318 fe6a 5c INCB ADD ONE TO DIGIT COUNTER +5319 fe6b 56 RORB ROTATE CARRY INTO BIT 7 +5320 fe6c 59 ROLB * SET OVERFLOW FLAG - BRANCH IF CARRY SET AND +5321 fe6d 28 e3 BVC L9213 * ADDING MANTISSA OR CARRY CLEAR AND SUBTRACTING MANTISSA +5322 fe6f 24 03 BCC L9235 BRANCH IF SUBTRACTING MANTISSA +5323 fe71 c0 0b SUBB #10+1 WAS SUBB #10+1 +5324 fe73 50 NEGB * IF ADDING MANTISSA +5325 fe74 cb 2f L9235 ADDB #$2F WAS ADDB #'0'-1 +5326 fe76 30 04 LEAX $04,X MOVE TO NEXT POWER OF 10 MANTISSA +5327 fe78 1f 98 TFR B,A SAVE DIGIT IN ACCA +5328 fe7a 84 7f ANDA #$7F MASK OFF ADD/SUBTRACT FLAG (BIT 7) +5329 fe7c a7 c0 STA ,U+ STORE DIGIT IN BUFFER +5330 fe7e 53 COMB TOGGLE ADD/SUBTRACT FLAG +5331 fe7f c4 80 ANDB #$80 MASK OFF EVERYTHING BUT ADD/SUB FLAG +5332 fe81 8c f1 32 CMPX #LBEE9 COMPARE TO END OF UNNORMALIZED POWERS OF 10 +5333 fe84 26 ca BNE L9211 BRANCH IF NOT DONE +5334 fe86 6f c4 CLR ,U PUT A ZERO AT END OF INTEGER +5335 +5336 * DECREMENT DECIMAL POINT COUNTER AND CHECK FOR COMMA INSERTION +5337 fe88 0a 45 L9249 DEC V45 DECREMENT DECIMAL POINT COUNTER +5338 fe8a 26 09 BNE L9256 NOT TIME FOR DECIMAL POINT +5339 fe8c df 39 L924D STU VARPTR SAVE BUFFER POINTER-POSITION OF THE DECIMAL POINT +5340 fe8e 86 2e LDA #'.' * STORE A DECIMAL +5341 fe90 a7 c0 STA ,U+ * POINT IN THE OUTPUT BUFFER +5342 fe92 0f 97 CLR VD7 * CLEAR COMMA COUNTER - NOW IT WILL TAKE 255 +5343 * * DECREMENTS BEFORE ANOTHER COMMA WILL BE INSERTED +5344 fe94 39 RTS +5345 fe95 0a 97 L9256 DEC VD7 DECREMENT COMMA COUNTER +5346 fe97 26 08 BNE L9262 RETURN IF NOT TIME FOR COMMA +5347 fe99 86 03 LDA #$03 * RESET COMMA COUNTER TO 3; THREE +5348 fe9b 97 97 STA VD7 * DIGITS BETWEEN COMMAS +5349 fe9d 86 2c LDA #',' * PUT A COMMA INTO +5350 fe9f a7 c0 STA ,U+ * THE BUFFER +5351 fea1 39 L9262 RTS +5352 +5353 * INITIALIZE DECIMAL POINT AND COMMA COUNTERS +5354 fea2 96 47 L9263 LDA V47 GET THE BASE 10 EXPONENT OFFSET +5355 fea4 8b 0a ADDA #10 * ADD 10 (FPA0 WAS ‘NORMALIZED’ TO 9 PLACES LEFT +5356 fea6 97 45 STA V45 * OF DECIMAL POINT) - SAVE IN DECIMAL POINT COUNTER +5357 fea8 4c INCA ADD ONE FOR THE DECIMAL POINT +5358 fea9 80 03 L926A SUBA #$03 * DIVIDE DECIMAL POINT COUNTER BY 3; LEAVE +5359 feab 24 fc BCC L926A * THE REMAINDER IN ACCA +5360 fead 8b 05 ADDA #$05 CONVERT REMAINDER INTO A NUMBER FROM 1-3 +5361 feaf 97 97 STA VD7 SAVE COMMA COUNTER +5362 feb1 96 9a LDA VDA GET STATUS BYTE +5363 feb3 84 40 ANDA #$40 CHECK FOR COMMA FLAG +5364 feb5 26 02 BNE L927A BRANCH IF COMMA FLAG ACTIVE +5365 feb7 97 97 STA VD7 CLEAR COMMA COUNTER - 255 DIGITS OUTPUT BEFORE A COMMA +5366 feb9 39 L927A RTS +5367 * +5368 * INSERT ACCA ZEROES INTO THE BUFFER +5369 feba 34 02 L927B PSHS A SAVE ZEROES COUNTER +5370 febc 8d ca BSR L9249 CHECK FOR DECIMAL POINT +5371 febe 35 02 PULS A RESTORE ZEROES COUNTER +5372 fec0 4a L9281 DECA * DECREMENT ZEROES COUNTER AND +5373 fec1 2b 0a BMI L928E * RETURN IF < 0 +5374 fec3 34 02 PSHS A SAVE ZEROES COUNTER +5375 fec5 86 30 LDA #'0' * PUT A ZERO INTO +5376 fec7 a7 c0 STA ,U+ * THE BUFFER +5377 fec9 a6 e0 LDA ,S+ RESTORE THE ZEROES COUNTER +5378 fecb 26 ed BNE L927B BRANCH IF NOT DONE +5379 fecd 39 L928E RTS +5380 +5381 +5382 * LINE +5383 fece 81 89 LINE CMPA #TOK_INPUT ‘INPUT’ TOKEN +5384 fed0 10 27 f9 5c LBEQ L89C0 GO DO ‘LINE INPUT’ COMMAND +5385 fed4 7e e5 00 JMP LB277 ‘SYNTAX ERROR’ IF NOT "LINE INPUT" +5386 +5387 +5388 * END OF EXTENDED BASIC +5389 * INTERRUPT VECTORS +5390 fff0 ORG $FFF0 +5391 fff0 00 00 LBFF0 FDB $0000 RESERVED +5392 fff2 00 9b LBFF2 FDB SW3VEC SWI3 +5393 fff4 00 9e LBFF4 FDB SW2VEC SWI2 +5394 fff6 00 aa LBFF6 FDB FRQVEC FIRQ +5395 fff8 00 a7 LBFF8 FDB IRQVEC IRQ +5396 fffa 00 a1 LBFFA FDB SWIVEC SWI +5397 fffc 00 a4 LBFFC FDB NMIVEC NMI +5398 fffe db 46 LBFFE FDB RESVEC RESET diff --git a/MC6809/MC6809.Test/roms/searle/ExBasROM.asm b/MC6809/MC6809.Test/roms/searle/ExBasROM.asm new file mode 100644 index 0000000..6caba79 --- /dev/null +++ b/MC6809/MC6809.Test/roms/searle/ExBasROM.asm @@ -0,0 +1,5398 @@ + +UART EQU $A000 +RECEV EQU UART+1 +TRANS EQU UART+1 +USTAT EQU UART +UCTRL EQU UART + +BS EQU 8 BACKSPACE +CR EQU $D ENTER KEY +ESC EQU $1B ESCAPE CODE +SPACE EQU $20 SPACE (BLANK) +STKBUF EQU 58 STACK BUFFER ROOM +LBUFMX EQU 250 MAX NUMBER OF CHARS IN A BASIC LINE +MAXLIN EQU $FA MAXIMUM MS BYTE OF LINE NUMBER +* PSEUDO OPS +SKP1 EQU $21 OP CODE OF BRN — SKIP ONE BYTE +SKP2 EQU $8C OP CODE OF CMPX # - SKIP TWO BYTES +SKP1LD EQU $86 OP CODE OF LDA # - SKIP THE NEXT BYTE +* AND LOAD THE VALUE OF THAT BYTE INTO ACCA — THIS +* IS USUALLY USED TO LOAD ACCA WITH A NON ZERO VALUE +RTS_LOW EQU $95 + ORG 0 +ENDFLG RMB 1 STOP/END FLAG: POSITIVE=STOP, NEG=END +CHARAC RMB 1 TERMINATOR FLAG 1 +ENDCHR RMB 1 TERMINATOR FLAG 2 +TMPLOC RMB 1 SCRATCH VARIABLE +IFCTR RMB 1 IF COUNTER - HOW MANY IF STATEMENTS IN A LINE +DIMFLG RMB 1 *DV* ARRAY FLAG 0=EVALUATE, 1=DIMENSIONING +VALTYP RMB 1 *DV* *PV TYPE FLAG: 0=NUMERIC, $FF=STRING +GARBFL RMB 1 *TV STRING SPACE HOUSEKEEPING FLAG +ARYDIS RMB 1 DISABLE ARRAY SEARCH: 00=ALLOW SEARCH +INPFLG RMB 1 *TV INPUT FLAG: READ=0, INPUT<>0 +RELFLG RMB 1 *TV RELATIONAL OPERATOR FLAG +TEMPPT RMB 2 *PV TEMPORARY STRING STACK POINTER +LASTPT RMB 2 *PV ADDR OF LAST USED STRING STACK ADDRESS +TEMPTR RMB 2 TEMPORARY POINTER +TMPTR1 RMB 2 TEMPORARY DESCRIPTOR STORAGE (STACK SEARCH) +FPA2 RMB 4 FLOATING POINT ACCUMULATOR #2 MANTISSA +BOTSTK RMB 2 BOTTOM OF STACK AT LAST CHECK +TXTTAB RMB 2 *PV BEGINNING OF BASIC PROGRAM +VARTAB RMB 2 *PV START OF VARIABLES +ARYTAB RMB 2 *PV START OF ARRAYS +ARYEND RMB 2 *PV END OF ARRAYS (+1) +FRETOP RMB 2 *PV START OF STRING STORAGE (TOP OF FREE RAM) +STRTAB RMB 2 *PV START OF STRING VARIABLES +FRESPC RMB 2 UTILITY STRING POINTER +MEMSIZ RMB 2 *PV TOP OF STRING SPACE +OLDTXT RMB 2 SAVED LINE NUMBER DURING A "STOP" +BINVAL RMB 2 BINARY VALUE OF A CONVERTED LINE NUMBER +OLDPTR RMB 2 SAVED INPUT PTR DURING A "STOP" +TINPTR RMB 2 TEMPORARY INPUT POINTER STORAGE +DATTXT RMB 2 *PV 'DATA' STATEMENT LINE NUMBER POINTER +DATPTR RMB 2 *PV 'DATA' STATEMENT ADDRESS POINTER +DATTMP RMB 2 DATA POINTER FOR 'INPUT' & 'READ' +VARNAM RMB 2 *TV TEMP STORAGE FOR A VARIABLE NAME +VARPTR RMB 2 *TV POINTER TO A VARIABLE DESCRIPTOR +VARDES RMB 2 TEMP POINTER TO A VARIABLE DESCRIPTOR +RELPTR RMB 2 POINTER TO RELATIONAL OPERATOR PROCESSING ROUTINE +TRELFL RMB 1 TEMPORARY RELATIONAL OPERATOR FLAG BYTE +* FLOATING POINT ACCUMULATORS #3,4 & 5 ARE MOSTLY +* USED AS SCRATCH PAD VARIABLES. +** FLOATING POINT ACCUMULATOR #3 :PACKED: ($40-$44) +V40 RMB 1 +V41 RMB 1 +V42 RMB 1 +V43 RMB 1 +V44 RMB 1 +** FLOATING POINT ACCUMULATOR #4 :PACKED: ($45-$49) +V45 RMB 1 +V46 RMB 1 +V47 RMB 1 +V48 RMB 2 +** FLOATING POINT ACCUMULATOR #5 :PACKED: ($4A—$4E) +V4A RMB 1 +V4B RMB 2 +V4D RMB 2 +** FLOATING POINT ACCUMULATOR #0 +FP0EXP RMB 1 *PV FLOATING POINT ACCUMULATOR #0 EXPONENT +FPA0 RMB 4 *PV FLOATING POINT ACCUMULATOR #0 MANTISSA +FP0SGN RMB 1 *PV FLOATING POINT ACCUMULATOR #0 SIGN +COEFCT RMB 1 POLYNOMIAL COEFFICIENT COUNTER +STRDES RMB 5 TEMPORARY STRING DESCRIPTOR +FPCARY RMB 1 FLOATING POINT CARRY BYTE +** FLOATING POINT ACCUMULATOR #1 +FP1EXP RMB 1 *PV FLOATING POINT ACCUMULATOR #1 EXPONENT +FPA1 RMB 4 *PV FLOATING POINT ACCUMULATOR #1 MANTISSA +FP1SGN RMB 1 *PV FLOATING POINT ACCUMULATOR #1 SIGN +RESSGN RMB 1 SIGN OF RESULT OF FLOATING POINT OPERATION +FPSBYT RMB 1 FLOATING POINT SUB BYTE (FIFTH BYTE) +COEFPT RMB 2 POLYNOMIAL COEFFICIENT POINTER +LSTTXT RMB 2 CURRENT LINE POINTER DURING LIST +CURLIN RMB 2 *PV CURRENT LINE # OF BASIC PROGRAM, $FFFF = DIRECT +DEVCFW RMB 1 *TV TAB FIELD WIDTH +DEVLCF RMB 1 *TV TAB ZONE +DEVPOS RMB 1 *TV PRINT POSITION +DEVWID RMB 1 *TV PRINT WIDTH +RSTFLG RMB 1 *PV WARM START FLAG: $55=WARM, OTHER=COLD +RSTVEC RMB 2 *PV WARM START VECTOR - JUMP ADDRESS FOR WARM START +TOPRAM RMB 2 *PV TOP OF RAM +IKEYIM RMB 1 *TV INKEY$ RAM IMAGE +ZERO RMB 2 *PV DUMMY - THESE TWO BYTES ARE ALWAYS ZERO +* THE FOLLOWING BYTES ARE MOVED DOWN FROM ROM +LPTCFW RMB 1 16 +LPTLCF RMB 1 112 +LPTWID RMB 1 132 +LPTPOS RMB 1 0 +EXECJP RMB 2 LB4AA + +* THIS ROUTINE PICKS UP THE NEXT INPUT CHARACTER FROM +* BASIC. THE ADDRESS OF THE NEXT BASIC BYTE TO BE +* INTERPRETED IS STORED AT CHARAD. +GETNCH INC 7372800 / 4 / 16 = 115200 + STA UCTRL + LDX #LA147-1 POINT X TO COLOR BASIC COPYRIGHT MESSAGE + JSR LB99C PRINT ‘COLOR BASIC’ + LDX #BAWMST WARM START ADDRESS + STX RSTVEC SAVE IT + LDA #$55 WARM START FLAG + STA RSTFLG SAVE IT + BRA LA0F3 GO TO BASIC’S MAIN LOOP +BAWMST NOP NOP REQ’D FOR WARM START + JSR LAD33 DO PART OF A NEW +LA0F3 JMP LAC73 GO TO MAIN LOOP OF BASIC +* +* FIRQ SERVICE ROUTINE +BFRQSV + RTI +* +* THESE BYTES ARE MOVED TO ADDRESSES $76 - $85 THE DIRECT PAGE +LA10D FCB 16 TAB FIELD WIDTH + FCB 64 LAST TAB ZONE + FCB 80 PRINTER WIDTH + FCB 0 LINE PRINTER POSITION + FDB LB44A ARGUMENT OF EXEC COMMAND - SET TO ‘FC’ ERROR +* LINE INPUT ROUTINE + INC CHARAD+1 + BNE LA123 + INC CHARAD +LA123 LDA >0000 + JMP BROMHK +* +* THESE BYTES ARE MOVED TO ADDRESSES $A7-$B1 + JMP BIRQSV IRQ SERVICE + JMP BFRQSV FIRQ SERVICE + JMP LB44A USR ADDRESS FOR 8K BASIC (INITIALIZED TO ‘FC’ ERROR) + FCB $80 *RANDOM SEED + FDB $4FC7 *RANDON SEED OF MANTISSA + FDB $5259 *.811635157 +* BASIC COMMAND INTERPRETATION TABLE ROM IMAGE +COMVEC FCB 50 50 BASIC COMMANDS + FDB LAA66 POINTS TO RESERVED WORDS + FDB LAB67 POINTS TO JUMP TABLE FOR COMMANDS + FCB 29 29 BASIC SECONDARY COMMANDS + FDB LAB1A POINTS TO SECONDARY FUNCTION RESERVED WORDS + FDB LAA29 POINTS TO SECONDARY FUNCTION JUMP TABLE + FDB 0 NO MORE TABLES (RES WORDS=0) + FDB 0 NO MORE TABLES + FDB 0 NO MORE TABLES + FDB 0 NO MORE TABLES + FDB 0 NO MORE TABLES + FDB 0 NO MORE TABLES (SECONDARY FNS =0) + +* COPYRIGHT MESSAGES +LA147 FCC "6809 EXTENDED BASIC" + FCB CR + FCC "(C) 1982 BY MICROSOFT" +LA156 FCB CR,CR +LA165 FCB $00 + + +LA35F PSHS X,B,A SAVE REGISTERS + LDX LPTCFW TAB FIELD WIDTH AND TAB ZONE + LDD LPTWID PRINTER WIDTH AND POSITION +LA37C STX DEVCFW SAVE TAB FIELD WIDTH AND ZONE + STB DEVPOS SAVE PRINT POSITION + STA DEVWID SAVE PRINT WIDTH + PULS A,B,X,PC RESTORE REGISTERS + +* THIS IS THE ROUTINE THAT GETS AN INPUT LINE FOR BASIC +* EXIT WITH BREAK KEY: CARRY = 1 +* EXIT WITH ENTER KEY: CARRY = 0 +LA38D +LA390 CLR IKEYIM RESET BREAK CHECK KEY TEMP KEY STORAGE + LDX #LINBUF+1 INPUT LINE BUFFER + LDB #1 ACCB CHAR COUNTER: SET TO 1 TO ALLOW A +* BACKSPACE AS FIRST CHARACTER +LA39A JSR LA171 GO GET A CHARACTER FROM CONSOLE IN + CMPA #BS BACKSPACE + BNE LA3B4 NO + DECB YES - DECREMENT CHAR COUNTER + BEQ LA390 BRANCH IF BACK AT START OF LINE AGAIN + LEAX -1,X DECREMENT BUFFER POINTER + BRA LA3E8 ECHO CHAR TO SCREEN +LA3B4 CMPA #$15 SHIFT RIGHT ARROW? + BNE LA3C2 NO +* YES, RESET BUFFER TO BEGINNING AND ERASE CURRENT LINE +LA3B8 DECB DEC CHAR CTR + BEQ LA390 GO BACK TO START IF CHAR CTR = 0 + LDA #BS BACKSPACE? + JSR PUTCHR SEND TO CONSOLE OUT (SCREEN) + BRA LA3B8 KEEP GOING +LA3C2 CMPA #3 BREAK KEY? + ORCC #1 SET CARRY FLAG + BEQ LA3CD BRANCH IF BREAK KEY DOWN +LA3C8 CMPA #CR ENTER KEY? + BNE LA3D9 NO +LA3CC CLRA CLEAR CARRY FLAG IF ENTER KEY - END LINE ENTRY +LA3CD PSHS CC SAVE CARRY FLAG + JSR LB958 SEND CR TO SCREEN + CLR ,X MAKE LAST BYTE IN INPUT BUFFER = 0 + LDX #LINBUF RESET INPUT BUFFER POINTER + PULS CC,PC RESTORE CARRY FLAG + +* INSERT A CHARACTER INTO THE BASIC LINE INPUT BUFFER +LA3D9 CMPA #$20 IS IT CONTROL CHAR? + BLO LA39A BRANCH IF CONTROL CHARACTER + CMPA #'z+1 * + BCC LA39A * IGNORE IF > LOWER CASE Z + CMPB #LBUFMX HAVE 250 OR MORE CHARACTERS BEEN ENTERED? + BCC LA39A YES, IGNORE ANY MORE + STA ,X+ PUT IT IN INPUT BUFFER + INCB INCREMENT CHARACTER COUNTER +LA3E8 JSR PUTCHR ECHO IT TO SCREEN + BRA LA39A GO SET SOME MORE + + +* EXEC +EXEC BEQ LA545 BRANCH IF NO ARGUMENT + JSR LB73D EVALUATE ARGUMENT - ARGUMENT RETURNED IN X + STX EXECJP STORE X TO EXEC JUMP ADDRESS +LA545 JMP [EXECJP] GO DO IT + +* BREAK CHECK +LA549 JMP LADEB GO DO BREAK KEY CHECK + +* INKEY$ +INKEY LDA IKEYIM WAS A KEY DOWN IN THE BREAK CHECK? + BNE LA56B YES + JSR KEYIN GO GET A KEY +LA56B CLR IKEYIM CLEAR INKEY RAM IMAGE + STA FPA0+3 STORE THE KEY IN FPA0 + LBNE LB68F CONVERT FPA0+3 TO A STRING + STA STRDES SET LENGTH OF STRING = 0 IF NO KEY DOWN + JMP LB69B PUT A NULL STRING ONTO THE STRING STACK + +* MOVE ACCB BYTES FROM (X) TO (U) +LA59A LDA ,X+ GET BYTE FROM X + STA ,U+ STORE IT AT U + DECB MOVED ALL BYTES? + BNE LA59A NO +LA5A1 RTS + +LA5C4 RTS + +** THIS ROUTINE WILL SCAN OFF THE FILE NAME FROM A BASIC LINE +** AND RETURN A SYNTAX ERROR IF THERE ARE ANY CHARACTERS +** FOLLOWING THE END OF THE NAME +LA5C7 JSR GETCCH GET CURRENT INPUT CHAR FROM BASIC LINE +LA5C9 BEQ LA5C4 RETURN IF END OF LINE + JMP LB277 SYNTAX ERROR IF ANY MORE CHARACTERS +* IRQ SERVICE +BIRQSV +LA9C5 RTI RETURN FROM INTERRUPT + +* SET CARRY IF NUMERIC - RETURN WITH +* ZERO FLAG SET IF ACCA = 0 OR 3A(:) - END +* OF BASIC LINE OR SUB LINE +BROMHK CMPA #'9+1 IS THIS CHARACTER >=(ASCII 9)+1? + BHS LAA28 BRANCH IF > 9; Z SET IF = COLON + CMPA #SPACE SPACE? + BNE LAA24 NO - SET CARRY IF NUMERIC + JMP GETNCH IF SPACE, GET NECT CHAR (IGNORE SPACES) +LAA24 SUBA #'0 * SET CARRY IF + SUBA #-'0 * CHARACTER > ASCII 0 +LAA28 RTS + +* DISPATCH TABLE FOR SECONDARY FUNCTIONS +* TOKENS ARE PRECEEDED BY $FF +* FIRST SET ALWAYS HAS ONE PARAMETER +FUNC_TAB +LAA29 FDB SGN SGN + FDB INT INT + FDB ABS ABS + FDB USRJMP USR +TOK_USR EQU *-FUNC_TAB/2+$7F +TOK_FF_USR EQU *-FUNC_TAB/2+$FF7F + FDB RND RND + FDB SIN SIN + FDB PEEK PEEK + FDB LEN LEN + FDB STR STR$ + FDB VAL VAL + FDB ASC ASC + FDB CHR CHR$ + FDB ATN ATN + FDB COS COS + FDB TAN TAN + FDB EXP EXP + FDB FIX FIX + FDB LOG LOG + FDB POS POS + FDB SQR SQR + FDB HEXDOL HEX$ +* LEFT, RIGHT AND MID ARE TREATED SEPARATELY + FDB LEFT LEFT$ +TOK_LEFT EQU *-FUNC_TAB/2+$7F + FDB RIGHT RIGHT$ + FDB MID MID$ +TOK_MID EQU *-FUNC_TAB/2+$7F +* REMAINING FUNCTIONS + FDB INKEY INKEY$ +TOK_INKEY EQU *-FUNC_TAB/2+$7F + FDB MEM MEM + FDB VARPT VARPTR + FDB INSTR INSTR + FDB STRING STRING$ +NUM_SEC_FNS EQU *-FUNC_TAB/2 + +* THIS TABLE CONTAINS PRECEDENCES AND DISPATCH ADDRESSES FOR ARITHMETIC +* AND LOGICAL OPERATORS - THE NEGATION OPERATORS DO NOT ACT ON TWO OPERANDS +* S0 THEY ARE NOT LISTED IN THIS TABLE. THEY ARE TREATED SEPARATELY IN THE +* EXPRESSION EVALUATION ROUTINE. THEY ARE: +* UNARY NEGATION (-), PRECEDENCE &7D AND LOGICAL NEGATION (NOT), PRECEDENCE $5A +* THE RELATIONAL OPERATORS < > = ARE ALSO NOT LISTED, PRECEDENCE $64. +* A PRECEDENCE VALUE OF ZERO INDICATES END OF EXPRESSION OR PARENTHESES +* +LAA51 FCB $79 + FDB LB9C5 + + FCB $79 + FDB LB9BC - + FCB $7B + FDB LBACC * + FCB $7B + FDB LBB91 / + FCB $7F + FDB L8489 EXPONENTIATION + FCB $50 + FDB LB2D5 AND + FCB $46 + FDB LB2D4 OR + +* THIS IS THE RESERVED WORD TABLE +* FIRST PART OF THE TABLE CONTAINS EXECUTABLE COMMANDS +LAA66 FCC "FO" 80 + FCB $80+'R' + FCC "G" 81 + FCB $80+'O' +TOK_GO EQU $81 + FCC "RE" 82 + FCB $80+'M' + FCB ''+$80 83 + FCC "ELS" 84 + FCB $80+'E' + FCC "I" 85 + FCB $80+'F' + FCC "DAT" 86 + FCB $80+'A' + FCC "PRIN" 87 + FCB $80+'T' + FCC "O" 88 + FCB $80+'N' + FCC "INPU" 89 + FCB $80+'T' + FCC "EN" 8A + FCB $80+'D' + FCC "NEX" 8B + FCB $80+'T' + FCC "DI" 8C + FCB $80+'M' + FCC "REA" 8D + FCB $80+'D' + FCC "RU" 8E + FCB $80+'N' + FCC "RESTOR" 8F + FCB $80+'E' + FCC "RETUR" 90 + FCB $80+'N' + FCC "STO" 91 + FCB $80+'P' + FCC "POK" 92 + FCB $80+'E' + FCC "CON" 93 + FCB $80+'T' + FCC "LIS" 94 + FCB $80+'T' + FCC "CLEA" 95 + FCB $80+'R' + FCC "NE" 96 + FCB $80+'W' + FCC "EXE" 97 + FCB $80+'C' + FCC "TRO" 98 + FCB $80+'N' + FCC "TROF" 99 + FCB $80+'F' + FCC "DE" 9A + FCB $80+'L' + FCC "DE" 9B + FCB $80+'F' + FCC "LIN" 9C + FCB $80+'E' + FCC "RENU" 9D + FCB $80+'M' + FCC "EDI" 9E + FCB $80+'T' +* END OF EXECUTABLE COMMANDS. THE REMAINDER OF THE TABLE ARE NON-EXECUTABLE TOKENS + FCC "TAB" 9F + FCB $80+'(' +TOK_TAB EQU $9F + FCC "T" A0 + FCB $80+'O' +TOK_TO EQU $A0 + FCC "SU" A1 + FCB $80+'B' +TOK_SUB EQU $A1 + FCC "THE" A2 + FCB $80+'N' +TOK_THEN EQU $A2 + FCC "NO" A3 + FCB $80+'T' +TOK_NOT EQU $A3 + FCC "STE" A4 + FCB $80+'P' +TOK_STEP EQU $A4 + FCC "OF" A5 + FCB $80+'F' + FCB '++$80 A6 +TOK_PLUS EQU $A6 + FCB '-+$80 A7 +TOK_MINUS EQU $A7 + FCB '*+$80 A8 + FCB '/+$80 A9 + FCB '^+$80 AA + FCC "AN" AB + FCB $80+'D' + FCC "O" AC + FCB $80+'R' + FCB '>+$80 AD +TOK_GREATER EQU $AD + FCB '=+$80 AE +TOK_EQUALS EQU $AE + FCB '<+$80 AF + FCC "F" B0 + FCB $80+'N' +TOK_FN EQU $B0 + FCC "USIN" B1 + FCB $80+'G' +TOK_USING EQU $B1 +* + +* FIRST SET ALWAYS HAS ONE PARAMETER +LAB1A FCC "SG" 80 + FCB $80+'N' + FCC "IN" 81 + FCB $80+'T' + FCC "AB" 82 + FCB $80+'S' + FCC "US" 83 + FCB $80+'R' + FCC "RN" 84 + FCB $80+'D' + FCC "SI" 85 + FCB $80+'N' + FCC "PEE" 86 + FCB $80+'K' + FCC "LE" 87 + FCB $80+'N' + FCC "STR" 88 + FCB $80+'$' + FCC "VA" 89 + FCB $80+'L' + FCC "AS" 8A + FCB $80+'C' + FCC "CHR" 8B + FCB $80+'$' + FCC "AT" 8C + FCB $80+'N' + FCC "CO" 8D + FCB $80+'S' + FCC "TA" 8E + FCB $80+'N' + FCC "EX" 8F + FCB $80+'P' + FCC "FI" 90 + FCB $80+'X' + FCC "LO" 91 + FCB $80+'G' + FCC "PO" 92 + FCB $80+'S' + FCC "SQ" 93 + FCB $80+'R' + FCC "HEX" 94 + FCB $80+'$' +* LEFT, RIGHT AND MID ARE TREATED SEPARATELY + FCC "LEFT" 95 + FCB $80+'$' + FCC "RIGHT" 96 + FCB $80+'$' + FCC "MID" 97 + FCB $80+'$' +* REMAINING FUNCTIONS + FCC "INKEY" 98 + FCB $80+'$' + FCC "ME" 99 + FCB $80+'M' + FCC "VARPT" 9A + FCB $80+'R' + FCC "INST" 9B + FCB $80+'R' + FCC "STRING" 9C + FCB $80+'$' + +* +* DISPATCH TABLE FOR COMMANDS TOKEN # +CMD_TAB +LAB67 FDB FOR 80 + FDB GO 81 + FDB REM 82 +TOK_REM EQU *-CMD_TAB/2+$7F + FDB REM 83 (') +TOK_SNGL_Q EQU *-CMD_TAB/2+$7F + FDB REM 84 (ELSE) +TOK_ELSE EQU *-CMD_TAB/2+$7F + FDB IF 85 +TOK_IF EQU *-CMD_TAB/2+$7F + FDB DATA 86 +TOK_DATA EQU *-CMD_TAB/2+$7F + FDB PRINT 87 +TOK_PRINT EQU *-CMD_TAB/2+$7F + FDB ON 88 + FDB INPUT 89 +TOK_INPUT EQU *-CMD_TAB/2+$7F + FDB END 8A + FDB NEXT 8B + FDB DIM 8C + FDB READ 8D + FDB RUN 8E + FDB RESTOR 8F + FDB RETURN 90 + FDB STOP 91 + FDB POKE 92 + FDB CONT 93 + FDB LIST 94 + FDB CLEAR 95 + FDB NEW 96 + FDB EXEC 97 + FDB TRON 98 + FDB TROFF 99 + FDB DEL 9A + FDB DEF 9B + FDB LINE 9C + FDB RENUM 9D + FDB EDIT 9E +TOK_HIGH_EXEC EQU *-CMD_TAB/2+$7F + +* ERROR MESSAGES AND THEIR NUMBERS AS USED INTERNALLY +LABAF FCC "NF" 0 NEXT WITHOUT FOR + FCC "SN" 1 SYNTAX ERROR + FCC "RG" 2 RETURN WITHOUT GOSUB + FCC "OD" 3 OUT OF DATA + FCC "FC" 4 ILLEGAL FUNCTION CALL + FCC "OV" 5 OVERFLOW + FCC "OM" 6 OUT OF MEMORY + FCC "UL" 7 UNDEFINED LINE NUMBER + FCC "BS" 8 BAD SUBSCRIPT + FCC "DD" 9 REDIMENSIONED ARRAY + FCC "/0" 10 DIVISION BY ZERO + FCC "ID" 11 ILLEGAL DIRECT STATEMENT + FCC "TM" 12 TYPE MISMATCH + FCC "OS" 13 OUT OF STRING SPACE + FCC "LS" 14 STRING TOO LONG + FCC "ST" 15 STRING FORMULA TOO COMPLEX + FCC "CN" 16 CAN'T CONTINUE + FCC "FD" 17 BAD FILE DATA + FCC "AO" 18 FILE ALREADY OPEN + FCC "DN" 19 DEVICE NUMBER ERROR + FCC "IO" 20 I/O ERROR + FCC "FM" 21 BAD FILE MODE + FCC "NO" 22 FILE NOT OPEN + FCC "IE" 23 INPUT PAST END OF FILE + FCC "DS" 24 DIRECT STATEMENT IN FILE +* ADDITIONAL ERROR MESSAGES ADDED BY EXTENDED BASIC +L890B FCC "UF" 25 UNDEFINED FUNCTION (FN) CALL +L890D FCC "NE" 26 FILE NOT FOUND + +LABE1 FCC " ERROR" + FCB $00 +LABE8 FCC " IN " + FCB $00 +LABED FCB CR +LABEE FCC "OK" + FCB CR,$00 +LABF2 FCB CR + FCC "BREAK" + FCB $00 + +* SEARCH THE STACK FOR ‘GOSUB/RETURN’ OR ‘FOR/NEXT’ DATA. +* THE ‘FOR/NEXT’ INDEX VARIABLE DESCRIPTOR ADDRESS BEING +* SOUGHT IS STORED IN VARDES. EACH BLOCK OF FOR/NEXT DATA IS 18 +* BYTES WITH A $80 LEADER BYTE AND THE GOSUB/RETURN DATA IS 5 BYTES +* WITH AN $A6 LEADER BYTE. THE FIRST NON "FOR/NEXT" DATA +* IS CONSIDERED ‘GOSUB/RETURN’ +LABF9 LEAX 4,S POINT X TO 3RD ADDRESS ON STACK - IGNORE THE +* FIRST TWO RETURN ADDRESSES ON THE STACK +LABFB LDB #18 18 BYTES SAVED ON STACK FOR EACH ‘FOR’ LOOP + STX TEMPTR SAVE POINTER + LDA ,X GET 1ST BYTE + SUBA #$80 * CHECK FOR TYPE OF STACK JUMP FOUND + BNE LAC1A * BRANCH IF NOT ‘FOR/NEXT’ + LDX 1,X = GET INDEX VARIABLE DESCRIPTOR + STX TMPTR1 = POINTER AND SAVE IT IN TMPTR1 + LDX VARDES GET INDEX VARIABLE BEING SEARCHED FOR + BEQ LAC16 BRANCH IF DEFAULT INDEX VARIABLE - USE THE +* FIRST ‘FOR/NEXT’ DATA FOUND ON STACK +* IF NO INDEX VARIABLE AFTER ‘NEXT’ + CMPX TMPTR1 DOES THE STACK INDEX MATCH THE ONE +* BEING SEARCHED FOR? + BEQ LAC1A YES + LDX TEMPTR * RESTORE INITIAL POINTER, ADD + ABX * 18 TO IT AND LOOK FOR + BRA LABFB * NEXT BLOCK OF DATA +LAC16 LDX TMPTR1 = GET 1ST INDEX VARIABLE FOUND AND + STX VARDES = SAVE AS ‘NEXT’ INDEX +LAC1A LDX TEMPTR POINT X TO START OF ‘FOR/NEXT’ DATA + TSTA SET ZERO FLAG IF ‘FOR/NEXT’ DATA + RTS +* CHECK FOR MEMORY SPACE FOR NEW TOP OF +* ARRAYS AND MOVE ARRAYS TO NEW LOCATION +LAC1E BSR LAC37 ACCD = NEW BOTTOM OF FREE RAM - IS THERE +* ROOM FOR THE STACK? +* MOVE BYTES FROM V43(X) TO V41(U) UNTIL (X) = V47 AND +* SAVE FINAL VALUE OF U IN V45 +LAC20 LDU V41 POINT U TO DESTINATION ADDRESS (V41) + LEAU 1,U ADD ONE TO U - COMPENSATE FOR FIRST PSHU + LDX V43 POINT X TO SOURCE ADDRESS (V43) + LEAX 1,X ADD ONE - COMPENSATE FOR FIRST LDA ,X +LAC28 LDA ,-X GRAB A BYTE FROM SOURCE + PSHU A MOVE IT TO DESTINATION + CMPX V47 DONE? + BNE LAC28 NO - KEEP MOVING BYTES + STU V45 SAVE FINAL DESTINATION ADDRESS +LAC32 RTS +* CHECK TO SEE IF THERE IS ROOM TO STORE 2*ACCB +* BYTES IN FREE RAM - OM ERROR IF NOT +LAC33 CLRA * ACCD CONTAINS NUMBER OF EXTRA + ASLB * BYTES TO PUT ON STACK + ADDD ARYEND END OF PROGRAM AND VARIABLES +LAC37 ADDD #STKBUF ADD STACK BUFFER - ROOM FOR STACK? + BCS LAC44 BRANCH IF GREATER THAN $FFFF + STS BOTSTK CURRENT NEW BOTTOM OF STACK STACK POINTER + CMPD BOTSTK ARE WE GOING TO BE BELOW STACK? + BCS LAC32 YES - NO ERROR +LAC44 LDB #6*2 OUT OF MEMORY ERROR + +* ERROR SERVICING ROUTINE +LAC46 JSR LAD33 RESET STACK, STRING STACK, CONTINUE POINTER + JSR LB95C SEND A CR TO SCREEN + JSR LB9AF SEND A ‘?‘ TO SCREEN + LDX #LABAF POINT TO ERROR TABLE +LAC60 ABX ADD MESSAGE NUMBER OFFSET + BSR LACA0 * GET TWO CHARACTERS FROM X AND + BSR LACA0 * SEND TO CONSOLE OUT (SCREEN) + LDX #LABE1-1 POINT TO "ERROR" MESSAGE +LAC68 JSR LB99C PRINT MESSAGE POINTED TO BY X + LDA CURLIN GET CURRENT LINE NUMBER (CURL IN) + INCA TEST FOR DIRECT MODE + BEQ LAC73 BRANCH IF DIRECT MODE + JSR LBDC5 PRINT ‘IN ****‘ + +* THIS IS THE MAIN LOOP OF BASIC WHEN IN DIRECT MODE +LAC73 JSR LB95C MOVE CURSOR TO START OF LINE + LDX #LABED POINT X TO ‘OK’, CR MESSAGE + JSR LB99C PRINT ‘OK’, CR +LAC7C JSR LA390 GO GET AN INPUT LINE + LDU #$FFFF THE LINE NUMBER FOR DIRECT MODE IS $FFFF + STU CURLIN SAVE IT IN CURLIN + BCS LAC7C BRANCH IF LINE INPUT TERMINATED BY BREAK + STX CHARAD SAVE (X) AS CURRENT INPUT POINTER - THIS WILL +* ENABLE THE ‘LIVE KEYBOARD’ (DIRECT) MODE. THE +* LINE JUST ENTERED WILL BE INTERPRETED + JSR GETNCH GET NEXT CHARACTER FROM BASIC + BEQ LAC7C NO LINE INPUT - GET ANOTHER LINE + BCS LACA5 BRANCH IF NUMER1C - THERE WAS A LINE NUMBER BEFORE +* THE STATEMENT ENTERED, SO THIS STATEMENT +* WILL BE MERGED INTO THE BASIC PROGRAM + JSR LB821 GO CRUNCH LINE + JMP LADC0 GO EXECUTE THE STATEMENT (LIVE KEYBOARD) +* +LACA0 LDA ,X+ GET A CHARACTER + JMP LB9B1 SEND TO CONSOLE OUT +* TAKE A LINE FROM THE LINE INPUT BUFFER +* AND INSERT IT INTO THE BASIC PROGRAM +LACA5 JSR LAF67 CONVERT LINE NUMBER TO BINARY +LACA8 LDX BINVAL GET CONVERTED LINE NUMBER + STX LINHDR STORE IT IN LINE INPUT HEADER + JSR LB821 GO CRUNCH THE LINE + STB TMPLOC SAVE LINE LENGTH + BSR LAD01 FIND OUT WHERE TO INSERT LINE + BCS LACC8 BRANCH IF LINE NUMBER DOES NOT ALREADY EXIST + LDD V47 GET ABSOLUTE ADDRESS OF LINE NUMBER + SUBD ,X SUBTRACT ADDRESS OF NEXT LINE NUMBER + ADDD VARTAB * ADD TO CURRENT END OF PROGRAM - THIS WILL REMOVE + STD VARTAB * THE LENGTH OF THIS LINE NUMBER FROM THE PROGRAM + LDU ,X POINT U TO ADDRESS OF NEXT LINE NUMBER +* DELETE OLD LINE FROM BASIC PROGRAM +LACC0 PULU A GET A BYTE FROM WHAT’S LEFT OF PROGRAM + STA ,X+ MOVE IT DOWN + CMPX VARTAB COMPARE TO END OF BASIC PROGRAM + BNE LACC0 BRANCH IF NOT AT END +LACC8 LDA LINBUF * CHECK TO SEE IF THERE IS A LINE IN + BEQ LACE9 * THE BUFFER AND BRANCH IF NONE + LDD VARTAB = SAVE CURRENT END OF + STD V43 = PROGRAM IN V43 + ADDB TMPLOC * ADD LENGTH OF CRUNCHED LINE, + ADCA #0 * PROPOGATE CARRY AND SAVE NEW END + STD V41 * OF PROGRAM IN V41 + JSR LAC1E = MAKE SURE THERE’S ENOUGH RAM FOR THIS +* = LINE & MAKE A HOLE IN BASIC FOR NEW LINE + LDU #LINHDR-2 POINT U TO LINE TO BE INSERTED +LACDD PULU A GET A BYTE FROM NEW LINE + STA ,X+ INSERT IT IN PROGRAM + CMPX V45 * COMPARE TO ADDRESS OF END OF INSERTED + BNE LACDD * LINE AND BRANCH IF NOT DONE + LDX V41 = GET AND SAVE + STX VARTAB = END OF PROGRAM +LACE9 BSR LAD21 RESET INPUT POINTER, CLEAR VARIABLES, INITIALIZE + BSR LACEF ADJUST START OF NEXT LINE ADDRESSES + BRA LAC7C REENTER BASIC’S INPUT LOOP +* COMPUTE THE START OF NEXT LINE ADDRESSES FOR THE BASIC PROGRAM +LACEF LDX TXTTAB POINT X TO START OF PROGRAM +LACF1 LDD ,X GET ADDRESS OF NEXT LINE + BEQ LAD16 RETURN IF END OF PROGRAM + LEAU 4,X POINT U TO START OF BASIC TEXT IN LINE +LACF7 LDA ,U+ * SKIP THROUGH THE LINE UNTIL A + BNE LACF7 * ZERO (END OF LINE) IS FOUND + STU ,X SAVE THE NEW START OF NEXT LINE ADDRESS + LDX ,X POINT X TO START OF NEXT LINE + BRA LACF1 KEEP GOING +* +* FIND A LINE NUMBER IN THE BASIC PROGRAM +* RETURN WITH CARRY SET IF NO MATCH FOUND +LAD01 LDD BINVAL GET THE LINE NUMBER TO FIND + LDX TXTTAB BEGINNING OF PROGRAM +LAD05 LDU ,X GET ADDRESS OF NEXT LINE NUMBER + BEQ LAD12 BRANCH IF END OF PROG + CMPD 2,X IS IT A MATCH? + BLS LAD14 CARRY SET IF LOWER; CARRY CLEAR IF MATCH + LDX ,X X = ADDRESS OF NEXT LINE + BRA LAD05 KEEP LOOPING FOR LINE NUMBER +LAD12 ORCC #1 SET CARRY FLAG +LAD14 STX V47 SAVE MATCH LINE NUMBER OR NUMBER OF LINE JUST AFTER +* WHERE IT SHOULD HAVE BEEN +LAD16 RTS + +* NEW +NEW BNE LAD14 BRANCH IF ARGUMENT GIVEN +LAD19 LDX TXTTAB GET START OF BASIC + CLR ,X+ * PUT 2 ZERO BYTES THERE - ERASE + CLR ,X+ * THE BASIC PROGRAM + STX VARTAB AND THE NEXT ADDRESS IS NOW THE END OF PROGRAM +LAD21 LDX TXTTAB GET START OF BASIC + JSR LAEBB PUT INPUT POINTER ONE BEFORE START OF BASIC +* ERASE ALL VARIABLES +LAD26 LDX MEMSIZ * RESET START OF STRING VARIABLES + STX STRTAB * TO TOP OF STRING SPACE + JSR RESTOR RESET ‘DATA’ POINTER TO START OF BASIC + LDX VARTAB * GET START OF VARIABLES AND USE IT + STX ARYTAB * TO RESET START OF ARRAYS + STX ARYEND RESET END OF ARRAYS +LAD33 LDX #STRSTK * RESET STRING STACK POINTER TO + STX TEMPPT * BOTTOM OF STRING STACK + LDX ,S GET RETURN ADDRESS OFF STACK + LDS FRETOP RESTORE STACK POINTER + CLR ,-S PUT A ZERO BYTE ON STACK - TO CLEAR ANY RETURN OF +* FOR/NEXT DATA FROM THE STACK + CLR OLDPTR RESET ‘CONT’ ADDRESS SO YOU + CLR OLDPTR+1 ‘CAN’T CONTINUE’ + CLR ARYDIS CLEAR THE ARRAY DISABLE FLAG + JMP ,X RETURN TO CALLING ROUTINE - THIS IS NECESSARY +* SINCE THE STACK WAS RESET +* +* FOR +* +* THE FOR COMMAND WILL STORE 18 BYTES ON THE STACK FOR +* EACH FOR-NEXT LOOP WHICH IS BEING PROCESSED. THESE +* BYTES ARE DEFINED AS FOLLOWS: 0- $80 (FOR FLAG); +* 1,2=INDEX VARIABLE DESCRIPTOR POINTER; 3-7=FP VALUE OF STEP; +* 8=STEP DIRECTION: $FF IF NEGATIVE; 0 IF ZERO; 1 IF POSITIVE; +* 9-13=FP VALUE OF ‘TO’ PARAMETER; +* 14,15=CURRENT LINE NUMBER; 16,17=RAM ADDRESS OF THE END +* OF THE LINE CONTAINING THE ‘FOR’ STATEMENT +FOR LDA #$80 * SAVE THE DISABLE ARRAY FLAG IN VO8 + STA ARYDIS * DO NOT ALLOW THE INDEX VARIABLE TO BE AN ARRAY + JSR LET SET INDEX VARIABLE TO INITIAL VALUE + JSR LABF9 SEARCH THE STACK FOR ‘FOR/NEXT’ DATA + LEAS 2,S PURGE RETURN ADDRESS OFF OF THE STACK + BNE LAD59 BRANCH IF INDEX VARIABLE NOT ALREADY BEING USED + LDX TEMPTR GET (ADDRESS + 18) OF MATCHED ‘FOR/NEXT’ DATA + LEAS B,X MOVE THE STACK POINTER TO THE BEGINNING OF THE +* MATCHED ‘FOR/NEXT’ DATA SO THE NEW DATA WILL +* OVERLAY THE OLD DATA. THIS WILL ALSO DESTROY +* ALL OF THE ‘RETURN’ AND ‘FOR/NEXT’ DATA BELOW +* THIS POINT ON THE STACK +LAD59 LDB #$09 * CHECK FOR ROOM FOR 18 BYTES + JSR LAC33 * IN FREE RAM + JSR LAEE8 GET ADDR OF END OF SUBLINE IN X + LDD CURLIN GET CURRENT LINE NUMBER + PSHS X,B,A SAVE LINE ADDR AND LINE NUMBER ON STACK + LDB #TOK_TO TOKEN FOR ‘TO’ + JSR LB26F SYNTAX CHECK FOR ‘TO’ + JSR LB143 ‘TM’ ERROR IF INDEX VARIABLE SET TO STRING + JSR LB141 EVALUATE EXPRESSION +* + LDB FP0SGN GET FPA0 MANTISSA SIGN + ORB #$7F FORM A MASK TO SAVE DATA BITS OF HIGH ORDER MANTISSA + ANDB FPA0 PUT THE MANTISSA SIGN IN BIT 7 OF HIGH ORDER MANTISSA + STB FPA0 SAVE THE PACKED HIGH ORDER MANTISSA + LDY #LAD7F LOAD FOLLOWING ADDRESS INTO Y AS A RETURN + JMP LB1EA ADDRESS - PUSH FPA0 ONTO THE STACK +LAD7F LDX #LBAC5 POINT X TO FLOATING POINT NUMBER 1.0 (DEFAULT STEP VALUE) + JSR LBC14 MOVE (X) TO FPA0 + JSR GETCCH GET CURRENT INPUT CHARACTER + CMPA #TOK_STEP STEP TOKEN + BNE LAD90 BRANCH IF NO ‘STEP’ VALUE + JSR GETNCH GET A CHARACTER FROM BASIC + JSR LB141 EVALUATE NUMERIC EXPRESSION +LAD90 JSR LBC6D CHECK STATUS OF FPA0 + JSR LB1E6 SAVE STATUS AND FPA0 ON THE STACK + LDD VARDES * GET DESCRIPTOR POINTER FOR THE ‘STEP’ + PSHS B,A * VARIABLE AND SAVE IT ON THE STACK + LDA #$80 = GET THE ‘FOR’ FLAG AND + PSHS A = SAVE IT ON THE STACK +* +* MAIN COMMAND INTERPRETATION LOOP +LAD9E ANDCC #$AF ENABLE IRQ,FIRQ + BSR LADEB CHECK FOR KEYBOARD BREAK + LDX CHARAD GET BASIC’S INPUT POINTER + STX TINPTR SAVE IT + LDA ,X+ GET CURRENT INPUT CHAR & MOVE POINTER + BEQ LADB4 BRANCH IF END OF LINE + CMPA #': CHECK FOR LINE SEPARATOR + BEQ LADC0 BRANCH IF COLON +LADB1 JMP LB277 ‘SYNTAX ERROR’-IF NOT LINE SEPARATOR +LADB4 LDA ,X++ GET MS BYTE OF ADDRESS OF NEXT BASIC LINE + STA ENDFLG SAVE IN STOP/END FLAG - CAUSE A STOP IF +* NEXT LINE ADDRESS IS < $8000; CAUSE +* AN END IF ADDRESS > $8000 + BEQ LAE15 BRANCH TO ‘STOP’ - END OF PROGRAM + LDD ,X+ GET CURRENT LINE NUMBER + STD CURLIN SAVE IN CURLIN + STX CHARAD SAVE ADDRESS OF FIRST BYTE OF LINE +* EXTENDED BASIC TRACE + LDA TRCFLG TEST THE TRACE FLAG + BEQ LADC0 BRANCH IF TRACE OFF + LDA #$5B RIGHT HAND MARKER FOR TRON LINE NUMBER + JSR PUTCHR OUTPUT A CHARACTER +* END OF EXTENDED BASIC TRACE +LADC0 JSR GETNCH GET A CHARACTER FROM BASIC + BSR LADC6 GO PROCESS COMMAND + BRA LAD9E GO BACK TO MAIN LOOP +LADC6 BEQ LADEA RETURN IF END OF LINE (RTS - was BEQ LAE40) + TSTA CHECK FOR TOKEN - BIT 7 SET (NEGATIVE) + LBPL LET BRANCH IF NOT A TOKEN - GO DO A ‘LET’ WHICH +* IS THE ‘DEFAULT’ TOKEN FOR MICROSOFT BASIC + CMPA #$FF SECONDARY TOKEN + BEQ SECTOK + CMPA #TOK_HIGH_EXEC SKIPF TOKEN - HIGHEST EXECUTABLE COMMAND IN BASIC + BHI LADB1 ‘SYNTAX ERROR’ IF NON-EXECUTABLE TOKEN + LDX COMVEC+3 GET ADDRESS OF BASIC’S COMMAND TABLE +LADD4 ASLA X2 (2 BYTE/JUMP ADDRESS) & DISCARD BIT 7 + TFR A,B SAVE COMMAND OFFSET IN ACCB + ABX NON X POINTS TO COMMAND JUMP ADDR + JSR GETNCH GET AN INPUT CHAR +* +* HERE IS WHERE WE BRANCH TO DO A ‘COMMAND’ + JMP [,X] GO DO A COMMAND +SECTOK +* THE ONLY SECONDARY TOKEN THAT CAN ALSO BE AN EXECUTABLE IS +* THE MID$ REPLACEMENT STATEMENT. SO SPECIAL-CASE CHECK DONE HERE + JSR GETNCH GET AN INPUT CHAR + CMPA #TOK_MID TOKEN FOR "MID$" + LBEQ L86D6 PROCESS MID$ REPLACEMENT + JMP LB277 SYNTAX ERROR + +* +* RESTORE +RESTOR LDX TXTTAB BEGINNING OF PROGRAM ADDRESS + LEAX -1,X MOVE TO ONE BYTE BEFORE PROGRAM +LADE8 STX DATPTR SAVE NEW DATA POINTER +LADEA RTS +* +* BREAK CHECK +LADEB JSR LA1C1 GET A KEYSTROKE ENTRY + BEQ LADFA RETURN IF NO INPUT +LADF0 CMPA #3 CONTROL C? (BREAK) + BEQ STOP YES + CMPA #$13 CONTROL S? (PAUSE) + BEQ LADFB YES + STA IKEYIM SAVE KEYSTROKE IN INKEY IMAGE +LADFA RTS +LADFB JSR KEYIN GET A KEY + BEQ LADFB BRANCH IF NO KEY DOWN + BRA LADF0 CONTINUE - DO A BREAK CHECK +* +* END +END JSR GETCCH GET CURRENT INPUT CHAR + BRA LAE0B +* +* STOP +STOP ORCC #$01 SET CARRY FLAG +LAE0B BNE LAE40 BRANCH IF ARGUMENT EXISTS + LDX CHARAD * SAVE CURRENT POSITION OF + STX TINPTR * BASIC’S INPUT POINTER +LAE11 ROR ENDFLG ROTATE CARRY INTO BIT 7 OF STOP/END FLAG + LEAS 2,S PURGE RETURN ADDRESS OFF STACK +LAE15 LDX CURLIN GET CURRENT LINE NUMBER + CMPX #$FFFF DIRECT MODE? + BEQ LAE22 YES + STX OLDTXT SAVE CURRENT LINE NUMBER + LDX TINPTR * GET AND SAVE CURRENT POSITION + STX OLDPTR * OF BASIC’S INPUT POINTER +LAE22 + LDX #LABF2-1 POINT TO CR, ‘BREAK’ MESSAGE + TST ENDFLG CHECK STOP/END FLAG + LBPL LAC73 BRANCH TO MAIN LOOP OF BASIC IF END + JMP LAC68 PRINT ‘BREAK AT ####’ AND GO TO +* BASIC’S MAIN LOOP IF ‘STOP’ + +* CONT +CONT BNE LAE40 RETURN IF ARGUMENT GIVEN + LDB #2*16 ‘CAN’T CONTINUE’ ERROR + LDX OLDPTR GET CONTINUE ADDRESS (INPUT POINTER) + LBEQ LAC46 ‘CN’ ERROR IF CONTINUE ADDRESS = 0 + STX CHARAD RESET BASIC’S INPUT POINTER + LDX OLDTXT GET LINE NUMBER + STX CURLIN RESET CURRENT LINE NUMBER +LAE40 RTS +* +* CLEAR +CLEAR BEQ LAE6F BRANCH IF NO ARGUMENT + JSR LB3E6 EVALUATE ARGUMENT + PSHS B,A SAVE AMOUNT OF STRING SPACE ON STACK + LDX MEMSIZ GET CURRENT TOP OF CLEARED SPACE + JSR GETCCH GET CURRENT INPUT CHARACTER + BEQ LAE5A BRANCH IF NO NEW TOP OF CLEARED SPACE + JSR LB26D SYNTAX CHECK FOR COMMA + JSR LB73D EVALUATE EXPRESSlON; RETURN VALUE IN X + LEAX -1,X X = TOP OF CLEARED SPACE + CMPX TOPRAM COMPARE TO TOP OF RAM + BHI LAE72 ‘OM’ ERROR IF > TOP OF RAM +LAE5A TFR X,D ACCD = TOP OF CLEARED SPACE + SUBD ,S++ SUBTRACT OUT AMOUNT OF CLEARED SPACE + BCS LAE72 ‘OM’ ERROR IF FREE MEM < 0 + TFR D,U U = BOTTOM OF CLEARED SPACE + SUBD #STKBUF SUBTRACT OUT STACK BUFFER + BCS LAE72 ‘OM’ ERROR IF FREE MEM < 0 + SUBD VARTAB SUBTRACT OUT START OF VARIABLES + BCS LAE72 ‘OM’ ERROR IF FREE MEM < 0 + STU FRETOP SAVE NEW BOTTOM OF CLEARED SPACE + STX MEMSIZ SAVE NEW TOP OF CLEARED SPACE +LAE6F JMP LAD26 ERASE ALL VARIABLES, INITIALIZE POINTERS, ETC +LAE72 JMP LAC44 ‘OM’ ERROR +* +* RUN +RUN JSR GETCCH * GET CURRENT INPUT CHARACTER + LBEQ LAD21 * IF NO LINE NUMBER + JSR LAD26 ERASE ALL VARIABLES + BRA LAE9F ‘GOTO’ THE RUN ADDRESS +* +* GO +GO TFR A,B SAVE INPUT CHARACTER IN ACCB +LAE88 JSR GETNCH GET A CHARACTER FROM BASIC + CMPB #TOK_TO ‘TO’ TOKEN + BEQ LAEA4 BRANCH IF GOTO + CMPB #TOK_SUB ‘SUB’ TOKEN + BNE LAED7 ‘SYNTAX ERROR’ IF NEITHER + LDB #3 =ROOM FOR 6 + JSR LAC33 =BYTES ON STACK? + LDU CHARAD * SAVE CURRENT BASIC INPUT POINTER, LINE + LDX CURLIN * NUMBER AND SUB TOKEN ON STACK + LDA #TOK_SUB * + PSHS U,X,A * +LAE9F BSR LAEA4 GO DO A ‘GOTO’ + JMP LAD9E JUMP BACK TO BASIC’S MAIN LOOP +* GOTO +LAEA4 JSR GETCCH GET CURRENT INPUT CHAR + JSR LAF67 GET LINE NUMBER TO BINARY IN BINVAL + BSR LAEEB ADVANCE BASIC’S POINTER TO END OF LINE + LEAX $01,X POINT TO START OF NEXT LINE + LDD BINVAL GET THE LINE NUMBER TO RUN + CMPD CURLIN COMPARE TO CURRENT LINE NUMBER + BHI LAEB6 IF REO’D LINE NUMBER IS > CURRENT LINE NUMBER, +* DON’T START LOOKING FROM +* START OF PROGRAM + LDX TXTTAB BEGINNING OF PROGRAM +LAEB6 JSR LAD05 GO FIND A LINE NUMBER + BCS LAED2 ‘UNDEFINED LINE NUMBER’ +LAEBB LEAX -1,X MOVE BACK TO JUST BEFORE START OF LINE + STX CHARAD RESET BASIC’S INPUT POINTER +LAEBF RTS +* +* RETURN +RETURN BNE LAEBF EXIT ROUTINE IF ARGUMENT GIVEN + LDA #$FF * PUT AN ILLEGAL VARIABLE NAME IN FIRST BYTE OF + STA VARDES * VARDES WHICH WILL CAUSE ‘FOR/NEXT’ DATA ON THE +* STACK TO BE IGNORED + JSR LABF9 CHECK FOR RETURN DATA ON THE STACK + TFR X,S RESET STACK POINTER - PURGE TWO RETURN ADDRESSES +* FROM THE STACK + CMPA #TOK_SUB-$80 SUB TOKEN - $80 + BEQ LAEDA BRANCH IF ‘RETURN’ FROM SUBROUTINE + LDB #2*2 ERROR #2 ‘RETURN WITHOUT GOSUB’ + FCB SKP2 SKIP TWO BYTES +LAED2 LDB #7*2 ERROR #7 ‘UNDEFINED LINE NUMBER’ + JMP LAC46 JUMP TO ERROR HANDLER +LAED7 JMP LB277 ‘SYNTAX ERROR’ +LAEDA PULS A,X,U * RESTORE VALUES OF CURRENT LINE NUMBER AND + STX CURLIN * BASIC’S INPUT POINTER FOR THIS SUBROUTINE + STU CHARAD * AND LOAD ACCA WITH SUB TOKEN ($A6) +* +* DATA +DATA BSR LAEE8 MOVE INPUT POINTER TO END OF SUBLINE OR LINE + FCB SKP2 SKIP 2 BYTES + +* REM, ELSE +ELSE +REM BSR LAEEB MOVE INPUT POINTER TO END OF LINE + STX CHARAD RESET BASIC’S INPUT POINTER +LAEE7 RTS +* ADVANCE INPUT POINTER TO END OF SUBLINE OR LINE +LAEE8 LDB #': COLON = SUBLINE TERMINATOR CHARACTER +LAEEA FCB SKP1LD SKPILD SKIP ONE BYTE; LDA #$5F +* ADVANCE BASIC’S INPUT POINTER TO END OF +* LINE - RETURN ADDRESS OF END OF LINE+1 IN X +LAEEB CLRB 0 = LINE TERMINATOR CHARACTER + STB CHARAC TEMP STORE PRIMARY TERMINATOR CHARACTER + CLRB 0 (END OF LINE) = ALTERNATE TERM. CHAR. + LDX CHARAD LOAD X W/BASIC’S INPUT POINTER +LAEF1 TFR B,A * CHANGE TERMINATOR CHARACTER + LDB CHARAC * FROM ACCB TO CHARAC - SAVE OLD TERMINATOR +* IN CHARAC + STA CHARAC SWAP PRIMARY AND SECONDARY TERMINATORS +LAEF7 LDA ,X GET NEXT INPUT CHARACTER + BEQ LAEE7 RETURN IF 0 (END OF LINE) + PSHS B SAVE TERMINATOR ON STACK + CMPA ,S+ COMPARE TO INPUT CHARACTER + BEQ LAEE7 RETURN IF EQUAL + LEAX 1,X MOVE POINTER UP ONE + CMPA #'" CHECK FOR DOUBLE QUOTES + BEQ LAEF1 BRANCH IF " - TOGGLE TERMINATOR CHARACTERS + INCA * CHECK FOR $FF AND BRANCH IF + BNE LAF0C * NOT SECONDARY TOKEN + LEAX 1,X MOVE INPUT POINTER 1 MORE IF SECONDARY +LAF0C CMPA #TOK_IF+1 TOKEN FOR IF? + BNE LAEF7 NO - GET ANOTHER INPUT CHARACTER + INC IFCTR INCREMENT IF COUNTER - KEEP TRACK OF HOW MANY +* ‘IF’ STATEMENTS ARE NESTED IN ONE LINE + BRA LAEF7 GET ANOTHER INPUT CHARACTER + +* IF +IF JSR LB141 EVALUATE NUMERIC EXPRESSION + JSR GETCCH GET CURRENT INPUT CHARACTER + CMPA #TOK_GO TOKEN FOR GO + BEQ LAF22 TREAT ‘GO’ THE SAME AS ‘THEN’ + LDB #TOK_THEN TOKEN FOR THEN + JSR LB26F DO A SYNTAX CHECK ON ACCB +LAF22 LDA FP0EXP CHECK FOR TRUE/FALSE - FALSE IF FPA0 EXPONENT = ZERO + BNE LAF39 BRANCH IF CONDITION TRUE + CLR IFCTR CLEAR FLAG - KEEP TRACK OF WHICH NESTED ELSE STATEMENT +* TO SEARCH FOR IN NESTED ‘IF’ LOOPS +LAF28 BSR DATA MOVE BASIC’S POINTER TO END OF SUBLINE + TSTA * CHECK TO SEE IF END OF LINE OR SUBLINE + BEQ LAEE7 * AND RETURN IF END OF LINE + JSR GETNCH GET AN INPUT CHARACTER FROM BASIC + CMPA #TOK_ELSE TOKEN FOR ELSE + BNE LAF28 IGNORE ALL DATA EXCEPT ‘ELSE’ UNTIL +* END OF LINE (ZERO BYTE) + DEC IFCTR CHECK TO SEE IF YOU MUST SEARCH ANOTHER SUBLINE + BPL LAF28 BRANCH TO SEARCH ANOTHER SUBLINE FOR ‘ELSE’ + JSR GETNCH GET AN INPUT CHARACTER FROM BASIC +LAF39 JSR GETCCH GET CURRENT INPUT CHARACTER + LBCS LAEA4 BRANCH TO ‘GOTO’ IF NUMERIC CHARACTER + JMP LADC6 RETURN TO MAIN INTERPRETATION LOOP + +* ON +ON JSR LB70B EVALUATE EXPRESSION + LDB #TOK_GO TOKEN FOR GO + JSR LB26F SYNTAX CHECK FOR GO + PSHS A SAVE NEW TOKEN (TO,SUB) + CMPA #TOK_SUB TOKEN FOR SUB? + BEQ LAF54 YES + CMPA #TOK_TO TOKEN FOR TO? +LAF52 BNE LAED7 ‘SYNTAX’ ERROR IF NOT ‘SUB’ OR ‘TO’ +LAF54 DEC FPA0+3 DECREMENT IS BYTE OF MANTISSA OF FPA0 - THIS +* IS THE ARGUMENT OF THE ‘ON’ STATEMENT + BNE LAF5D BRANCH IF NOT AT THE PROPER GOTO OR GOSUB LINE NUMBER + PULS B GET BACK THE TOKEN FOLLOWING ‘GO’ + JMP LAE88 GO DO A ‘GOTO’ OR ‘GOSUB’ +LAF5D JSR GETNCH GET A CHARACTER FROM BASIC + BSR LAF67 CONVERT BASIC LINE NUMBER TO BINARY + CMPA #', IS CHARACTER FOLLOWING LINE NUMBER A COMMA? + BEQ LAF54 YES + PULS B,PC IF NOT, FALL THROUGH TO NEXT COMMAND +LAF67 LDX ZERO DEFAULT LINE NUMBER OF ZERO + STX BINVAL SAVE IT IN BINVAL +* +* CONVERT LINE NUMBER TO BINARY - RETURN VALUE IN BINVAL +* +LAF6B BCC LAFCE RETURN IF NOT NUMERIC CHARACTER + SUBA #'0 MASK OFF ASCII + STA CHARAC SAVE DIGIT IN VO1 + LDD BINVAL GET ACCUMULATED LINE NUMBER VALUE + CMPA #24 LARGEST LINE NUMBER IS $F9FF (63999) - +* (24*256+255)*10+9 + BHI LAF52 ‘SYNTAX’ ERROR IF TOO BIG +* MULT ACCD X 10 + ASLB * + ROLA * TIMES 2 + ASLB = + ROLA = TIMES 4 + ADDD BINVAL ADD 1 = TIMES 5 + ASLB * + ROLA * TIMES 10 + ADDB CHARAC ADD NEXT DIGIT + ADCA #0 PROPAGATE CARRY + STD BINVAL SAVE NEW ACCUMULATED LINE NUMBER + JSR GETNCH GET NEXT CHARACTER FROM BASIC + BRA LAF6B LOOP- PROCESS NEXT DIGIT +* +* LET (EXBAS) +* EVALUATE A NON-TOKEN EXPRESSION +* TARGET = REPLACEMENT +LET JSR LB357 FIND TARGET VARIABLE DESCRIPTOR + STX VARDES SAVE DESCRIPTOR ADDRESS OF 1ST EXPRESSION + LDB #TOK_EQUALS TOKEN FOR "=" + JSR LB26F DO A SYNTAX CHECK FOR ‘=‘ + LDA VALTYP * GET VARIABLE TYPE AND + PSHS A * SAVE ON THE STACK + JSR LB156 EVALUATE EXPRESSION + PULS A * REGET VARIABLE TYPE OF 1ST EXPRESSION AND + RORA * SET CARRY IF STRING + JSR LB148 TYPE CHECK-TM ERROR IF VARIABLE TYPES ON +* BOTH SIDES OF EQUALS SIGN NOT THE SAME + LBEQ LBC33 GO PUT FPA0 INTO VARIABLE DESCRIPTOR IF NUMERIC +* MOVE A STRING WHOSE DESCRIPTOR IS LOCATED AT +* FPA0+2 INTO THE STRING SPACE. TRANSFER THE +* DESCRIPTOR ADDRESS TO THE ADDRESS IN VARDES +* DON’T MOVE THE STRING IF IT IS ALREADY IN THE +* STRING SPACE. REMOVE DESCRIPTOR FROM STRING +* STACK IF IT IS LAST ONE ON THE STACK +LAFA4 LDX FPA0+2 POINT X TO DESCRIPTOR OF REPLACEMENT STRING + LDD FRETOP LOAD ACCD WITH START OF STRING SPACE + CMPD 2,X IS THE STRING IN STRING SPACE? + BCC LAFBE BRANCH IF IT’S NOT IN THE STRING SPACE + CMPX VARTAB COMPARE DESCRIPTOR ADDRESS TO START OF VARIABLES + BCS LAFBE BRANCH IF DESCRIPTOR ADDRESS NOT IN VARIABLES +LAFB1 LDB ,X GET LENGTH OF REPLACEMENT STRING + JSR LB50D RESERVE ACCB BYTES OF STRING SPACE + LDX V4D GET DESCRIPTOR ADDRESS BACK + JSR LB643 MOVE STRING INTO STRING SPACE + LDX #STRDES POINT X TO TEMP STRING DESCRIPTOR ADDRESS +LAFBE STX V4D SAVE STRING DESCRIPTOR ADDRESS IN V4D + JSR LB675 REMOVE STRING DESCRIPTOR IF LAST ONE +* ON STRING STACK + LDU V4D POINT U TO REPLACEMENT DESCRIPTOR ADDRESS + LDX VARDES GET TARGET DESCRIPTOR ADDRESS + PULU A,B,Y GET LENGTH AND START OF REPLACEMENT STRING + STA ,X * SAVE STRING LENGTH AND START IN + STY 2,X * TARGET DESCRIPTOR LOCATION +LAFCE RTS + +LAFCF FCC "?REDO" ?REDO MESSAGE + FCB CR,$00 + +LAFD6 +LAFDC JMP LAC46 JMP TO ERROR HANDLER +LAFDF LDA INPFLG = GET THE INPUT FLAG AND BRANCH + BEQ LAFEA = IF ‘INPUT’ + LDX DATTXT * GET LINE NUMBER WHERE THE ERROR OCCURRED + STX CURLIN * AND USE IT AS THE CURRENT LINE NUMBER + JMP LB277 ‘SYNTAX ERROR’ +LAFEA LDX #LAFCF-1 * POINT X TO ‘?REDO’ AND PRINT + JSR LB99C * IT ON THE SCREEN + LDX TINPTR = GET THE SAVED ABSOLUTE ADDRESS OF + STX CHARAD = INPUT POINTER AND RESTORE IT + RTS +* +* INPUT +INPUT LDB #11*2 ‘ID’ ERROR + LDX CURLIN GET CURRENT LINE NUMBER + LEAX 1,X ADD ONE + BEQ LAFDC ‘ID’ ERROR BRANCH IF DIRECT MODE + BSR LB00F GET SOME INPUT DATA - WAS LB002 + RTS +LB00F CMPA #'" CHECK FOR PROMPT STRING DELIMITER + BNE LB01E BRANCH IF NO PROMPT STRING + JSR LB244 PUT PROMPT STRING ON STRING STACK + LDB #'; * + JSR LB26F * DO A SYNTAX CHECK FOR SEMICOLON + JSR LB99F PRINT MESSAGE TO CONSOLE OUT +LB01E LDX #LINBUF POINT TO BASIC’S LINE BUFFER + CLR ,X CLEAR 1ST BYTE - FLAG TO INDICATE NO DATA +* IN LINE BUFFER + BSR LB02F INPUT A STRING TO LINE BUFFER + LDB #', * INSERT A COMMA AT THE END + STB ,X * OF THE LINE INPUT BUFFER + BRA LB049 +* FILL BASIC’S LINE INPUT BUFFER CONSOLE IN +LB02F JSR LB9AF SEND A "?" TO CONSOLE OUT + JSR LB9AC SEND A ‘SPACE’ TO CONSOLE OUT +LB035 JSR LA390 GO READ IN A BASIC LINE + BCC LB03F BRANCH IF ENTER KEY ENDED ENTRY + LEAS 4,S PURGE TWO RETURN ADDRESSES OFF THE STACK + JMP LAE11 GO DO A ‘STOP’ IF BREAK KEY ENDED LINE ENTRY +LB03F LDB #2*23 ‘INPUT PAST END OF FILE’ ERROR + RTS +* +* READ +READ LDX DATPTR GET ‘READ’ START ADDRESS + FCB SKP1LD SKIP ONE BYTE - LDA #*$4F +LB049 CLRA ‘INPUT’ ENTRY POINT: INPUT FLAG = 0 + STA INPFLG SET INPUT FLAG; 0 = INPUT: <> 0 = READ + STX DATTMP SAVE ‘READ’ START ADDRESS/’INPUT’ BUFFER START +LB04E JSR LB357 EVALUATE A VARIABLE + STX VARDES SAVE DESCRIPTOR ADDRESS + LDX CHARAD * GET BASIC’S INPUT POINTER + STX BINVAL * AND SAVE IT + LDX DATTMP GET ‘READ’ ADDRESS START/’INPUT’ BUFFER POINTER + LDA ,X GET A CHARACTER FROM THE BASIC PROGRAM + BNE LB069 BRANCH IF NOT END OF LINE + LDA INPFLG * CHECK INPUT FLAG AND BRANCH + BNE LB0B9 * IF LOOKING FOR DATA (READ) +* NO DATA IN ‘INPUT’ LINE BUFFER AND/OR INPUT +* NOT COMING FROM SCREEN + JSR LB9AF SEND A '?' TO CONSOLE OUT + BSR LB02F FILL INPUT BUFFER FROM CONSOLE IN +LB069 STX CHARAD RESET BASIC’S INPUT POINTER + JSR GETNCH GET A CHARACTER FROM BASIC + LDB VALTYP * CHECK VARIABLE TYPE AND + BEQ LB098 * BRANCH IF NUMERIC +* READ/INPUT A STRING VARIABLE + LDX CHARAD LOAD X WITH CURRENT BASIC INPUT POINTER + STA CHARAC SAVE CURRENT INPUT CHARACTER + CMPA #'" CHECK FOR STRING DELIMITER + BEQ LB08B BRANCH IF STRING DELIMITER + LEAX -1,X BACK UP POINTER + CLRA * ZERO = END OF LINE CHARACTER + STA CHARAC * SAVE AS TERMINATOR + JSR LA35F SET UP PRINT PARAMETERS + LDA #': END OF SUBLINE CHARACTER + STA CHARAC SAVE AS TERMINATOR I + LDA #', COMMA +LB08B STA ENDCHR SAVE AS TERMINATOR 2 + JSR LB51E STRIP A STRING FROM THE INPUT BUFFER + JSR LB249 MOVE INPUT POINTER TO END OF STRING + JSR LAFA4 PUT A STRING INTO THE STRING SPACE IF NECESSARY + BRA LB09E CHECK FOR ANOTHER DATA ITEM +* SAVE A NUMERIC VALUE IN A READ OR INPUT DATA ITEM +LB098 JSR LBD12 CONVERT AN ASCII STRING TO FP NUMBER + JSR LBC33 PACK FPA0 AND STORE IT IN ADDRESS IN VARDES - +* INPUT OR READ DATA ITEM +LB09E JSR GETCCH GET CURRENT INPUT CHARACTER + BEQ LB0A8 BRANCH IF END OF LINE + CMPA #', CHECK FOR A COMMA + LBNE LAFD6 BAD FILE DATA' ERROR OR RETRY +LB0A8 LDX CHARAD * GET CURRENT INPUT + STX DATTMP * POINTER (USED AS A DATA POINTER) AND SAVE IT + LDX BINVAL * RESET INPUT POINTER TO INPUT OR + STX CHARAD * READ STATEMENT + JSR GETCCH GET CURRENT CHARACTER FROM BASIC + BEQ LB0D5 BRANCH IF END OF LINE - EXIT COMMAND + JSR LB26D SYNTAX CHECK FOR COMMA + BRA LB04E GET ANOTHER INPUT OR READ ITEM +* SEARCH FROM ADDRESS IN X FOR +* 1ST OCCURENCE OF THE TOKEN FOR DATA +LB0B9 STX CHARAD RESET BASIC’S INPUT POINTER + JSR LAEE8 SEARCH FOR END OF CURRENT LINE OR SUBLINE + LEAX 1,X MOVE X ONE PAST END OF LINE + TSTA CHECK FOR END OF LINE + BNE LB0CD BRANCH IF END OF SUBLINE + LDB #2*3 ‘OUT OF DATA’ ERROR + LDU ,X++ GET NEXT 2 CHARACTERS + BEQ LB10A ‘OD’ ERROR IF END OF PROGRAM + LDD ,X++ GET BASIC LINE NUMBER AND + STD DATTXT SAVE IT IN DATTXT +LB0CD LDA ,X GET AN INPUT CHARACTER + CMPA #TOK_DATA DATA TOKEN? + BNE LB0B9 NO — KEEP LOOKING + BRA LB069 YES +* EXIT READ AND INPUT COMMANDS +LB0D5 LDX DATTMP GET DATA POINTER + LDB INPFLG * CHECK INPUT FLAG + LBNE LADE8 * SAVE NEW DATA POINTER IF READ + LDA ,X = CHECK NEXT CHARACTER IN ‘INPUT’ BUFFER + BEQ LB0E7 = + LDX #LB0E8-1 POINT X TO ‘?EXTRA IGNORED’ + JMP LB99C PRINT THE MESSAGE +LB0E7 RTS + +LB0E8 FCC "?EXTRA IGNORED" ?EXTRA IGNORED MESSAGE + + + FCB CR,$00 + +* NEXT +NEXT BNE LB0FE BRANCH IF ARGUMENT GIVEN + LDX ZERO X = 0: DEFAULT FOR NO ARGUMENT + BRA LB101 +LB0FE JSR LB357 EVALUATE AN ALPHA EXPRESSION +LB101 STX VARDES SAVE VARIABLE DESCRIPTOR POINTER + JSR LABF9 GO SCAN FOR ‘FOR/NEXT’ DATA ON STACK + BEQ LB10C BRANCH IF DATA FOUND + LDB #0 ‘NEXT WITHOUT FOR’ ERROR (SHOULD BE CLRB) +LB10A BRA LB153 PROCESS ERROR +LB10C TFR X,S POINT S TO START OF ‘FOR/NEXT’ DATA + LEAX 3,X POINT X TO FP VALUE OF STEP + JSR LBC14 COPY A FP NUMBER FROM (X) TO FPA0 + LDA 8,S GET THE DIRECTION OF STEP + STA FP0SGN SAVE IT AS THE SIGN OF FPA0 + LDX VARDES POINT (X) TO INDEX VARIABLE DESCRIPTOR + JSR LB9C2 ADD (X) TO FPA0 (STEP TO INDEX) + JSR LBC33 PACK FPA0 AND STORE IT IN ADDRESS +* CONTAINED IN VARDES + LEAX 9,S POINT (X) TO TERMINAL VALUE OF INDEX + JSR LBC96 COMPARE CURRENT INDEX VALUE TO TERMINAL VALUE OF INDEX + SUBB 8,S ACCB = 0 IF TERMINAL VALUE=CURRENT VALUE AND STEP=0 OR IF +* STEP IS POSITIVE AND CURRENT VALUE>TERMINAL VALUE OR +* STEP IS NEGATIVE AND CURRENT VALUE + BCS LB181 BRANCH IF LESS THAN RELATIONAL OPERATORS + CMPA #3 * + BCC LB181 * BRANCH IF GREATER THAN RELATIONAL OPERATORS + CMPA #1 SET CARRY IF ‘>‘ + ROLA CARRY TO BIT 0 + EORA TRELFL * CARRY SET IF + CMPA TRELFL * TRELFL = ACCA + BCS LB1DF BRANCH IF SYNTAX ERROR : == << OR >> + STA TRELFL BIT 0: >, BIT 1 =, BIT 2: < + JSR GETNCH GET AN INPUT CHARACTER + BRA LB16A CHECK FOR ANOTHER RELATIONAL OPERATOR +* +LB181 LDB TRELFL GET RELATIONAL OPERATOR FLAG + BNE LB1B8 BRANCH IF RELATIONAL COMPARISON + LBCC LB1F4 BRANCH IF > RELATIONAL OPERATOR + ADDA #7 SEVEN ARITHMETIC/LOGICAL OPERATORS + BCC LB1F4 BRANCH IF NOT ARITHMETIC/LOGICAL OPERATOR + ADCA VALTYP ADD CARRY, NUMERIC FLAG AND MODIFIED TOKEN NUMBER + LBEQ LB60F BRANCH IF VALTYP = FF, AND ACCA = ‘+‘ TOKEN - +* CONCATENATE TWO STRINGS + ADCA #-1 RESTORE ARITHMETIC/LOGICAL OPERATOR NUMBER + PSHS A * STORE OPERATOR NUMBER ON STACK; MULTIPLY IT BY 2 + ASLA * THEN ADD THE STORED STACK DATA = MULTIPLY + ADDA ,S+ * X 3; 3 BYTE/TABLE ENTRY + LDX #LAA51 JUMP TABLE FOR ARITHMETIC & LOGICAL OPERATORS + LEAX A,X POINT X TO PROPER TABLE +LB19F PULS A GET PRECEDENCE FLAG FROM STACK + CMPA ,X COMPARE TO CURRENT OPERATOR + BCC LB1FA BRANCH IF STACK OPERATOR > CURRENT OPERATOR + BSR LB143 ‘TM’ ERROR IF VARIABLE TYPE = STRING + +* OPERATION BEING PROCESSED IS OF HIGHER PRECEDENCE THAN THE PREVIOUS OPERATION. +LB1A7 PSHS A SAVE PRECEDENCE FLAG + BSR LB1D4 PUSH OPERATOR ROUTINE ADDRESS AND FPA0 ONTO STACK + LDX RELPTR GET POINTER TO ARITHMETIC/LOGICAL TABLE ENTRY FOR +* LAST CALCULATED OPERATION + PULS A GET PRECEDENCE FLAG OF PREVIOUS OPERATION + BNE LB1CE BRANCH IF NOT END OF OPERATION + TSTA CHECK TYPE OF PRECEDENCE FLAG + LBEQ LB220 BRANCH IF END OF EXPRESSION OR SUB-EXPRESSION + BRA LB203 EVALUATE AN OPERATION + +LB1B8 ASL VALTYP BIT 7 OF TYPE FLAG TO CARRY + ROLB SHIFT RELATIONAL FLAG LEFT - VALTYP TO BIT 0 + BSR LB1C6 MOVE THE INPUT POINTER BACK ONE + LDX #LB1CB POINT X TO RELATIONAL COMPARISON JUMP TABLE + STB TRELFL SAVE RELATIONAL COMPARISON DATA + CLR VALTYP SET VARIABLE TYPE TO NUMERIC + BRA LB19F PERFORM OPERATION OR SAVE ON STACK + +LB1C6 LDX CHARAD * GET BASIC’S INPUT POINTER AND + JMP LAEBB * MOVE IT BACK ONE +* RELATIONAL COMPARISON JUMP TABLE +LB1CB FCB $64 RELATIONAL COMPARISON FLAG +LB1CC FDB LB2F4 JUMP ADDRESS + +LB1CE CMPA ,X COMPARE PRECEDENCE OF LAST DONE OPERATION TO +* NEXT TO BE DONE OPERATION + BCC LB203 EVALUATE OPERATION IF LOWER PRECEDENCE + BRA LB1A7 PUSH OPERATION DATA ON STACK IF HIGHER PRECEDENCE + +* PUSH OPERATOR EVALUATION ADDRESS AND FPA0 ONTO STACK AND EVALUATE ANOTHER EXPR +LB1D4 LDD 1,X GET ADDRESS OF OPERATOR ROUTINE + PSHS B,A SAVE IT ON THE STACK + BSR LB1E2 PUSH FPA0 ONTO STACK + LDB TRELFL GET BACK RELATIONAL OPERATOR FLAG + LBRA LB15A EVALUATE ANOTHER EXPRESSION +LB1DF JMP LB277 ‘SYNTAX ERROR’ +* PUSH FPA0 ONTO THE STACK. ,S = EXPONENT +* 1-2,S =HIGH ORDER MANTISSA 3-4,S = LOW ORDER MANTISSA +* 5,S = SIGN RETURN WITH PRECEDENCE CODE IN ACCA +LB1E2 LDB FP0SGN GET SIGN OF FPA0 MANTISSA + LDA ,X GET PRECEDENCE CODE TO ACCA +LB1E6 PULS Y GET RETURN ADDRESS FROM STACK & PUT IT IN Y + PSHS B SAVE ACCB ON STACK +LB1EA LDB FP0EXP * PUSH FPA0 ONTO THE STACK + LDX FPA0 * + LDU FPA0+2 * + PSHS U,X,B * + JMP ,Y JUMP TO ADDRESS IN Y + +* BRANCH HERE IF NON-OPERATOR CHARACTER FOUND - USUALLY ‘)‘ OR END OF LINE +LB1F4 LDX ZERO POINT X TO DUMMY VALUE (ZERO) + LDA ,S+ GET PRECEDENCE FLAG FROM STACK + BEQ LB220 BRANCH IF END OF EXPRESSION +LB1FA CMPA #$64 * CHECK FOR RELATIONAL COMPARISON FLAG + BEQ LB201 * AND BRANCH IF RELATIONAL COMPARISON + JSR LB143 ‘TM’ ERROR IF VARIABLE TYPE = STRING +LB201 STX RELPTR SAVE POINTER TO OPERATOR ROUTINE +LB203 PULS B GET RELATIONAL OPERATOR FLAG FROM STACK + CMPA #$5A CHECK FOR ‘NOT’ OPERATOR + BEQ LB222 RETURN IF ‘NOT’ - NO RELATIONAL COMPARISON + CMPA #$7D CHECK FOR NEGATION (UNARY) FLAG + BEQ LB222 RETURN IF NEGATION - NO RELATIONAL COMPARISON + +* EVALUATE AN OPERATION. EIGHT BYTES WILL BE STORED ON STACK, FIRST SIX BYTES +* ARE A TEMPORARY FLOATING POINT RESULT THEN THE ADDRESS OF ROUTINE WHICH +* WILL EVALUATE THE OPERATION. THE RTS AT END OF ROUTINE WILL VECTOR +* TO EVALUATING ROUTINE. + LSRB = ROTATE VALTYP BIT INTO CARRY + STB RELFLG = FLAG AND SAVE NEW RELFLG + PULS A,X,U * PULL A FP VALUE OFF OF THE STACK + STA FP1EXP * AND SAVE IT IN FPA1 + STX FPA1 * + STU FPA1+2 * + PULS B = GET MANTISSA SIGN AND + STB FP1SGN = SAVE IT IN FPA1 + EORB FP0SGN EOR IT WITH FPA1 MANTISSA SIGN + STB RESSGN SAVE IT IN RESULT SIGN BYTE +LB220 LDB FP0EXP GET EXPONENT OF FPA0 +LB222 RTS + +LB223 JSR XVEC15 CALL EXTENDED BASIC ADD-IN + CLR VALTYP INITIALIZE TYPE FLAG TO NUMERIC + JSR GETNCH GET AN INPUT CHAR + BCC LB22F BRANCH IF NOT NUMERIC +LB22C JMP LBD12 CONVERT ASCII STRING TO FLOATING POINT - +* RETURN RESULT IN FPA0 +* PROCESS A NON NUMERIC FIRST CHARACTER +LB22F JSR LB3A2 SET CARRY IF NOT ALPHA + BCC LB284 BRANCH IF ALPHA CHARACTER + CMPA #'. IS IT ‘.‘ (DECIMAL POINT)? + BEQ LB22C CONVERT ASCII STRING TO FLOATING POINT + CMPA #TOK_MINUS MINUS TOKEN + BEQ LB27C YES - GO PROCESS THE MINUS OPERATOR + CMPA #TOK_PLUS PLUS TOKEN + BEQ LB223 YES - GET ANOTHER CHARACTER + CMPA #'" STRING DELIMITER? + BNE LB24E NO +LB244 LDX CHARAD CURRENT BASIC POINTER TO X + JSR LB518 SAVE STRING ON STRING STACK +LB249 LDX COEFPT * GET ADDRESS OF END OF STRING AND + STX CHARAD * PUT BASIC’S INPUT POINTER THERE + RTS +LB24E CMPA #TOK_NOT NOT TOKEN? + BNE LB25F NO +* PROCESS THE NOT OPERATOR + LDA #$5A ‘NOT’ PRECEDENCE FLAG + JSR LB15A PROCESS OPERATION FOLLOWING ‘NOT’ + JSR INTCNV CONVERT FPA0 TO INTEGER IN ACCD + COMA * ‘NOT’ THE INTEGER + COMB * + JMP GIVABF CONVERT ACCD TO FLOATING POINT (FPA0) +LB25F INCA CHECK FOR TOKENS PRECEEDED BY $FF + BEQ LB290 IT WAS PRECEEDED BY $FF +LB262 BSR LB26A SYNTAX CHECK FOR A ‘(‘ + JSR LB156 EVALUATE EXPRESSIONS WITHIN PARENTHESES AT +* HIGHEST PRECEDENCE +LB267 LDB #') SYNTAX CHECK FOR ‘)‘ + FCB SKP2 SKIP 2 BYTES +LB26A LDB #'( SYNTAX CHECK FOR ‘(‘ + FCB SKP2 SKIP 2 BYTES +LB26D LDB #', SYNTAX CHECK FOR COMMA +LB26F CMPB [CHARAD] * COMPARE ACCB TO CURRENT INPUT + BNE LB277 * CHARACTER - SYNTAX ERROR IF NO MATCH + JMP GETNCH GET A CHARACTER FROM BASIC +LB277 LDB #2*1 SYNTAX ERROR + JMP LAC46 JUMP TO ERROR HANDLER + +* PROCESS THE MINUS (UNARY) OPERATOR +LB27C LDA #$7D MINUS (UNARY) PRECEDENCE FLAG + JSR LB15A PROCESS OPERATION FOLLOWING ‘UNARY’ NEGATION + JMP LBEE9 CHANGE SIGN OF FPA0 MANTISSA + +* EVALUATE ALPHA EXPRESSION +LB284 JSR LB357 FIND THE DESCRIPTOR ADDRESS OF A VARIABLE +LB287 STX FPA0+2 SAVE DESCRIPTOR ADDRESS IN FPA0 + LDA VALTYP TEST VARIABLE TYPE + BNE LB222 RETURN IF STRING + JMP LBC14 COPY A FP NUMBER FROM (X) TO FPA0 + +* EVALUATING A SECONDARY TOKEN +LB290 JSR GETNCH GET AN INPUT CHARACTER (SECONDARY TOKEN) + TFR A,B SAVE IT IN ACCB + ASLB X2 & BET RID OF BIT 7 + JSR GETNCH GET ANOTHER INPUT CHARACTER + CMPB #NUM_SEC_FNS-1*2 29 SECONDARY FUNCTIONS - 1 + BLS LB29F BRANCH IF COLOR BASIC TOKEN + JMP LB277 SYNTAX ERROR +LB29F PSHS B SAVE TOKEN OFFSET ON STACK + CMPB #TOK_LEFT-$80*2 CHECK FOR TOKEN WITH AN ARGUMENT + BCS LB2C7 DO SECONDARIES STRING$ OR LESS + CMPB #TOK_INKEY-$80*2 * + BCC LB2C9 * DO SECONDARIES $92 (INKEY$) OR > + BSR LB26A SYNTAX CHECK FOR A ‘(‘ + LDA ,S GET TOKEN NUMBER +* DO SECONDARIES (LEFT$, RIGHT$, MID$) + JSR LB156 EVALUATE FIRST STRING IN ARGUMENT + BSR LB26D SYNTAX CHECK FOR A COMMA + JSR LB146 ‘TM’ ERROR IF NUMERIC VARiABLE + PULS A GET TOKEN OFFSET FROM STACK + LDU FPA0+2 POINT U TO STRING DESCRIPTOR + PSHS U,A SAVE TOKEN OFFSET AND DESCRIPTOR ADDRESS + JSR LB70B EVALUATE FIRST NUMERIC ARGUMENT + PULS A GET TOKEN OFFSET FROM STACK + PSHS B,A SAVE TOKEN OFFSET AND NUMERIC ARGUMENT + FCB $8E OP CODE OF LDX# - SKlP 2 BYTES +LB2C7 BSR LB262 SYNTAX CHECK FOR A ‘(‘ +LB2C9 PULS B GET TOKEN OFFSET + LDX COMVEC+8 GET SECONDARY FUNCTION JUMP TABLE ADDRESS +LB2CE ABX ADD IN COMMAND OFFSET +* +* HERE IS WHERE WE BRANCH TO A SECONDARY FUNCTION + JSR [,X] GO DO AN SECONDARY FUNCTION + JMP LB143 ‘TM’ ERROR IF VARIABLE TYPE = STRING + +* LOGICAL OPERATOR ‘OR’ JUMPS HERE +LB2D4 FCB SKP1LD SKIP ONE BYTE - ‘OR’ FLAG = $4F + +* LOGICAL OPERATOR ‘AND’ JUMPS HERE +LB2D5 CLRA AND FLAG = 0 + STA TMPLOC AND/OR FLAG + JSR INTCNV CONVERT FPA0 INTO AN INTEGER IN ACCD + STD CHARAC TEMP SAVE ACCD + JSR LBC4A MOVE FPA1 TO FPA0 + JSR INTCNV CONVERT FPA0 INTO AN INTEGER IN ACCD + TST TMPLOC CHECK AND/OR FLAG + BNE LB2ED BRANCH IF OR + ANDA CHARAC * ‘AND’ ACCD WITH FPA0 INTEGER + ANDB ENDCHR * STORED IN ENDCHR + BRA LB2F1 CONVERT TO FP +LB2ED ORA CHARAC * ‘OR’ ACCD WITH FPA0 INTEGER + ORB ENDCHR * STORED IN CHARAC +LB2F1 JMP GIVABF CONVERT THE VALUE IN ACCD INTO A FP NUMBER + +* RELATIONAL COMPARISON PROCESS HANDLER +LB2F4 JSR LB148 ‘TM’ ERROR IF TYPE MISMATCH + BNE LB309 BRANCH IF STRING VARIABLE + LDA FP1SGN * ‘PACK’ THE MANTISSA + ORA #$7F * SIGN OF FPA1 INTO + ANDA FPA1 * BIT 7 OF THE + STA FPA1 * MANTISSA MS BYTE + LDX #FP1EXP POINT X TO FPA1 + JSR LBC96 COMPARE FPA0 TO FPA1 + BRA LB33F CHECK TRUTH OF RELATIONAL COMPARISON + +* RELATIONAL COMPARISON OF STRINGS +LB309 CLR VALTYP SET VARIABLE TYPE TO NUMERIC + DEC TRELFL REMOVE STRING TYPE FLAG (BIT0=1 FOR STRINGS) FROM THE +* DESIRED RELATIONAL COMPARISON DATA + JSR LB657 GET LENGTH AND ADDRESS OF STRING WHOSE +* DESCRIPTOR ADDRESS IS IN THE BOTTOM OF FPA0 + STB STRDES * SAVE LENGTH AND ADDRESS IN TEMPORARY + STX STRDES+2 * DESCRIPTOR (STRING B) + LDX FPA1+2 = RETURN LENGTH AND ADDRESS OF STRING + JSR LB659 = WHOSE DESCRIPTOR ADDRESS IS STORED IN FPA1+2 + LDA STRDES LOAD ACCA WITH LENGTH OF STRING B + PSHS B SAVE LENGTH A ON STACK + SUBA ,S+ SUBTRACT LENGTH A FROM LENGTH B + BEQ LB328 BRANCH IF STRINGS OF EQUAL LENGTH + LDA #1 TRUE FLAG + BCC LB328 TRUE IF LENGTH B > LENGTH A + LDB STRDES LOAD ACCB WITH LENGTH B + NEGA SET FLAG = FALSE (1FF) +LB328 STA FP0SGN SAVE TRUE/FALSE FLAG + LDU STRDES+2 POINT U TO START OF STRING + INCB COMPENSATE FOR THE DECB BELOW +* ENTER WITH ACCB CONTAINING LENGTH OF SHORTER STRING +LB32D DECB DECREMENT SHORTER STRING LENGTH + BNE LB334 BRANCH IF ALL OF STRING NOT COMPARED + LDB FP0SGN GET TRUE/FALSE FLAB + BRA LB33F CHECK TRUTH OF RELATIONAL COMPARISON +LB334 LDA ,X+ GET A BYTE FROM STRING A + CMPA ,U+ COMPARE TO STRING B + BEQ LB32D CHECK ANOTHER CHARACTER IF = + LDB #$FF FALSE FLAG IF STRING A > B + BCC LB33F BRANCH IF STRING A > STRING B + NEGB SET FLAG = TRUE + +* DETERMINE TRUTH OF COMPARISON - RETURN RESULT IN FPA0 +LB33F ADDB #1 CONVERT $FF,0,1 TO 0,1,2 + ROLB NOW IT’S 1,2,4 FOR > = < + ANDB RELFLG ‘AND’ THE ACTUAL COMPARISON WITH THE DESIRED - +COMPARISON + BEQ LB348 BRANCH IF FALSE (NO MATCHING BITS) + LDB #$FF TRUE FLAG +LB348 JMP LBC7C CONVERT ACCB INTO FP NUMBER IN FPA0 + +* DIM +LB34B JSR LB26D SYNTAX CHECK FOR COMMA +DIM LDB #1 DIMENSION FLAG + BSR LB35A SAVE ARRAY SPACE FOR THIS VARIABLE + JSR GETCCH GET CURRENT INPUT CHARACTER + BNE LB34B KEEP DIMENSIONING IF NOT END OF LINE + RTS +* EVALUATE A VARIABLE - RETURN X AND +* VARPTR POINTING TO VARIABLE DESCRIPTOR +* EACH VARIABLE REQUIRES 7 BYTES - THE FIRST TWO +* BYTES ARE THE VARIABLE NAME AND THE NEXT 5 +* BYTES ARE THE DESCRIPTOR. IF BIT 7 OF THE +* FIRST BYTE OF VARlABLE NAME IS SET, THE +* VARIABLE IS A DEF FN VARIABLE. IF BIT 7 OF +* THE SECOND BYTE OF VARIABLE NAME IS SET, THE +* VARIABLE IS A STRING, OTHERWISE THE VARIABLE +* IS NUMERIC. +* IF THE VARIABLE IS NOT FOUND, A ZERO VARIABLE IS +* INSERTED INTO THE VARIABLE SPACE +LB357 CLRB DIMENSION FLAG = 0; DO NOT SET UP AN ARRAY + JSR GETCCH GET CURRENT INPUT CHARACTER +LB35A STB DIMFLG SAVE ARRAY FLAG +* ENTRY POINT FOR DEF FN VARIABLE SEARCH +LB35C STA VARNAM SAVE INPUT CHARACTER + JSR GETCCH GET CURRENT INPUT CHARACTER + BSR LB3A2 SET CARRY IF NOT ALPHA + LBCS LB277 SYNTAX ERROR IF NOT ALPHA + CLRB DEFAULT 2ND VARIABLE CHARACTER TO ZERO + STB VALTYP SET VARIABLE TYPE TO NUMERIC + JSR GETNCH GET ANOTHER CHARACTER FROM BASIC + BCS LB371 BRANCH IF NUMERIC (2ND CHARACTER IN +* VARIABLE MAY BE NUMERIC) + BSR LB3A2 SET CARRY IF NOT ALPHA + BCS LB37B BRANCH IF NOT ALPHA +LB371 TFR A,B SAVE 2ND CHARACTER IN ACCB +* READ INPUT CHARACTERS UNTIL A NON ALPHA OR +* NON NUMERIC IS FOUND - IGNORE ALL CHARACTERS +* IN VARIABLE NAME AFTER THE 1ST TWO +LB373 JSR GETNCH GET AN INPUT CHARACTER + BCS LB373 BRANCH IF NUMERIC + BSR LB3A2 SET CARRY IF NOT ALPHA + BCC LB373 BRANCH IF ALPHA +LB37B CMPA #'$ CHECK FOR A STRING VARIABLE + BNE LB385 BRANCH IF IT IS NOT A STRING + COM VALTYP SET VARIABLE TYPE TO STRING + ADDB #$80 SET BIT 7 OF 2ND CHARACTER (STRING) + JSR GETNCH GET AN INPUT CHARACTER +LB385 STB VARNAM+1 SAVE 2ND CHARACTER IN VARNAM+1 + ORA ARYDIS OR IN THE ARRAY DISABLE FLAG - IF = $80, +* DON’T SEARCH FOR VARIABLES IN THE ARRAYS + SUBA #'( IS THIS AN ARRAY VARIABLE? + LBEQ LB404 BRANCH IF IT IS + CLR ARYDIS RESET THE ARRAY DISABLE FLAG + LDX VARTAB POINT X TO THE START OF VARIABLES + LDD VARNAM GET VARIABLE IN QUESTION +LB395 CMPX ARYTAB COMPARE X TO THE END OF VARIABLES + BEQ LB3AB BRANCH IF END OF VARIABLES + CMPD ,X++ * COMPARE VARIABLE IN QUESTION TO CURRENT + BEQ LB3DC * VARIABLE AND BRANCH IF MATCH + LEAX 5,X = MOVE POINTER TO NEXT VARIABLE AND + BRA LB395 = KEEP LOOKING + +* SET CARRY IF NOT UPPER CASE ALPHA +LB3A2 CMPA #'A * CARRY SET IF < ‘A’ + BCS LB3AA * + SUBA #'Z+1 = +* SUBA #-('Z+1) = CARRY CLEAR IF <= 'Z' + FCB $80,$A5 +LB3AA RTS +* PUT A NEW VARIABLE IN TABLE OF VARIABLES +LB3AB LDX #ZERO POINT X TO ZERO LOCATION + LDU ,S GET CURRENT RETURN ADDRESS + CMPU #LB287 DID WE COME FROM ‘EVALUATE ALPHA EXPR’? + BEQ LB3DE YES - RETURN A ZERO VALUE + LDD ARYEND * GET END OF ARRAYS ADDRESS AND + STD V43 * SAVE IT AT V43 + ADDD #7 = ADD 7 TO END OF ARRAYS (EACH + STD V41 = VARIABLE = 7 BYTES) AND SAVE AT V41 + LDX ARYTAB * GET END OF VARIABLES AND SAVE AT V47 + STX V47 * + JSR LAC1E MAKE A SEVEN BYTE SLOT FOR NEW VARIABLE AT +* TOP OF VARIABLES + LDX V41 = GET NEW END OF ARRAYS AND SAVE IT + STX ARYEND = + LDX V45 * GET NEW END OF VARIABLES AND SAVE IT + STX ARYTAB * + LDX V47 GET OLD END OF VARIABLES + LDD VARNAM GET NEW VARIABLE NAME + STD ,X++ SAVE VARIABLE NAME + CLRA * ZERO OUT THE FP VALUE OF THE NUMERIC + CLRB * VARIABLE OR THE LENGTH AND ADDRESS + STD ,X * OF A STRING VARIABLE + STD 2,X * + STA 4,X * +LB3DC STX VARPTR STORE ADDRESS OF VARIABLE VALUE +LB3DE RTS +* +LB3DF FCB $90,$80,$00,$00,$00 * FLOATING POINT -32768 +* SMALLEST SIGNED TWO BYTE INTEGER +* +LB3E4 JSR GETNCH GET AN INPUT CHARACTER FROM BASIC +LB3E6 JSR LB141 GO EVALUATE NUMERIC EXPRESSION +LB3E9 LDA FP0SGN GET FPA0 MANTISSA SIGN + BMI LB44A ‘FC’ ERROR IF NEGATIVE NUMBER + + +INTCNV JSR LB143 ‘TM’ ERROR IF STRING VARIABLE + LDA FP0EXP GET FPA0 EXPONENT + CMPA #$90 * COMPARE TO 32768 - LARGEST INTEGER EXPONENT AND + BCS LB3FE * BRANCH IF FPA0 < 32768 + LDX #LB3DF POINT X TO FP VALUE OF -32768 + JSR LBC96 COMPARE -32768 TO FPA0 + BNE LB44A ‘FC’ ERROR IF NOT = +LB3FE JSR LBCC8 CONVERT FPA0 TO A TWO BYTE INTEGER + LDD FPA0+2 GET THE INTEGER + RTS +* EVALUATE AN ARRAY VARIABLE +LB404 LDD DIMFLG GET ARRAY FLAG AND VARIABLE TYPE + PSHS B,A SAVE THEM ON STACK + NOP DEAD SPACE CAUSED BY 1.2 REVISION + CLRB RESET DIMENSION COUNTER +LB40A LDX VARNAM GET VARIABLE NAME + PSHS X,B SAVE VARIABLE NAME AND DIMENSION COUNTER + BSR LB3E4 EVALUATE EXPRESSION (DIMENSlON LENGTH) + PULS B,X,Y PULL OFF VARIABLE NAME, DIMENSlON COUNTER, +* ARRAY FLAG + STX VARNAM SAVE VARIABLE NAME AND VARIABLE TYPE + LDU FPA0+2 GET DIMENSION LENGTH + PSHS U,Y SAVE DIMENSION LENGTH, ARRAY FLAG, VARIABLE TYPE + INCB INCREASE DIMENSION COUNTER + JSR GETCCH GET CURRENT INPUT CHARACTER + CMPA #', CHECK FOR ANOTHER DIMENSION + BEQ LB40A BRANCH IF MORE + STB TMPLOC SAVE DIMENSION COUNTER + JSR LB267 SYNTAX CHECK FOR A ‘)‘ + PULS A,B * RESTORE VARIABLE TYPE AND ARRAY + STD DIMFLG * FLAG - LEAVE DIMENSION LENGTH ON STACK + LDX ARYTAB GET START OF ARRAYS +LB42A CMPX ARYEND COMPARE TO END OF ARRAYS + BEQ LB44F BRANCH IF NO MATCH FOUND + LDD VARNAM GET VARIABLE IN QUESTION + CMPD ,X COMPARE TO CURRENT VARIABLE + BEQ LB43B BRANCH IF = + LDD 2,X GET OFFSET TO NEXT ARRAY VARIABLE + LEAX D,X ADD TO CURRENT POINTER + BRA LB42A KEEP SEARCHING +LB43B LDB #2*9 ‘REDIMENSIONED ARRAY’ ERROR + LDA DIMFLG * TEST ARRAY FLAG - IF <>0 YOU ARE TRYING + BNE LB44C * TO REDIMENSION AN ARRAY + LDB TMPLOC GET NUMBER OF DIMENSIONS IN ARRAY + CMPB 4,X COMPARE TO THIS ARRAYS DIMENSIONS + BEQ LB4A0 BRANCH IF = +LB447 LDB #8*2 ‘BAD SUBSCRIPT’ + FCB SKP2 SKIP TWO BYTES +LB44A LDB #4*2 ‘ILLEGAL FUNCTION CALL’ +LB44C JMP LAC46 JUMP TO ERROR SERVICING ROUTINE + +* INSERT A NEW ARRAY INTO ARRAY VARIABLES +* EACH SET OF ARRAY VARIABLES IS PRECEEDED BY A DE- +* SCRIPTOR BLOCK COMPOSED OF 5+2*N BYTES WHERE N IS THE +* NUMBER OF DIMENSIONS IN THE ARRAY. THE BLOCK IS DEFINED +* AS FOLLOWS: BYTES 0,1:VARIABLE’S NAME; 2,3:TOTAL LENGTH +* OF ARRAY ITEMS AND DESCRIPTOR BLOCK; 4:NUMBER OF DIMEN- +* ISIONS; 5,6:LENGTH OF DIMENSION 1; 7,8:LENGTH OF DIMEN- +* SION 2;… 4+N,5+N:LENGTH OF DIMENSION N. + +LB44F LDD #5 * 5 BYTES/ARRAY ENTRY SAVE AT COEFPT + STD COEFPT * + LDD VARNAM = GET NAME OF ARRAY AND SAVE IN + STD ,X = FIRST 2 BYTES OF DESCRIPTOR + LDB TMPLOC GET NUMBER OF DIMENSIONS AND SAVE IN + STB 4,X * 5TH BYTE OF DESCRIPTOR + JSR LAC33 CHECK FOR ROOM FOR DESCRIPTOR IN FREE RAM + STX V41 TEMPORARILY SAVE DESCRIPTOR ADDRESS +LB461 LDB #11 * DEFAULT DIMENSION VALUE:X(10) + CLRA * + TST DIMFLG = CHECK ARRAY FLAG AND BRANCH IF + BEQ LB46D = NOT DIMENSIONING AN ARRAY + PULS A,B GET DIMENSION LENGTH + ADDD #1 ADD ONE (X(0) HAS A LENGTH OF ONE) +LB46D STD 5,X SAVE LENGTH OF ARRAY DIMENSION + BSR LB4CE MULTIPLY ACCUM ARRAY SIZE NUMBER LENGTH +* OF NEW DIMENSION + STD COEFPT TEMP STORE NEW CURRENT ACCUMULATED ARRAY SIZE + LEAX 2,X BUMP POINTER UP TWO + DEC TMPLOC * DECREMENT DIMENSION COUNTER AND BRANCH IF + BNE LB461 * NOT DONE WITH ALL DIMENSIONS + STX TEMPTR SAVE ADDRESS OF (END OF ARRAY DESCRIPTOR - 5) + ADDD TEMPTR ADD TOTAL SIZE OF NEW ARRAY + LBCS LAC44 ‘OM’ ERROR IF > $FFFF + TFR D,X SAVE END OF ARRAY IN X + JSR LAC37 MAKE SURE THERE IS ENOUGH FREE RAM FOR ARRAY + SUBD #STKBUF-5 SUBTRACT OUT THE (STACK BUFFER - 5) + STD ARYEND SAVE NEW END OF ARRAYS + CLRA ZERO = TERMINATOR BYTE +LB48C LEAX -1,X * STORE TWO TERMINATOR BYTES AT + STA 5,X * THE END OF THE ARRAY DESCRIPTOR + CMPX TEMPTR * + BNE LB48C * + LDX V41 GET ADDRESS OF START OF DESCRIPTOR + LDA ARYEND GET MSB OF END OF ARRAYS; LSB ALREADY THERE + SUBD V41 SUBTRACT OUT ADDRESS OF START OF DESCRIPTOR + STD 2,X SAVE LENGTH OF (ARRAY AND DESCRIPTOR) + LDA DIMFLG * GET ARRAY FLAG AND BRANCH + BNE LB4CD * BACK IF DIMENSIONING +* CALCULATE POINTER TO CORRECT ELEMENT +LB4A0 LDB 4,X GET THE NUMBER OF DIMENSIONS + STB TMPLOC TEMPORARILY SAVE + CLRA * INITIALIZE POINTER + CLRB * TO ZERO +LB4A6 STD COEFPT SAVE ACCUMULATED POINTER + PULS A,B * PULL DIMENSION ARGUMENT OFF THE + STD FPA0+2 * STACK AND SAVE IT + CMPD 5,X COMPARE TO STORED ‘DIM’ ARGUMENT + BCC LB4EB ‘BS’ ERROR IF > = "DIM" ARGUMENT + LDU COEFPT * GET ACCUMULATED POINTER AND + BEQ LB4B9 * BRANCH IF 1ST DIMENSION + BSR LB4CE = MULTIPLY ACCUMULATED POINTER AND DIMENSION + ADDD FPA0+2 = LENGTH AND ADD TO CURRENT ARGUMENT +LB4B9 LEAX 2,X MOVE POINTER TO NEXT DIMENSION + DEC TMPLOC * DECREMENT DIMENSION COUNTER AND + BNE LB4A6 * BRANCH IF ANY DIMENSIONS LEFT +* MULTIPLY ACCD BY 5 - 5 BYTES/ARRAY VALUE + STD ,--S + ASLB + ROLA TIMES 2 + ASLB + ROLA TIMES 4 + ADDD ,S++ TIMES 5 + LEAX D,X ADD OFFSET TO START OF ARRAY + LEAX 5,X ADJUST POINTER FOR SIZE OF DESCRIPTOR + STX VARPTR SAVE POINTER TO ARRAY VALUE +LB4CD RTS +* MULTIPLY 2 BYTE NUMBER IN 5,X BY THE 2 BYTE NUMBER +* IN COEFPT. RETURN RESULT IN ACCD, BS ERROR IF > $FFFF +LB4CE LDA #16 16 SHIFTS TO DO A MULTIPLY + STA V45 SHIFT COUNTER + LDD 5,X * GET SIZE OF DIMENSION + STD BOTSTK * AND SAVE IT + CLRA * ZERO + CLRB * ACCD +LB4D8 ASLB = SHIFT ACCB LEFT + ROLA = ONE BIT + BCS LB4EB BS' ERROR IF CARRY + ASL COEFPT+1 * SHIFT MULTIPLICAND LEFT ONE + ROL COEFPT * BIT - ADD MULTIPLIER TO ACCUMULATOR + BCC LB4E6 * IF CARRY <> 0 + ADDD BOTSTK ADD MULTIPLIER TO ACCD + BCS LB4EB BS' ERROR IF CARRY (>$FFFF) +LB4E6 DEC V45 * DECREMENT SHIFT COUNTER + BNE LB4D8 * IF NOT DONE + RTS +LB4EB JMP LB447 BS' ERROR +* +* MEM +* THIS IS NOT A TRUE INDICATOR OF FREE MEMORY BECAUSE +* BASIC REQUIRES A STKBUF SIZE BUFFER FOR THE STACK +* FOR WHICH MEM DOES NOT ALLOW. +* +MEM TFR S,D PUT STACK POINTER INTO ACCD + SUBD ARYEND SUBTRACT END OF ARRAYS + FCB SKP1 SKIP ONE BYTE +*CONVERT THE VALUE IN ACCB INTO A FP NUMBER IN FPA0 +LB4F3 CLRA CLEAR MS BYTE OF ACCD +* CONVERT THE VALUE IN ACCD INTO A FLOATING POINT NUMBER IN FPA0 +GIVABF CLR VALTYP SET VARIABLE TYPE TO NUMERIC + STD FPA0 SAVE ACCD IN TOP OF FACA + LDB #$90 EXPONENT REQUIRED IF THE TOP TWO BYTES +* OF FPA0 ARE TO BE TREATED AS AN INTEGER IN FPA0 + JMP LBC82 CONVERT THE REST OF FPA0 TO AN INTEGER + +* STR$ +STR JSR LB143 TM' ERROR IF STRING VARIABLE + LDU #STRBUF+2 *CONVERT FP NUMBER TO ASCII STRING IN + JSR LBDDC *THE STRING BUFFER + LEAS 2,S PURGE THE RETURN ADDRESS FROM THE STACK + LDX #STRBUF+1 *POINT X TO STRING BUFFER AND SAVE + BRA LB518 *THE STRING IN THE STRING SPACE +* RESERVE ACCB BYTES OF STRING SPACE. RETURN START +* ADDRESS IN (X) AND FRESPC +LB50D STX V4D SAVE X IN V4D +LB50F BSR LB56D RESERVE ACCB BYTES IN STRING SPACE +LB511 STX STRDES+2 SAVE NEW STRING ADDRESS + STB STRDES SAVE LENGTH OF RESERVED BLOCK + RTS +LB516 LEAX -1,X MOVE POINTER BACK ONE +* SCAN A LINE FROM (X) UNTIL AN END OF LINE FLAG (ZERO) OR +* EITHER OF THE TWO TERMINATORS STORED IN CHARAC OR ENDCHR IS MATCHED. +* THE RESULTING STRING IS STORED IN THE STRING SPACE +* ONLY IF THE START OF THE STRING IS <= STRBUF+2 +LB518 LDA #'" * INITIALIZE + STA CHARAC * TERMINATORS +LB51A STA ENDCHR * TO " +LB51E LEAX 1,X MOVE POINTER UP ONE + STX RESSGN TEMPORARILY SAVE START OF STRING + STX STRDES+2 SAVE START OF STRING IN TEMP DESCRIPTOR + LDB #-1 INITIALIZE CHARACTER COUNTER TO - 1 +LB526 INCB INCREMENT CHARACTER COUNTER + LDA ,X+ GET CHARACTER + BEQ LB537 BRANCH IF END OF LINE + CMPA CHARAC * CHECK FOR TERMINATORS + BEQ LB533 * IN CHARAC AND ENDCHR + CMPA ENDCHR * DON’T MOVE POINTER BACK + BNE LB526 * ONE IF TERMINATOR IS "MATCHED" +LB533 CMPA #'" = COMPARE CHARACTER TO STRING DELIMITER + BEQ LB539 = & DON’T MOVE POINTER BACK IF SO +LB537 LEAX -1,X MOVE POINTER BACK ONE +LB539 STX COEFPT SAVE END OF STRING ADDRESS + STB STRDES SAVE STRING LENGTH IN TEMP DESCRIPTOR + LDU RESSGN GET INITlAL STRING START + CMPU #STRBUF+2 COMPARE TO START OF STRING BUFFER +LB543 BHI LB54C BRANCH IF > START OF STRING BUFFER + BSR LB50D GO RESERVE SPACE FOR THE STRING + LDX RESSGN POINT X TO THE BEGINNING OF THE STRING + JSR LB645 MOVE (B) BYTES FROM (X) TO +* [FRESPC] - MOVE STRING DATA +* PUT DIRECT PAGE STRING DESCRIPTOR BUFFER DATA +* ON THE STRING STACK. SET VARIABLE TYPE TO STRING +LB54C LDX TEMPPT GET NEXT AVAILABLE STRING STACK DESCRIPTOR + CMPX #LINHDR COMPARE TO TOP OF STRING DESCRIPTOR STACK - WAS #CFNBUF + BNE LB558 FORMULA O.K. + LDB #15*2 STRING FORMULA TOO COMPLEX' ERROR +LB555 JMP LAC46 JUMP TO ERROR SERVICING ROUTINE +LB558 LDA STRDES * GET LENGTH OF STRING AND SAVE IT +* STA ,X * IN BYTE 0 OF DESCRIPTOR + FCB $A7,$00 + LDD STRDES+2 = GET START ADDRESS OF ACTUAL STRING + STD 2,X = AND SAVE IN BYTES 2,3 OF DESCRIPTOR + LDA #$FF * VARIABLE TYPE = STRING + STA VALTYP * SAVE IN VARIABLE TYPE FLAG + STX LASTPT = SAVE START OF DESCRIPTOR + STX FPA0+2 = ADDRESS IN LASTPT AND FPA0 + LEAX 5,X 5 BYTES/STRING DESCRIPTOR + STX TEMPPT NEXT AVAILABLE STRING VARIABLE DESCRIPTOR + RTS +* RESERVE ACCB BYTES IN STRING STORAGE SPACE +* RETURN WITH THE STARTING ADDRESS OF THE +* RESERVED STRING SPACE IN (X) AND FRESPC +LB56D CLR GARBFL CLEAR STRING REORGANIZATION FLAG +LB56F CLRA * PUSH THE LENGTH OF THE + PSHS B,A * STRING ONTO THE STACK + LDD STRTAB GET START OF STRING VARIABLES + SUBD ,S+ SUBTRACT STRING LENGTH + CMPD FRETOP COMPARE TO START OF STRING STORAGE + BCS LB585 IF BELOW START, THEN REORGANIZE + STD STRTAB SAVE NEW START OF STRING VARIABLES + LDX STRTAB GET START OF STRING VARIABLES + LEAX 1,X ADD ONE + STX FRESPC SAVE START ADDRESS OF NEWLY RESERVED SPACE + PULS B,PC RESTORE NUMBER OF BYTES RESERVED AND RETURN +LB585 LDB #2*13 OUT OF STRING SPACE' ERROR + COM GARBFL TOGGLE REORGANIZATiON FLAG + BEQ LB555 ERROR IF FRESHLY REORGANIZED + BSR LB591 GO REORGANIZE STRING SPACE + PULS B GET BACK THE NUMBER OF BYTES TO RESERVE + BRA LB56F TRY TO RESERVE ACCB BYTES AGAIN +* REORGANIZE THE STRING SPACE +LB591 LDX MEMSIZ GET THE TOP OF STRING SPACE +LB593 STX STRTAB SAVE TOP OF UNORGANIZED STRING SPACE + CLRA * ZERO OUT ACCD + CLRB * AND RESET VARIABLE + STD V4B * POINTER TO 0 + LDX FRETOP POINT X TO START OF STRING SPACE + STX V47 SAVE POINTER IN V47 + LDX #STRSTK POINT X TO START OF STRING DESCRIPTOR STACK +LB5A0 CMPX TEMPPT COMPARE TO ADDRESS OF NEXT AVAILABLE DESCRIPTOR + BEQ LB5A8 BRANCH IF TOP OF STRING STACK + BSR LB5D8 CHECK FOR STRING IN UNORGANIZED STRING SPACE + BRA LB5A0 KEEP CHECKING +LB5A8 LDX VARTAB GET THE END OF BASIC PROGRAM +LB5AA CMPX ARYTAB COMPARE TO END OF VARIABLES + BEQ LB5B2 BRANCH IF AT TOP OF VARIABLES + BSR LB5D2 CHECK FOR STRING IN UNORGANIZED STRING SPACE + BRA LB5AA KEEP CHECKING VARIABLES +LB5B2 STX V41 SAVE ADDRESS OF THE END OF VARIABLES +LB5B4 LDX V41 GET CURRENT ARRAY POINTER +LB5B6 CMPX ARYEND COMPARE TO THE END OF ARRAYS + BEQ LB5EF BRANCH IF AT END OF ARRAYS + LDD 2,X GET LENGTH OF ARRAY AND DESCRIPTOR + ADDD V41 * ADD TO CURRENT ARRAY POINTER + STD V41 * AND SAVE IT + LDA 1,X GET 1ST CHARACTER OF VARIABLE NAME + BPL LB5B4 BRANCH IF NUMERIC ARRAY + LDB 4,X GET THE NUMBER OF DIMENSIONS IN THIS ARRAY + ASLB MULTIPLY BY 2 + ADDB #5 ADD FIVE BYTES (VARIABLE NAME, ARRAY +* LENGTH, NUMBER DIMENSIONS) + ABX X NOW POINTS TO START OF ARRAY ELEMENTS +LB5CA CMPX V41 AT END OF THIS ARRAY? + BEQ LB5B6 YES - CHECK FOR ANOTHER + BSR LB5D8 CHECK FOR STRING LOCATED IN +* UNORGANIZED STRING SPACE + BRA LB5CA KEEP CHECKING ELEMENTS IN THIS ARRAY +LB5D2 LDA 1,X GET F1RST BYTE OF VARIABLE NAME + LEAX 2,X MOVE POINTER TO DESCRIPTOR + BPL LB5EC BRANCH IF VARIABLE IS NUMERIC +* SEARCH FOR STRING - ENTER WITH X POINTING TO +* THE STRING DESCRIPTOR. IF STRING IS STORED +* BETWEEN V47 AND STRTAB, SAVE DESCRIPTOR POINTER +* IN V4B AND RESET V47 TO STRING ADDRESS +LB5D8 LDB ,X GET THE LENGTH OF THE STRING + BEQ LB5EC BRANCH IF NULL - NO STRING + LDD 2,X GET STARTING ADDRESS OF THE STRING + CMPD STRTAB COMPARE TO THE START OF STRING VARIABLES + BHI LB5EC BRANCH IF THIS STRING IS STORED IN +* THE STRING VARIABLES + CMPD V47 COMPARE TO START OF STRING SPACE + BLS LB5EC BRANCH IF NOT STORED IN THE STRING SPACE + STX V4B SAVE VARIABLE POINTER IF STORED IN STRING SPACE + STD V47 SAVE STRING STARTING ADDRESS +LB5EC LEAX 5,X MOVE TO NEXT VARIABLE DESCRIPTOR +LB5EE RTS +LB5EF LDX V4B GET ADDRESS OF THE DESCRIPTOR FOR THE +* STRING WHICH IS STORED IN THE HIGHEST RAM ADDRESS IN +* THE UNORGANIZED STRING SPACE + BEQ LB5EE BRANCH IF NONE FOUND AND REORGANIZATION DONE + CLRA CLEAR MS BYTE OF LENGTH + LDB ,X GET LENGTH OF STRING + DECB SUBTRACT ONE + ADDD V47 ADD LENGTH OF STRING TO ITS STARTING ADDRESS + STD V43 SAVE AS MOVE STARTING ADDRESS + LDX STRTAB POINT X TO THE START OF ORGANIZED STRING VARIABLES + STX V41 SAVE AS MOVE ENDING ADDRESS + JSR LAC20 MOVE STRING FROM CURRENT POSITION TO THE +* TOP OF UNORGANIZED STRING SPACE + LDX V4B POINT X TO STRING DESCRIPTOR + LDD V45 * GET NEW STARTING ADDRESS OF STRING AND + STD 2,X * SAVE IT IN DESCRIPTOR + LDX V45 GET NEW TOP OF UNORGANIZED STRING SPACE + LEAX -1,X MOVE POINTER BACK ONE + JMP LB593 JUMP BACK AND REORGANIZE SOME MORE + + +LB60F LDD FPA0+2 * GET DESCRIPTOR ADDRESS OF STRING A + PSHS B,A * AND SAVE IT ON THE STACK + JSR LB223 GET DESCRIPTOR ADDRESS OF STRING B + JSR LB146 TM' ERROR IF NUMERIC VARIABLE + PULS X * POINT X TO STRING A DESCRIPTOR + STX RESSGN * ADDRESS AND SAVE IT IN RESSGN + LDB ,X GET LENGTH OF STRING A + LDX FPA0+2 POINT X TO DESCRIPTOR OF STRING B + ADDB ,X ADD LENGTH OF STRING B TO STR1NG A + BCC LB62A BRANCH IF LENGTH < 256 + LDB #2*14 STRING TOO LONG' ERROR IF LENGTH > 255 + JMP LAC46 JUMP TO ERROR SERVICING ROUTINE +LB62A JSR LB50D RESERVE ROOM IN STRING SPACE FOR NEW STRING + LDX RESSGN GET DESCRIPTOR ADDRESS OF STRING A + LDB ,X GET LENGTH OF STRING A + BSR LB643 MOVE STRING A INTO RESERVED BUFFER IN STRING SPACE + LDX V4D GET DESCRIPTOR ADDRESS OF STRING B + BSR LB659 GET LENGTH AND ADDRESS OF STRING B + BSR LB645 MOVE STRING B INTO REST OF RESERVED BUFFER + LDX RESSGN POINT X TO DESCRIPTOR OF STRING A + BSR LB659 DELETE STRING A IF LAST STRING ON STRING STACK + JSR LB54C PUT STRING DESCRIPTOR ON THE STRING STACK + JMP LB168 BRANCH BACK TO EXPRESSION EVALUATION + +* MOVE (B) BYTES FROM 2,X TO FRESPC +LB643 LDX 2,X POINT X TO SOURCE ADDRESS +LB645 LDU FRESPC POINT U TO DESTINATION ADDRESS + INCB COMPENSATION FOR THE DECB BELOW + BRA LB64E GO MOVE THE BYTES +* MOVE B BYTES FROM (X) TO (U) +LB64A LDA ,X+ * GET A SOURCE BYTE AND MOVE IT + STA ,U+ * TO THE DESTINATION +LB64E DECB DECREMENT BYTE COUNTER + BNE LB64A BRANCH IF ALL BYTES NOT MOVED + STU FRESPC SAVE ENDING ADDRESS IN FRESPC + RTS +* RETURN LENGTH (ACCB) AND ADDRESS (X) OF +* STRING WHOSE DESCRIPTOR IS IN FPA0+2 +* DELETE THE STRING IF IT IS THE LAST ONE +* PUT ON THE STRING STACK. REMOVE STRING FROM STRING +* SPACE IF IT IS AT THE BOTTOM OF STRING VARIABLES. +LB654 JSR LB146 TM' ERROR IF VARIABLE TYPE = NUMERIC +LB657 LDX FPA0+2 GET ADDRESS OF SELECTED STRING DESCRIPTOR +LB659 LDB ,X GET LENGTH OF STRING + BSR LB675 * CHECK TO SEE IF THIS STRING DESCRIPTOR WAS + BNE LB672 * THE LAST ONE PUT ON THE STRING STACK AND +* * BRANCH IF NOT + LDX 5+2,X GET START ADDRESS OF STRING JUST REMOVED + LEAX -1,X MOVE POINTER DOWN ONE + CMPX STRTAB COMPARE TO START OF STRING VARIABLES + BNE LB66F BRANCH IF THIS STRING IS NOT AT THE BOTTOM +* OF STRING VARIABLES + PSHS B SAVE LENGTH; ACCA WAS CLEARED + ADDD STRTAB * ADD THE LENGTH OF THE JUST REMOVED STRING + STD STRTAB * TO THE START OF STRING VARIABLES - THIS WILL +* * REMOVE THE STRING FROM THE STRING SPACE + PULS B RESTORE LENGTH +LB66F LEAX 1,X ADD ONE TO POINTER + RTS +LB672 LDX 2,X *POINT X TO ADDRESS OF STRING NOT + RTS *ON THE STRING STACK +* REMOVE STRING FROM STRING STACK. ENTER WITH X +* POINTING TO A STRING DESCRIPTOR - DELETE THE +* STRING FROM STACK IF IT IS ON TOP OF THE +* STACK. IF THE STRING IS DELETED, SET THE ZERO FLAG +LB675 CMPX LASTPT *COMPARE TO LAST USED DESCRIPTOR ADDRESS + BNE LB680 *ON THE STRING STACK, RETURN IF DESCRIPTOR +* *ADDRESS NOT ON THE STRING STACK + STX TEMPPT SAVE LAST USED DESCRIPTOR AS NEXT AVAILABLE + LEAX -5,X * MOVE LAST USED DESCRIPTOR BACK 5 BYTES + STX LASTPT * AND SAVE AS THE LAST USED DESCRIPTOR ADDR + CLRA SET ZERO FLAG +LB680 RTS + +* LEN +LEN BSR LB686 POINT X TO PROPER STRING AND GET LENGTH +LB683 JMP LB4F3 CONVERT ACCB TO FP NUMBER IN FPA0 +* POINT X TO STRING ADDRESS LOAD LENGTH INTO +* ACCB. ENTER WITH THE STRING DESCRIPTOR IN +* BOTTOM TWO BYTES OF FPA0 +LB686 BSR LB654 GET LENGTH AND ADDRESS OF STRING + CLR VALTYP SET VARIABLE TYPE TO NUMERIC + TSTB SET FLAGS ACCORDING TO LENGTH + RTS + +* CHR$ +CHR JSR LB70E CONVERT FPA0 TO AN INTEGER IN ACCD +LB68F LDB #1 * RESERVE ONE BYTE IN + JSR LB56D * THE STRING SPACE + LDA FPA0+3 GET ASCII STRING VALUE + JSR LB511 SAVE RESERVED STRING DESCRIPTOR IN TEMP DESCRIPTOR + STA ,X SAVE THE STRING (IT’S ONLY ONE BYTE) +LB69B LEAS 2,S PURGE THE RETURN ADDRESS OFF OF THE STACK +LB69D JMP LB54C PUT TEMP DESCRIPTOR DATA ONTO STRING STACK + + +ASC BSR LB6A4 PUT 1ST CHARACTER OF STRING INTO ACCB + BRA LB683 CONVERT ACCB INTO FP NUMBER IN FPA0 +LB6A4 BSR LB686 POINT X TO STRING DESCRIPTOR + BEQ LB706 FC' ERROR IF NULL STRING + LDB ,X GET FIRST BYTE OF STRING + RTS + + +LEFT BSR LB6F5 GET ARGUMENTS FROM STACK +LB6AD CLRA CLEAR STRING POINTER OFFSET - OFFSET = 0 FOR LEFT$ +LB6AE CMPB ,X * COMPARE LENGTH PARAMETER TO LENGTH OF + BLS LB6B5 * STRING AND BRANCH IF LENGTH OF STRING +* >= LENGTH PARAMETER + LDB ,X USE LENGTH OF STRING OTHERWISE + CLRA CLEAR STRING POINTER OFFSET (0 FOR LEFT$) +LB6B5 PSHS B,A PUSH PARAMETERS ONTO STACK + JSR LB50F RESERVE ACCB BYTES IN THE STRING SPACE + LDX V4D POINT X TO STRING DESCRIPTOR + BSR LB659 GET ADDRESS OF OLD STRING (X=ADDRESS) + PULS B * PULL STRING POINTER OFFSET OFF OF THE STACK + ABX * AND ADD IT TO STRING ADDRESS + PULS B PULL LENGTH PARAMETER OFF OF THE STACK + JSR LB645 MOVE ACCB BYTES FROM (X) TO [FRESPC] + BRA LB69D PUT TEMP STRING DESCRIPTOR ONTO THE STRING STACK + +* RIGHT$ +RIGHT BSR LB6F5 GET ARGUMENTS FROM STACK + SUBA ,X ACCA=LENGTH PARAMETER - LENGTH OF OLD STRING + NEGA NOW ACCA = LENGTH OF OLD STRING + BRA LB6AE PUT NEW STRING IN THE STRING SPACE + +* MID$ +MID LDB #$FF * GET DEFAULT VALUE OF LENGTH AND + STB FPA0+3 * SAVE IT IN FPA0 + JSR GETCCH GET CURRENT CHARACTER FROM BASIC + CMPA #') ARGUMENT DELIMITER? + BEQ LB6DE YES - NO LENGTH PARAMETER GIVEN + JSR LB26D SYNTAX CHECK FOR COMMA + BSR LB70B EVALUATE NUMERIC EXPRESSION (LENGTH) +LB6DE BSR LB6F5 GET ARGUMENTS FROM STACK + BEQ LB706 FC' ERROR IF NULL STRING + CLRB CLEAR LENGTH COUNTER (DEFAULT VALUE) + DECA *SUOTRACT ONE FROM POSITION PARAMETER (THESE + CMPA ,X *ROUTINES EXPECT 1ST POSITION TO BE ZERO, NOT ONE) +* *AND COMPARE IT TO LENGTH OF OLD STRING + BCC LB6B5 IF POSITION > LENGTH OF OLD STRING, THEN NEW +* STRING WILL BE A NULL STRING + TFR A,B SAVE ABSOLUTE POSITION PARAMETER IN ACCB + SUBB ,X ACCB=POSITION-LENGTH OF OLD STRING + NEGB NOW ACCB=LENGTH OF OLDSTRING-POSITION + CMPB FPA0+3 *IF THE AMOUNT OF OLD STRING TO THE RIGHT OF + BLS LB6B5 *POSITION IS <= THE LENGTH PARAMETER, BRANCH AND +* USE ALL OF THE STRING TO THE RIGHT OF THE POSITION +* INSTEAD OF THE LENGTH PARAMETER + LDB FPA0+3 GET LENGTH OF NEW STRING + BRA LB6B5 PUT NEW STRING IN STRING SPACE +* DO A SYNTAX CHECK FOR ")", THEN PULL THE PREVIOUSLY CALCULATED NUMERIC +* ARGUMENT (ACCD) AND STRING ARGUMENT DESCRIPTOR ADDR OFF OF THE STACK +LB6F5 JSR LB267 SYNTAX CHECK FOR A ")" + LDU ,S LOAD THE RETURN ADDRESS INTO U REGISTER + LDX 5,S * GET ADDRESS OF STRING AND + STX V4D * SAVE IT IN V4D + LDA 4,S = PUT LENGTH OF STRING IN + LDB 4,S = BOTH ACCA AND ACCB + LEAS 7,S REMOVE DESCRIPTOR AND RETURN ADDRESS FROM STACK + TFR U,PC JUMP TO ADDRESS IN U REGISTER +LB706 JMP LB44A ILLEGAL FUNCTION CALL' +* EVALUATE AN EXPRESSION - RETURN AN INTEGER IN +* ACCB - 'FC' ERROR IF EXPRESSION > 255 +LB709 JSR GETNCH GET NEXT BASIC INPUT CHARACTER +LB70B JSR LB141 EVALUATE A NUMERIC EXPRESSION +LB70E JSR LB3E9 CONVERT FPA0 TO INTEGER IN ACCD + TSTA TEST MS BYTE OF INTEGER + BNE LB706 FC' ERROR IF EXPRESSION > 255 + JMP GETCCH GET CURRENT INPUT CHARACTER FROM BASIC + +* VAL +VAL JSR LB686 POINT X TO STRING ADDRESS + LBEQ LBA39 IF NULL STRING SET FPA0 + LDU CHARAD SAVE INPUT POINTER IN REGISTER U + STX CHARAD POINT INPUT POINTER TO ADDRESS OF STRING + ABX MOVE POINTER TO END OF STRING TERMINATOR + LDA ,X GET LAST BYTE OF STRING + PSHS U,X,A SAVE INPUT POINTER, STRING TERMINATOR +* ADDRESS AND CHARACTER + CLR ,X CLEAR STRING TERMINATOR : FOR ASCII - FP CONVERSION + JSR GETCCH GET CURRENT CHARACTER FROM BASIC + JSR LBD12 CONVERT AN ASCII STRING TO FLOATING POINT + PULS A,X,U RESTORE CHARACTERS AND POINTERS + STA ,X REPLACE STRING TERMINATOR + STU CHARAD RESTORE INPUT CHARACTER + RTS + +LB734 BSR LB73D * EVALUATE AN EXPRESSION, RETURN + STX BINVAL * THE VALUE IN X; STORE IT IN BINVAL +LB738 JSR LB26D SYNTAX CHECK FOR A COMMA + BRA LB70B EVALUATE EXPRESSION IN RANGE 0 <= X < 256 +* EVALUATE EXPRESSION : RETURN INTEGER PORTION IN X - 'FC' ERROR IF + +LB73D JSR LB141 EVALUATE NUMERIC EXPRESSION +LB740 LDA FP0SGN GET SIGN OF FPA0 MANTISSA + BMI LB706 ILLEGAL FUNCTION CALL' IF NEGATIVE + LDA FP0EXP GET EXPONENT OF FPA0 + CMPA #$90 COMPARE TO LARGEST POSITIVE INTEGER + BHI LB706 ILLEGAL FUNCTION CALL' IF TOO LARGE + JSR LBCC8 SHIFT BINARY POINT TO EXTREME RIGHT OF FPA0 + LDX FPA0+2 LOAD X WITH LOWER TWO BYTES OF FPA0 + RTS + +* PEEK +PEEK BSR LB740 CONVERT FPA0 TO INTEGER IN REGISTER X + LDB ,X GET THE VALUE BEING 'PEEK'ED + JMP LB4F3 CONVERT ACCB INTO A FP NUMBER + +* POKE +POKE BSR LB734 EVALUATE 2 EXPRESSIONS + LDX BINVAL GET THE ADDRESS TO BE 'POKE'ED + STB ,X STORE THE DATA IN THAT ADDRESS + RTS + + +* LIST +LIST PSHS CC SAVE ZERO FLAG ON STACK + JSR LAF67 CONVERT DECIMAL LINE NUMBER TO BINARY + JSR LAD01 * FIND RAM ADDRESS OF THAT LINE NUMBER AND + STX LSTTXT * SAVE IT IN LSTTXT + PULS CC GET ZERO FLAG FROM STACK + BEQ LB784 BRANCH IF END OF LINE + JSR GETCCH GET CURRENT CHARACTER FROM BASIC + BEQ LB789 BRANCH IF END OF LINE + CMPA #TOK_MINUS MINUS TOKEN (IS IT A RANGE OF LINE NUMBERS?) + BNE LB783 NO - RETURN + JSR GETNCH GET NEXT CHARACTER FROM BASIC + BEQ LB784 BRANCH IF END OF LINE + JSR LAF67 GET ENDING LINE NUMBER + BEQ LB789 BRANCH IF LEGAL LINE NUMBER +LB783 RTS +* LIST THE ENTIRE PROGRAM +LB784 LDU #$FFFF * SET THE DEFAULT ENDING LINE NUMBER + STU BINVAL * TO $FFFF +LB789 LEAS 2,S PURGE RETURN ADDRESS FROM THE STACK + LDX LSTTXT POINT X TO STARTING LINE ADDRESS +LB78D JSR LB95C MOVE CURSOR TO START OF A NEW LINE + JSR LA549 CHECK FOR A BREAK OR PAUSE + LDD ,X GET ADDRESS OF NEXT BASIC LINE + BNE LB79F BRANCH IF NOT END OF PROGRAM +LB797 + JMP LAC73 RETURN TO BASIC’S MAIN INPUT LOOP +LB79F STX LSTTXT SAVE NEW STARTING LINE ADDRESS + LDD 2,X * GET THE LINE NUMBER OF THIS LINE AND + CMPD BINVAL * COMPARE IT TO ENDING LINE NUMBER + BHI LB797 EXIT IF LINE NUMBER > ENDING LINE NUMBER + JSR LBDCC PRINT THE NUMBER IN ACCD ON SCREEN IN DECIMAL + JSR LB9AC SEND A SPACE TO CONSOLE OUT + LDX LSTTXT GET RAM ADDRESS OF THIS LINE + BSR LB7C2 UNCRUNCH A LINE + LDX [LSTTXT] POINT X TO START OF NEXT LINE + LDU #LINBUF+1 POINT U TO BUFFER FULL OF UNCRUNCHED LINE +LB7B9 LDA ,U+ GET A BYTE FROM THE BUFFER + BEQ LB78D BRANCH IF END OF BUFFER + JSR LB9B1 SEND CHARACTER TO CONSOLE OUT + BRA LB7B9 GET ANOTHER CHARACTER + +* UNCRUNCH A LINE INTO BASIC’S LINE INPUT BUFFER +LB7C2 LEAX 4,X MOVE POINTER PAST ADDRESS OF NEXT LINE AND LINE NUMBER + LDY #LINBUF+1 UNCRUNCH LINE INTO LINE INPUT BUFFER +LB7CB LDA ,X+ GET A CHARACTER + BEQ LB820 BRANCH IF END OF LINE + BMI LB7E6 BRANCH IF IT’S A TOKEN + CMPA #': CHECK FOR END OF SUB LINE + BNE LB7E2 BRNCH IF NOT END OF SUB LINE + LDB ,X GET CHARACTER FOLLOWING COLON + CMPB #TOK_ELSE TOKEN FOR ELSE? + BEQ LB7CB YES - DON’T PUT IT IN BUFFER + CMPB #TOK_SNGL_Q TOKEN FOR REMARK? + BEQ LB7CB YES - DON’T PUT IT IN BUFFER + FCB SKP2 SKIP TWO BYTES +LB7E0 LDA #'! EXCLAMATION POINT +LB7E2 BSR LB814 PUT CHARACTER IN BUFFER + BRA LB7CB GET ANOTHER CHARACTER + +LB7E6 LDU #COMVEC-10 FIRST DO COMMANDS + CMPA #$FF CHECK FOR SECONDARY TOKEN + BNE LB7F1 BRANCH IF NON SECONDARY TOKEN + LDA ,X+ GET SECONDARY TOKEN + LEAU 5,U BUMP IT UP TO SECONDARY FUNCTIONS +LB7F1 ANDA #$7F MASK OFF BIT 7 OF TOKEN +LB7F3 LEAU 10,U MOVE TO NEXT COMMAND TABLE + TST ,U IS THIS TABLE ENABLED? + BEQ LB7E0 NO - ILLEGAL TOKEN + SUBA ,U SUBTRACT THE NUMBER OF TOKENS FROM THE CURRENT TOKEN NUMBER + BPL LB7F3 BRANCH IF TOKEN NOT IN THIS TABLE + ADDA ,U RESTORE TOKEN NUMBER RELATIVE TO THIS TABLE + LDU 1,U POINT U TO COMMAND DICTIONARY TABLE +LB801 DECA DECREMENT TOKEN NUMBER + BMI LB80A BRANCH IF THIS IS THE CORRECT TOKEN +* SKIP THROUGH DICTIONARY TABLE TO START OF NEXT TOKEN +LB804 TST ,U+ GRAB A BYTE + BPL LB804 BRANCH IF BIT 7 NOT SET + BRA LB801 GO SEE IF THIS IS THE CORRECT TOKEN +LB80A LDA ,U GET A CHARACTER FROM DICTIONARY TABLE + BSR LB814 PUT CHARACTER IN BUFFER + TST ,U+ CHECK FOR START OF NEXT TOKEN + BPL LB80A BRANCH IF NOT DONE WITH THIS TOKEN + BRA LB7CB GO GET ANOTHER CHARACTER +LB814 CMPY #LINBUF+LBUFMX TEST FOR END OF LINE INPUT BUFFER + BCC LB820 BRANCH IF AT END OF BUFFER + ANDA #$7F MASK OFF BIT 7 + STA ,Y+ * SAVE CHARACTER IN BUFFER AND + CLR ,Y * CLEAR NEXT CHARACTER SLOT IN BUFFER +LB820 RTS +* +* CRUNCH THE LINE THAT THE INPUT POINTER IS +* POINTING TO INTO THE LINE INPUT BUFFER +* RETURN LENGTH OF CRUNCHED LINE IN ACCD +* +LB821 LDX CHARAD GET BASIC'S INPUT POINTER ADDRESS + LDU #LINBUF POINT X TO LINE INPUT BUFFER +LB829 CLR V43 CLEAR ILLEGAL TOKEN FLAG + CLR V44 CLEAR DATA FLAG +LB82D LDA ,X+ GET INPUT CHAR + BEQ LB852 BRANCH IF END OF LINE + TST V43 * CHECK ILLEGAL TOKEN FLAG & BRANCH IF NOT + BEQ LB844 * PROCESSING AN ILLEGAL TOKEN + JSR LB3A2 SET CARRY IF NOT UPPER CASE ALPHA + BCC LB852 BRANCH IF UPPER CASE ALPHA + CMPA #'0 * DON’T CRUNCH ASCII NUMERIC CHARACTERS + BLO LB842 * BRANCH IF NOT NUMERIC + CMPA #'9 * + BLS LB852 * BRANCH IF NUMERIC +* END UP HERE IF NOT UPPER CASE ALPHA OR NUMERIC +LB842 CLR V43 CLEAR ILLEGAL TOKEN FLAG +LB844 CMPA #SPACE SPACE? + BEQ LB852 DO NOT REMOVE SPACES + STA V42 SAVE INPUT CHARACTER AS SCAN DELIMITER + CMPA #'" CHECK FOR STRING DELIMITER + BEQ LB886 BRANCH IF STRING + TST V44 * CHECK DATA FLAG AND BRANCH IF CLEAR + BEQ LB86B * DO NOT CRUNCH DATA +LB852 STA ,U+ SAVE CHARACTER IN BUFFER + BEQ LB85C BRANCH IF END OF LINE + CMPA #': * CHECK FOR END OF SUBLINE + BEQ LB829 * AND RESET FLAGS IF END OF SUBLINE +LB85A BRA LB82D GO GET ANOTHER CHARACTER +LB85C CLR ,U+ * DOUBLE ZERO AT END OF LINE + CLR ,U+ * + TFR U,D SAVE ADDRESS OF END OF LINE IN ACCD + SUBD #LINHDR LENGTH OF LINE IN ACCD + LDX #LINBUF-1 * SET THE INPUT POINTER TO ONE BEFORE + STX CHARAD * THE START OF THE CRUNCHED LINE + RTS EXIT 'CRUNCH' +LB86B CMPA #'? CHECK FOR "?" - PRINT ABBREVIATION + BNE LB873 BRANCH IF NOT PRINT ABBREVIATION + LDA #TOK_PRINT * GET THE PRINT TOKEN AND SAVE IT + BRA LB852 * IN BUFFER +LB873 CMPA #'' APOSTROPHE IS SAME AS REM + BNE LB88A BRANCH IF NOT REMARK + LDD #$3A00+TOK_SNGL_Q COLON, REM TOKEN + STD ,U++ SAVE IN BUFFER +LB87C CLR V42 SET DELIMITER = 0 (END OF LINE) +LB87E LDA ,X+ SCAN TILL WE MATCH [V42] + BEQ LB852 BRANCH IF END OF LINE + CMPA V42 DELIMITER? + BEQ LB852 BRANCH OUT IF SO +LB886 STA ,U+ DON’T CRUNCH REMARKS OR STRINGS + BRA LB87E GO GET MORE STRING OR REMARK +LB88A CMPA #'0 * LESS THAN ASCII ZERO? + BCS LB892 * BRANCH IF SO + CMPA #';+1 = CHECK FOR NUMERIC VALUE, COLON OR SEMICOLON + BCS LB852 = AND INSERT IN BUFFER IF SO +LB892 LEAX -1,X MOVE INPUT POINTER BACK ONE + PSHS U,X SAVE POINTERS TO INPUT STRING, OUTPUT STRING + CLR V41 TOKEN FLAG 0 = COMMAND, FF = SECONDARY + LDU #COMVEC-10 POINT U TO COMMAND INTERPRETATION +* TABLE FOR BASIC - 10 +LB89B CLR V42 INITIALIZE V42 AS TOKEN COUNTER +LB89D LEAU 10,U MOVE TO NEXT COMMAND INTERPRETATION TABLE + LDA ,U GET NUMBER OF COMMANDS + BEQ LB8D4 GO DO SECONDARY FUNCTIONS IF NO COMMAND TABLE + LDY 1,U POINT Y TO COMMAND DICTIONARY TABLE +LB8A6 LDX ,S GET POINTER TO INPUT STRING +LB8A8 LDB ,Y+ GET A BYTE FROM DICTIONARY TABLE + SUBB ,X+ SUBTRACT INPUT CHARACTER + BEQ LB8A8 LOOP IF SAME + CMPB #$80 LAST CHAR IN RESERVED WORD TABLE HAD +* BIT 7 SET, SO IF WE HAVE $80 HERE +* THEN IT IS A GOOD COMPARE + BNE LB8EA BRANCH IF NO MATCH - CHECK ANOTHER COMMAND + LEAS 2,S DELETE OLD INPUT POINTER FROM STACK + PULS U GET POINTER TO OUTPUT STRING + ORB V42 OR IN THE TABLE POSITION TO MAKE THE TOKEN +* - NOTE THAT B ALREADY HAD $80 IN IT - + LDA V41 * CHECK TOKEN FLAG AND BRANCH + BNE LB8C2 * IF SECONDARY + CMPB #TOK_ELSE IS IT ELSE TOKEN? + BNE LB8C6 NO + LDA #': PUT A COLON (SUBLINE) BEFORE ELSE TOKEN +LB8C2 STD ,U++ SECONDARY TOKENS PRECEEDED BY $FF + BRA LB85A GO PROCESS MORE INPUT CHARACTERS +LB8C6 STB ,U+ SAVE THIS TOKEN + CMPB #TOK_DATA DATA TOKEN? + BNE LB8CE NO + INC V44 SET DATA FLAG +LB8CE CMPB #TOK_REM REM TOKEN? + BEQ LB87C YES +LB8D2 BRA LB85A GO PROCESS MORE INPUT CHARACTERS +* CHECK FOR A SECONDARY TOKEN +LB8D4 LDU #COMVEC-5 NOW DO SECONDARY FUNCTIONS + COM V41 TOGGLE THE TOKEN FLAG + BNE LB89B BRANCH IF NOW CHECKING SECONDARY COMMANDS + +* THIS CODE WILL PROCESS INPUT DATA WHICH CANNOT BE CRUNCHED AND SO +* IS ASSUMED TO BE ILLEGAL DATA OR AN ILLEGAL TOKEN + PULS X,U RESTORE INPUT AND OUTPUT POINTERS + LDA ,X+ * MOVE THE FIRST CHARACTER OF AN + STA ,U+ * ILLEGAL TOKEN + JSR LB3A2 SET CARRY IF NOT ALPHA + BCS LB8D2 BRANCH IF NOT ALPHA + COM V43 SET ILLEGAL TOKEN FLAG IF UPPER CASE ALPHA + BRA LB8D2 PROCESS MORE INPUT CHARACTERS +LB8EA INC V42 INCREMENT TOKEN COUNTER + DECA DECR COMMAND COUNTER + BEQ LB89D GET ANOTHER COMMAND TABLE IF DONE W/THIS ONE + LEAY -1,Y MOVE POINTER BACK ONE +LB8F1 LDB ,Y+ * GET TO NEXT + BPL LB8F1 * RESERVED WORD + BRA LB8A6 GO SEE IF THIS WORD IS A MATCH + +* PRINT +PRINT BEQ LB958 BRANCH IF NO ARGUMENT + BSR LB8FE CHECK FOR ALL PRINT OPTIONS + RTS +LB8FE +LB918 JSR XVEC9 CALL EXTENDED BASIC ADD-IN +LB91B BEQ LB965 RETURN IF END OF LINE +LB91D CMPA #TOK_TAB TOKEN FOR TAB( ? + BEQ LB97E YES + CMPA #', COMMA? + BEQ LB966 YES - ADVANCE TO NEXT TAB FIELD + CMPA #'; SEMICOLON? + BEQ LB997 YES - DO NOT ADVANCE CURSOR + JSR LB156 EVALUATE EXPRESSION + LDA VALTYP * GET VARIABLE TYPE AND + PSHS A * SAVE IT ON THE STACK + BNE LB938 BRANCH IF STRING VARIABLE + JSR LBDD9 CONVERT FP NUMBER TO AN ASCII STRING + JSR LB516 PARSE A STRING FROM (X-1) AND PUT +* DESCRIPTOR ON STRING STACK +LB938 BSR LB99F PRINT STRING POINTED TO BY X + PULS B GET VARIABLE TYPE BACK + JSR LA35F SET UP TAB WIDTH ZONE, ETC +LB949 TSTB CHECK CURRENT PRINT POSITION + BNE LB954 BRANCH IF NOT AT START OF LINE + JSR GETCCH GET CURRENT INPUT CHARACTER + CMPA #', COMMA? + BEQ LB966 SKIP TO NEXT TAB FIELD + BSR LB9AC SEND A SPACE TO CONSOLE OUT +LB954 JSR GETCCH GET CURRENT INPUT CHARACTER + BNE LB91D BRANCH IF NOT END OF LINE +LB958 LDA #CR * SEND A CR TO + BRA LB9B1 * CONSOLE OUT +LB95C JSR LA35F SET UP TAB WIDTH, ZONE ETC + BEQ LB958 BRANCH IF WIDTH = ZERO + LDA DEVPOS GET PRINT POSITION + BNE LB958 BRANCH IF NOT AT START OF LINE +LB965 RTS +* SKIP TO NEXT TAB FIELD +LB966 JSR LA35F SET UP TAB WIDTH, ZONE ETC + BEQ LB975 BRANCH IF LINE WIDTH = 0 (CASSETTE) + LDB DEVPOS GET CURRENT POSITION + CMPB DEVLCF COMPARE TO LAST TAB ZONE + BCS LB977 BRANCH IF < LAST TAB ZONE + BSR LB958 SEND A CARRIAGE RETURN TO CONSOLE OUT + BRA LB997 GET MORE DATA +LB975 LDB DEVPOS * +LB977 SUBB DEVCFW * SUBTRACT TAB FIELD WIDTH FROM CURRENT + BCC LB977 * POSITION UNTIL CARRY SET - NEGATING THE + NEGB * REMAINDER LEAVES THE NUMBER OF SPACES TO NEXT +* * TAB ZONE IN ACCB + BRA LB98E GO ADVANCE TO NEXT TAB ZONE + +* PRINT TAB( +LB97E JSR LB709 EVALUATE EXPRESSION - RETURN VALUE IN B + CMPA #') * 'SYNTAX' ERROR IF NOT ')' + LBNE LB277 * + JSR LA35F SET UP TAB WIDTH, ZONE ETC + SUBB DEVPOS GET DIFFERENCE OF PRINT POSITION & TAB POSITION + BLS LB997 BRANCH IF TAB POSITION < CURRENT POSITION +LB98E +LB992 BSR LB9AC SEND A SPACE TO CONSOLE OUT + DECB DECREMENT DIFFERENCE COUNT + BNE LB992 BRANCH UNTIL CURRENT POSITION = TAB POSITION +LB997 JSR GETNCH GET NEXT CHARACTER FROM BASIC + JMP LB91B LOOK FOR MORE PRINT DATA +* COPY A STRING FROM (X) TO CONSOLE OUT +LB99C JSR LB518 PARSE A STRING FROM X AND PUT +* DESCRIPTOR ON STRING STACK +LB99F JSR LB657 GET LENGTH OF STRING AND REMOVE +* DESCRIPTOR FROM STRING STACK + INCB COMPENSATE FOR DECB BELOW +LB9A3 DECB DECREMENT COUNTER + BEQ LB965 EXIT ROUTINE + LDA ,X+ GET A CHARACTER FROM X + BSR LB9B1 SEND TO CONSOLE OUT + BRA LB9A3 KEEP LOOPING +LB9AC LDA #SPACE SPACE TO CONSOLE OUT + FCB SKP2 SKIP NEXT TWO BYTES +LB9AF LDA #'? QUESTION MARK TO CONSOLE OUT +LB9B1 JMP PUTCHR JUMP TO CONSOLE OUT + +* FLOATING POINT MATH PACKAGE + +* ADD .5 TO FPA0 +LB9B4 LDX #LBEC0 FLOATING POINT CONSTANT (.5) + BRA LB9C2 ADD .5 TO FPA0 +* SUBTRACT FPA0 FROM FP NUMBER POINTED +* TO BY (X), LEAVE RESULT IN FPA0 +LB9B9 JSR LBB2F COPY PACKED FP DATA FROM (X) TO FPA1 + +* ARITHMETIC OPERATION (-) JUMPS HERE - SUBTRACT FPA0 FROM FPA1 (ENTER +* WITH EXPONENT OF FPA0 IN ACCB AND EXPONENT OF FPA1 IN ACCA) +LB9BC COM FP0SGN CHANGE MANTISSA SIGN OF FPA0 + COM RESSGN REVERSE RESULT SIGN FLAG + BRA LB9C5 GO ADD FPA1 AND FPA0 +* ADD FP NUMBER POINTED TO BY +* (X) TO FPA0 - LEAVE RESULT IN FPA0 +LB9C2 JSR LBB2F UNPACK PACKED FP DATA FROM (X) TO +* FPA1; RETURN EXPONENT OF FPA1 IN ACCA + +* ARITHMETIC OPERATION (+) JUMPS HERE - ADD FPA0 TO + +LB9C5 TSTB CHECK EXPONENT OF FPA0 + LBEQ LBC4A COPY FPA1 TO FPA0 IF FPA0 = + LDX #FP1EXP POINT X TO FPA1 +LB9CD TFR A,B PUT EXPONENT OF FPA1 INTO ACCB + TSTB CHECK EXPONENT + BEQ LBA3E RETURN IF EXPONENT = 0 (ADDING 0 TO FPA0) + SUBB FP0EXP SUBTRACT EXPONENT OF FPA0 FROM EXPONENT OF FPA1 + BEQ LBA3F BRANCH IF EXPONENTS ARE EQUAL + BCS LB9E2 BRANCH IF EXPONENT FPA0 > FPA1 + STA FP0EXP REPLACE FPA0 EXPONENT WITH FPA1 EXPONENT + LDA FP1SGN * REPLACE FPA0 MANTISSA SIGN + STA FP0SGN * WITH FPA1 MANTISSA SIGN + LDX #FP0EXP POINT X TO FPA0 + NEGB NEGATE DIFFERENCE OF EXPONENTS +LB9E2 CMPB #-8 TEST DIFFERENCE OF EXPONENTS + BLE LBA3F BRANCH IF DIFFERENCE OF EXPONENTS <= 8 + CLRA CLEAR OVERFLOW BYTE + LSR 1,X SHIFT MS BYTE OF MANTISSA; BIT 7 = 0 + JSR LBABA GO SHIFT MANTISSA OF (X) TO THE RIGHT (B) TIMES +LB9EC LDB RESSGN GET SIGN FLAG + BPL LB9FB BRANCH IF FPA0 AND FPA1 SIGNS ARE THE SAME + COM 1,X * COMPLEMENT MANTISSA POINTED + COM 2,X * TO BY (X) THE + COM 3,X * ADCA BELOW WILL + COM 4,X * CONVERT THIS OPERATION + COMA * INTO A NEG (MANTISSA) + ADCA #0 ADD ONE TO ACCA - COMA ALWAYS SETS THE CARRY FLAG +* THE PREVIOUS TWO BYTES MAY BE REPLACED BY A NEGA +* +* ADD MANTISSAS OF FPA0 AND FPA1, PUT RESULT IN FPA0 +LB9FB STA FPSBYT SAVE FPA SUB BYTE + LDA FPA0+3 * ADD LS BYTE + ADCA FPA1+3 * OF MANTISSA + STA FPA0+3 SAVE IN FPA0 LSB + LDA FPA0+2 * ADD NEXT BYTE + ADCA FPA1+2 * OF MANTISSA + STA FPA0+2 SAVE IN FPA0 + LDA FPA0+1 * ADD NEXT BYTE + ADCA FPA1+1 * OF MANTISSA + STA FPA0+1 SAVE IN FPA0 + LDA FPA0 * ADD MS BYTE + ADCA FPA1 * OF MANTISSA + STA FPA0 SAVE IN FPA0 + TSTB TEST SIGN FLAG + BPL LBA5C BRANCH IF FPA0 & FPA1 SIGNS WERE ALIKE +LBA18 BCS LBA1C BRANCH IF POSITIVE MANTISSA + BSR LBA79 NEGATE FPA0 MANTISSA + +* NORMALIZE FPA0 +LBA1C CLRB CLEAR TEMPORARY EXPONENT ACCUMULATOR +LBA1D LDA FPA0 TEST MSB OF MANTISSA + BNE LBA4F BRANCH IF <> 0 + LDA FPA0+1 * IF THE MSB IS + STA FPA0 * 0, THEN SHIFT THE + LDA FPA0+2 * MANTISSA A WHOLE BYTE + STA FPA0+1 * AT A TIME. THIS + LDA FPA0+3 * IS FASTER THAN ONE + STA FPA0+2 * BIT AT A TIME + LDA FPSBYT * BUT USES MORE MEMORY. + STA FPA0+3 * FPSBYT, THE CARRY IN + CLR FPSBYT * BYTE, REPLACES THE MATISSA LSB. + ADDB #8 SHIFTING ONE BYTE = 8 BIT SHIFTS; ADD 8 TO EXPONENT + CMPB #5*8 CHECK FOR 5 SHIFTS + BLT LBA1D BRANCH IF < 5 SHIFTS, IF > 5, THEN MANTISSA = 0 +LBA39 CLRA A ZERO EXPONENT = 0 FLOATING POINT +LBA3A STA FP0EXP ZERO OUT THE EXPONENT + STA FP0SGN ZERO OUT THE MANTISSA SIGN +LBA3E RTS +LBA3F BSR LBAAE SHIFT FPA0 MANTISSA TO RIGHT + CLRB CLEAR CARRY FLAG + BRA LB9EC +* SHIFT FPA0 LEFT ONE BIT UNTIL BIT 7 +* OF MATISSA MS BYTE = 1 +LBA44 INCB ADD ONE TO EXPONENT ACCUMULATOR + ASL FPSBYT SHIFT SUB BYTE ONE LEFT + ROL FPA0+3 SHIFT LS BYTE + ROL FPA0+2 SHIFT NS BYTE + ROL FPA0+1 SHIFT NS BYTE + ROL FPA0 SHIFT MS BYTE +LBA4F BPL LBA44 BRANCH IF NOT YET NORMALIZED + LDA FP0EXP GET CURRENT EXPONENT + PSHS B SAVE EXPONENT MODIFIER CAUSED BY NORMALIZATION + SUBA ,S+ SUBTRACT ACCUMULATED EXPONENT MODIFIER + STA FP0EXP SAVE AS NEW EXPONENT + BLS LBA39 SET FPA0 = 0 IF THE NORMALIZATION CAUSED +* MORE OR EQUAL NUMBER OF LEFT SHIFTS THAN THE +* SIZE OF THE EXPONENT + FCB SKP2 SKIP 2 BYTES +LBA5C BCS LBA66 BRANCH IF MANTISSA OVERFLOW + ASL FPSBYT SUB BYTE BIT 7 TO CARRY - USE AS ROUND-OFF +* FLAG (TRUNCATE THE REST OF SUB BYTE) + LDA #0 CLRA, BUT DO NOT CHANGE CARRY FLAG + STA FPSBYT CLEAR THE SUB BYTE + BRA LBA72 GO ROUND-OFF RESULT +LBA66 INC FP0EXP INCREMENT EXPONENT - MULTIPLY BY 2 + BEQ LBA92 OVERFLOW ERROR IF CARRY PAST $FF + ROR FPA0 * SHIFT MANTISSA + ROR FPA0+1 * ONE TO + ROR FPA0+2 * THE RIGHT - + ROR FPA0+3 * DIVIDE BY TWO +LBA72 BCC LBA78 BRANCH IF NO ROUND-OFF NEEDED + BSR LBA83 ADD ONE TO MANTISSA - ROUND OFF + BEQ LBA66 BRANCH iF OVERFLOW - MANTISSA = 0 +LBA78 RTS +* NEGATE FPA0 MANTISSA +LBA79 COM FP0SGN TOGGLE SIGN OF MANTISSA +LBA7B COM FPA0 * COMPLEMENT ALL 4 MANTISSA BYTES + COM FPA0+1 * + COM FPA0+2 * + COM FPA0+3 * +* ADD ONE TO FPA0 MANTISSA +LBA83 LDX FPA0+2 * GET BOTTOM 2 MANTISSA + LEAX 1,X * BYTES, ADD ONE TO + STX FPA0+2 * THEM AND SAVE THEM + BNE LBA91 BRANCH IF NO OVERFLOW + LDX FPA0 * IF OVERFLOW ADD ONE + LEAX 1,X * TO TOP 2 MANTISSA + STX FPA0 * BYTES AND SAVE THEM +LBA91 RTS +LBA92 LDB #2*5 OV' OVERFLOW ERROR + JMP LAC46 PROCESS AN ERROR +LBA97 LDX #FPA2-1 POINT X TO FPA2 +* SHIFT FPA POINTED TO BY (X) TO +* THE RIGHT -(B) TIMES. EXIT WITH +* ACCA CONTAINING DATA SHIFTED OUT +* TO THE RIGHT (SUB BYTE) AND THE DATA +* SHIFTED IN FROM THE LEFT WILL COME FROM FPCARY +LBA9A LDA 4,X GET LS BYTE OF MANTISSA (X) + STA FPSBYT SAVE IN FPA SUB BYTE + LDA 3,X * SHIFT THE NEXT THREE BYTES OF THE + STA 4,X * MANTISSA RIGHT ONE COMPLETE BYTE. + LDA 2,X * + STA 3,X * + LDA 1,X * + STA 2,X * + LDA FPCARY GET THE CARRY IN BYTE + STA 1,X STORE AS THE MS MANTISSA BYTE OF (X) +LBAAE ADDB #8 ADD 8 TO DIFFERENCE OF EXPONENTS + BLE LBA9A BRANCH IF EXPONENT DIFFERENCE < -8 + LDA FPSBYT GET FPA SUB BYTE + SUBB #8 CAST OUT THE 8 ADDED IN ABOVE + BEQ LBAC4 BRANCH IF EXPONENT DIFFERENCE = 0 + + +LBAB8 ASR 1,X * SHIFT MANTISSA AND SUB BYTE ONE BIT TO THE RIGHT +LBABA ROR 2,X * + ROR 3,X * + ROR 4,X * + RORA * + INCB ADD ONE TO EXPONENT DIFFERENCE + BNE LBAB8 BRANCH IF EXPONENTS NOT = +LBAC4 RTS +LBAC5 FCB $81,$00,$00,$00,$00 FLOATING POINT CONSTANT 1.0 + +* ARITHMETIC OPERATION (*) JUMPS HERE - MULTIPLY +* FPA0 BY (X) - RETURN PRODUCT IN FPA0 +LBACA BSR LBB2F MOVE PACKED FPA FROM (X) TO FPA1 +LBACC BEQ LBB2E BRANCH IF EXPONENT OF FPA0 = 0 + BSR LBB48 CALCULATE EXPONENT OF PRODUCT +* MULTIPLY FPA0 MANTISSA BY FPA1. NORMALIZE +* HIGH ORDER BYTES OF PRODUCT IN FPA0. THE +* LOW ORDER FOUR BYTES OF THE PRODUCT WILL +* BE STORED IN VAB-VAE. +LBAD0 LDA #0 * ZERO OUT MANTISSA OF FPA2 + STA FPA2 * + STA FPA2+1 * + STA FPA2+2 * + STA FPA2+3 * + LDB FPA0+3 GET LS BYTE OF FPA0 + BSR LBB00 MULTIPLY BY FPA1 + LDB FPSBYT * TEMPORARILY SAVE SUB BYTE 4 + STB VAE * + LDB FPA0+2 GET NUMBER 3 MANTISSA BYTE OF FPA0 + BSR LBB00 MULTIPLY BY FPA1 + LDB FPSBYT * TEMPORARILY SAVE SUB BYTE 3 + STB VAD * + LDB FPA0+1 GET NUMBER 2 MANTISSA BYTE OF FPA0 + BSR LBB00 MULTIPLY BY FPA1 + LDB FPSBYT * TEMPORARILY SAVE SUB BYTE 2 + STB VAC * + LDB FPA0 GET MS BYTE OF FPA0 MANTISSA + BSR LBB02 MULTIPLY BY FPA1 + LDB FPSBYT * TEMPORARILY SAVE SUB BYTE 1 + STB VAB * + JSR LBC0B COPY MANTISSA FROM FPA2 TO FPA0 + JMP LBA1C NORMALIZE FPA0 +LBB00 BEQ LBA97 SHIFT FPA2 ONE BYTE TO RIGHT +LBB02 COMA SET CARRY FLAG +* MULTIPLY FPA1 MANTISSA BY ACCB AND +* ADD PRODUCT TO FPA2 MANTISSA +LBB03 LDA FPA2 GET FPA2 MS BYTE + RORB ROTATE CARRY FLAG INTO SHIFT COUNTER; +* DATA BIT INTO CARRY + BEQ LBB2E BRANCH WHEN 8 SHIFTS DONE + BCC LBB20 DO NOT ADD FPA1 IF DATA BIT = 0 + LDA FPA2+3 * ADD MANTISSA LS BYTE + ADDA FPA1+3 * + STA FPA2+3 * + LDA FPA2+2 = ADD MANTISSA NUMBER 3 BYTE + ADCA FPA1+2 = + STA FPA2+2 = + LDA FPA2+1 * ADD MANTISSA NUMBER 2 BYTE + ADCA FPA1+1 * + STA FPA2+1 * + LDA FPA2 = ADD MANTISSA MS BYTE + ADCA FPA1 = +LBB20 RORA * ROTATE CARRY INTO MS BYTE + STA FPA2 * + ROR FPA2+1 = ROTATE FPA2 ONE BIT TO THE RIGHT + ROR FPA2+2 = + ROR FPA2+3 = + ROR FPSBYT = + CLRA CLEAR CARRY FLAG + BRA LBB03 KEEP LOOPING +LBB2E RTS +* UNPACK A FP NUMBER FROM (X) TO FPA1 +LBB2F LDD 1,X GET TWO MSB BYTES OF MANTISSA FROM +* FPA POINTED TO BY X + STA FP1SGN SAVE PACKED MANTISSA SIGN BYTE + ORA #$80 FORCE BIT 7 OF MSB MANTISSA = 1 + STD FPA1 SAVE 2 MSB BYTES IN FPA1 + LDB FP1SGN * GET PACKED MANTISSA SIGN BYTE. EOR W/FPA0 + EORB FP0SGN * SIGN - NEW SIGN POSITION IF BOTH OLD SIGNS ALIKE, + STB RESSGN * NEG IF BOTH OLD SIGNS DIFF. SAVE ADJUSTED +* * MANTISSA SIGN BYTE + LDD 3,X = GET 2 LSB BYTES OF MANTISSA + STD FPA1+2 = AND PUT IN FPA1 + LDA ,X * GET EXPONENT FROM (X) AND + STA FP1EXP * PUT IN EXPONENT OF FPA1 + LDB FP0EXP GET EXPONENT OF FPA0 + RTS +* CALCULATE EXPONENT FOR PRODUCT OF FPA0 & FPA1 +* ENTER WITH EXPONENT OF FPA1 IN ACCA +LBB48 TSTA TEST EXPONENT OF FPA1 + BEQ LBB61 PURGE RETURN ADDRESS & SET FPA0 = 0 + ADDA FP0EXP ADD FPA1 EXPONENT TO FPA0 EXPONENT + RORA ROTATE CARRY INTO BIT 7; BIT 0 INTO CARRY + ROLA SET OVERFLOW FLAG + BVC LBB61 BRANCH IF EXPONENT TOO LARGE OR SMALL + ADDA #$80 ADD $80 BIAS TO EXPONENT + STA FP0EXP SAVE NEW EXPONENT + BEQ LBB63 SET FPA0 + LDA RESSGN GET MANTISSA SIGN + STA FP0SGN SAVE AS MANTISSA SIGN OF FPA0 + RTS +* IF FPA0 = POSITIVE THEN 'OV' ERROR IF FPA0 +* = IS NEGATIVE THEN FPA0 = 0 +LBB5C LDA FP0SGN GET MANTISSA SIGN OF FPA0 + COMA CHANGE SIGN OF FPA0 MANTISSA + BRA LBB63 +LBB61 LEAS 2,S PURGE RETURN ADDRESS FROM STACK +LBB63 LBPL LBA39 ZERO FPA0 MANTISSA SIGN & EXPONENT +LBB67 JMP LBA92 OV' OVERFLOW ERROR +* FAST MULTIPLY BY 10 AND LEAVE RESULT IN FPA0 +LBB6A JSR LBC5F TRANSFER FPA0 TO FPA1 + BEQ LBB7C BRANCH IF EXPONENT = 0 + ADDA #2 ADD 2 TO EXPONENT (TIMES 4) + BCS LBB67 OV' ERROR IF EXPONENT > $FF + CLR RESSGN CLEAR RESULT SIGN BYTE + JSR LB9CD ADD FPA1 TO FPA0 (TIMES 5) + INC FP0EXP ADD ONE TO EXPONENT (TIMES 10) + BEQ LBB67 OV' ERROR IF EXPONENT > $FF +LBB7C RTS +LBB7D FCB $84,$20,$00,$00,$00 FLOATING POINT CONSTANT 10 +* DIVIDE FPA0 BY 10 +LBB82 JSR LBC5F MOVE FPA0 TO FPA1 + LDX #LBB7D POINT TO FLOATING POINT CONSTANT 10 + CLRB ZERO MANTISSA SIGN BYTE +LBB89 STB RESSGN STORE THE QUOTIENT MANTISSA SIGN BYTE + JSR LBC14 UNPACK AN FP NUMBER FROM (X) INTO FPA0 + FCB SKP2 SKIP TWO BYTES +* DIVIDE (X) BY FPA0-LEAVE NORMALIZED QUOTIENT IN FPA0 +LBB8F BSR LBB2F GET FP NUMBER FROM (X) TO FPA1 + +* ARITHMETIC OPERATION (/) JUMPS HERE. DIVIDE FPA1 BY FPA0 (ENTER WITH +* EXPONENT OF FPA1 IN ACCA AND FLAGS SET BY TSTA) + +* DIVIDE FPA1 BY FPA0 +LBB91 BEQ LBC06 /0' DIVIDE BY ZERO ERROR + NEG FP0EXP GET EXPONENT OF RECIPROCAL OF DIVISOR + BSR LBB48 CALCULATE EXPONENT OF QUOTIENT + INC FP0EXP INCREMENT EXPONENT + BEQ LBB67 OV' OVERFLOW ERROR + LDX #FPA2 POINT X TO MANTISSA OF FPA2 - HOLD +* TEMPORARY QUOTIENT IN FPA2 + LDB #4 5 BYTE DIVIDE + STB TMPLOC SAVE BYTE COUNTER + LDB #1 SHIFT COUNTER-AND TEMPORARY QUOTIENT BYTE +* COMPARE FPA0 MANTISSA TO FPA1 MANTISSA - +* SET CARRY FLAG IF FPA1 >= FPA0 +LBBA4 LDA FPA0 * COMPARE THE TWO MS BYTES + CMPA FPA1 * OF FPA0 AND FPA1 AND + BNE LBBBD * BRANCH IF <> + LDA FPA0+1 = COMPARE THE NUMBER 2 + CMPA FPA1+1 = BYTES AND + BNE LBBBD = BRANCH IF <> + LDA FPA0+2 * COMPARE THE NUMBER 3 + CMPA FPA1+2 * BYTES AND + BNE LBBBD * BRANCH IF <> + LDA FPA0+3 = COMPARE THE LS BYTES + CMPA FPA1+3 = AND BRANCH + BNE LBBBD = IF <> + COMA SET CARRY FLAG IF FPA0 = FPA1 +LBBBD TFR CC,A SAVE CARRY FLAG STATUS IN ACCA; CARRY +* CLEAR IF FPA0 > FPA1 + ROLB ROTATE CARRY INTO TEMPORARY QUOTIENT BYTE + BCC LBBCC CARRY WILL BE SET AFTER 8 SHIFTS + STB ,X+ SAVE TEMPORARY QUOTIENT + DEC TMPLOC DECREMENT BYTE COUNTER + BMI LBBFC BRANCH IF DONE + BEQ LBBF8 BRANCH IF LAST BYTE + LDB #1 RESET SHIFT COUNTER AND TEMPORARY QUOTIENT BYTE +LBBCC TFR A,CC RESTORE CARRY FLAG AND + BCS LBBDE BRANCH IF FPA0 =< FPA1 +LBBD0 ASL FPA1+3 * SHIFT FPA1 MANTISSA 1 BIT TO LEFT + ROL FPA1+2 * + ROL FPA1+1 * + ROL FPA1 * + BCS LBBBD BRANCH IF CARRY - ADD ONE TO PARTIAL QUOTIENT + BMI LBBA4 IF MSB OF HIGH ORDER MANTISSA BYTE IS +* SET, CHECK THE MAGNITUDES OF FPA0, FPA1 + BRA LBBBD CARRY IS CLEAR, CHECK ANOTHER BIT +* SUBTRACT FPA0 FROM FPA1 - LEAVE RESULT IN FPA1 +LBBDE LDA FPA1+3 * SUBTRACT THE LS BYTES OF MANTISSA + SUBA FPA0+3 * + STA FPA1+3 * + LDA FPA1+2 = THEN THE NEXT BYTE + SBCA FPA0+2 = + STA FPA1+2 = + LDA FPA1+1 * AND THE NEXT + SBCA FPA0+1 * + STA FPA1+1 * + LDA FPA1 = AND FINALLY, THE MS BYTE OF MANTISSA + SBCA FPA0 = + STA FPA1 = + BRA LBBD0 GO SHIFT FPA1 +LBBF8 LDB #$40 USE ONLY TWO BITS OF THE LAST BYTE (FIFTH) + BRA LBBCC GO SHIFT THE LAST BYTE +LBBFC RORB * SHIFT CARRY (ALWAYS SET HERE) INTO + RORB * BIT 5 AND MOVE + RORB * BITS 1,0 TO BITS 7,6 + STB FPSBYT SAVE SUB BYTE + BSR LBC0B MOVE MANTISSA OF FPA2 TO FPA0 + JMP LBA1C NORMALIZE FPA0 +LBC06 LDB #2*10 /0' ERROR + JMP LAC46 PROCESS THE ERROR +* COPY MANTISSA FROM FPA2 TO FPA0 +LBC0B LDX FPA2 * MOVE TOP 2 BYTES + STX FPA0 * + LDX FPA2+2 = MOVE BOTTOM 2 BYTES + STX FPA0+2 = + RTS +* COPY A PACKED FP NUMBER FROM (X) TO FPA0 +LBC14 PSHS A SAVE ACCA + LDD 1,X GET TOP TWO MANTISSA BYTES + STA FP0SGN SAVE MS BYTE OF MANTISSA AS MANTISSA SIGN + ORA #$80 UNPACK MS BYTE + STD FPA0 SAVE UNPACKED TOP 2 MANTISSA BYTES + CLR FPSBYT CLEAR MANTISSA SUB BYTE + LDB ,X GET EXPONENT TO ACCB + LDX 3,X * MOVE LAST 2 + STX FPA0+2 * MANTISSA BYTES + STB FP0EXP SAVE EXPONENT + PULS A,PC RESTORE ACCA AND RETURN + +LBC2A LDX #V45 POINT X TO MANTISSA OF FPA4 + BRA LBC35 MOVE FPA0 TO FPA4 +LBC2F LDX #V40 POINT X TO MANTISSA OF FPA3 + FCB SKP2 SKIP TWO BYTES +LBC33 LDX VARDES POINT X TO VARIABLE DESCRIPTOR IN VARDES +* PACK FPA0 AND MOVE IT TO ADDRESS IN X +LBC35 LDA FP0EXP * COPY EXPONENT + STA ,X * + LDA FP0SGN GET MANTISSA SIGN BIT + ORA #$7F MASK THE BOTTOM 7 BITS + ANDA FPA0 AND BIT 7 OF MANTISSA SIGN INTO BIT 7 OF MS BYTE + STA 1,X SAVE MS BYTE + LDA FPA0+1 * MOVE 2ND MANTISSA BYTE + STA 2,X * + LDU FPA0+2 = MOVE BOTTOM 2 MANTISSA BYTES + STU 3,X = + RTS +* MOVE FPA1 TO FPA0 RETURN W/MANTISSA SIGN IN ACCA +LBC4A LDA FP1SGN * COPY MANTISSA SIGN FROM +LBC4C STA FP0SGN * FPA1 TO FPA0 + LDX FP1EXP = COPY EXPONENT + MS BYTE FROM + STX FP0EXP = FPA1 TO FPA0 + CLR FPSBYT CLEAR MANTISSA SUB BYTE + LDA FPA1+1 * COPY 2ND MANTISSA BYTE + STA FPA0+1 * FROM FPA1 TO FPA0 + LDA FP0SGN GET MANTISSA SIGN + LDX FPA1+2 * COPY 3RD AND 4TH MANTISSA BYTE + STX FPA0+2 * FROM FPA1 TO FPA0 + RTS +* TRANSFER FPA0 TO FPA1 +LBC5F LDD FP0EXP * TRANSFER EXPONENT & MS BYTE + STD FP1EXP * + LDX FPA0+1 = TRANSFER MIDDLE TWO BYTES + STX FPA1+1 = + LDX FPA0+3 * TRANSFER BOTTOM TWO BYTES + STX FPA1+3 * + TSTA SET FLAGS ACCORDING TO EXPONENT + RTS +* CHECK FPA0; RETURN ACCB = 0 IF FPA0 = 0, +* ACCB = $FF IF FPA0 = NEGATIVE, ACCB = 1 IF FPA0 = POSITIVE +LBC6D LDB FP0EXP GET EXPONENT + BEQ LBC79 BRANCH IF FPA0 = 0 +LBC71 LDB FP0SGN GET SIGN OF MANTISSA +LBC73 ROLB BIT 7 TO CARRY + LDB #$FF NEGATIVE FLAG + BCS LBC79 BRANCH IF NEGATIVE MANTISSA + NEGB ACCB = 1 IF POSITIVE MANTISSA +LBC79 RTS + +* SGN +SGN BSR LBC6D SET ACCB ACCORDING TO SIGN OF FPA0 +* CONVERT A SIGNED NUMBER IN ACCB INTO A FLOATING POINT NUMBER +LBC7C STB FPA0 SAVE ACCB IN FPA0 + CLR FPA0+1 CLEAR NUMBER 2 MANTISSA BYTE OF FPA0 + LDB #$88 EXPONENT REQUIRED IF FPA0 IS TO BE AN INTEGER +LBC82 LDA FPA0 GET MS BYTE OF MANTISSA + SUBA #$80 SET CARRY IF POSITIVE MANTISSA +LBC86 STB FP0EXP SAVE EXPONENT + LDD ZERO * ZERO OUT ACCD AND + STD FPA0+2 * BOTTOM HALF OF FPA0 + STA FPSBYT CLEAR SUB BYTE + STA FP0SGN CLEAR SIGN OF FPA0 MANTISSA + JMP LBA18 GO NORMALIZE FPA0 + +* ABS +ABS CLR FP0SGN FORCE MANTISSA SIGN OF FPA0 POSITIVE + RTS +* COMPARE A PACKED FLOATING POINT NUMBER POINTED TO +* BY (X) TO AN UNPACKED FP NUMBER IN FPA0. RETURN +* ZERO FLAG SET AND ACCB = 0, IF EQUAL; ACCB = 1 IF +* FPA0 > (X); ACCB = $FF IF FPA0 < (X) +LBC96 LDB ,X CHECK EXPONENT OF (X) + BEQ LBC6D BRANCH IF FPA = 0 + LDB 1,X GET MS BYTE OF MANTISSA OF (X) + EORB FP0SGN EOR WITH SIGN OF FPA0 + BMI LBC71 BRANCH IF SIGNS NOT = +* COMPARE FPA0 WITH FP NUMBER POINTED TO BY (X). +* FPA0 IS NORMALIZED, (X) IS PACKED. +LBCA0 LDB FP0EXP * GET EXPONENT OF + CMPB ,X * FPA0, COMPARE TO EXPONENT OF + BNE LBCC3 * (X) AND BRANCH IF <>. + LDB 1,X * GET MS BYTE OF (X), KEEP ONLY + ORB #$7F * THE SIGN BIT - 'AND' THE BOTTOM 7 + ANDB FPA0 * BITS OF FPA0 INTO ACCB + CMPB 1,X = COMPARE THE BOTTOM 7 BITS OF THE MANTISSA + BNE LBCC3 = MS BYTE AND BRANCH IF <> + LDB FPA0+1 * COMPARE 2ND BYTE + CMPB 2,X * OF MANTISSA, + BNE LBCC3 * BRANCH IF <> + LDB FPA0+2 = COMPARE 3RD BYTE + CMPB 3,X = OF MANTISSA, + BNE LBCC3 = BRANCH IF <> + LDB FPA0+3 * SUBTRACT LS BYTE + SUBB 4,X * OF (X) FROM LS BYTE OF + BNE LBCC3 * FPA0, BRANCH IF <> + RTS RETURN IF FP (X) = FPA0 +LBCC3 RORB SHIFT CARRY TO BIT 7; CARRY SET IF FPA0 < (X) + EORB FP0SGN TOGGLE SIZE COMPARISON BIT IF FPA0 IS NEGATIVE + BRA LBC73 GO SET ACCB ACCORDING TO COMPARISON +* DE-NORMALIZE FPA0 : SHIFT THE MANTISSA UNTIL THE BINARY POINT IS TO THE RIGHT +* OF THE LEAST SIGNIFICANT BYTE OF THE MANTISSA +LBCC8 LDB FP0EXP GET EXPONENT OF FPA0 + BEQ LBD09 ZERO MANTISSA IF FPA0 = 0 + SUBB #$A0 SUBTRACT $A0 FROM FPA0 EXPONENT T THIS WILL YIELD +* THE NUMBER OF SHIFTS REQUIRED TO DENORMALIZE FPA0. WHEN +* THE EXPONENT OF FPA0 IS = ZERO, THEN THE BINARY POINT +* WILL BE TO THE RIGHT OF THE MANTISSA + LDA FP0SGN TEST SIGN OF FPA0 MANTISSA + BPL LBCD7 BRANCH IF POSITIVE + COM FPCARY COMPLEMENT CARRY IN BYTE + JSR LBA7B NEGATE MANTISSA OF FPA0 +LBCD7 LDX #FP0EXP POINT X TO FPA0 + CMPB #-8 EXPONENT DIFFERENCE < -8? + BGT LBCE4 YES + JSR LBAAE SHIFT FPA0 RIGHT UNTIL FPA0 EXPONENT = $A0 + CLR FPCARY CLEAR CARRY IN BYTE + RTS +LBCE4 CLR FPCARY CLEAR CARRY IN BYTE + LDA FP0SGN * GET SIGN OF FPA0 MANTISSA + ROLA * ROTATE IT INTO THE CARRY FLAG + ROR FPA0 ROTATE CARRY (MANTISSA SIGN) INTO BIT 7 +* OF LS BYTE OF MANTISSA + JMP LBABA DE-NORMALIZE FPA0 + +* INT +* THE INT STATEMENT WILL "DENORMALIZE" FPA0 - THAT IS IT WILL SHIFT THE BINARY POINT +* TO THE EXTREME RIGHT OF THE MANTISSA TO FORCE ITS EXPONENT TO BE $AO. ONCE +* THIS IS DONE THE MANTISSA OF FPA0 WILL CONTAIN THE FOUR LEAST SIGNIFICANT +* BYTES OF THE INTEGER PORTION OF FPA0. AT THE CONCLUSION OF THE DE-NORMALIZATION +* ONLY THE INTEGER PORTION OF FPA0 WILL REMAIN. +* +INT LDB FP0EXP GET EXPONENT OF FPA0 + CMPB #$A0 LARGEST POSSIBLE INTEGER EXPONENT + BCC LBD11 RETURN IF FPA0 >= 32768 + BSR LBCC8 SHIFT THE BINARY POINT ONE TO THE RIGHT OF THE +* LS BYTE OF THE FPA0 MANTISSA + STB FPSBYT ACCB = 0: ZERO OUT THE SUB BYTE + LDA FP0SGN GET MANTISSA SIGN + STB FP0SGN FORCE MANTISSA SIGN TO BE POSITIVE + SUBA #$80 SET CARRY IF MANTISSA + LDA #$A0 * GET DENORMALIZED EXPONENT AND + STA FP0EXP * SAVE IT IN FPA0 EXPONENT + LDA FPA0+3 = GET LS BYTE OF FPA0 AND + STA CHARAC = SAVE IT IN CHARAC + JMP LBA18 NORMALIZE FPA0 + +LBD09 STB FPA0 * LOAD MANTISSA OF FPA0 WITH CONTENTS OF ACCB + STB FPA0+1 * + STB FPA0+2 * + STB FPA0+3 * +LBD11 RTS * + +* CONVERT ASCII STRING TO FLOATING POINT +LBD12 LDX ZERO (X) = 0 + STX FP0SGN * ZERO OUT FPA0 & THE SIGN FLAG (COEFCT) + STX FP0EXP * + STX FPA0+1 * + STX FPA0+2 * + STX V47 INITIALIZE EXPONENT & EXPONENT SIGN FLAG TO ZERO + STX V45 INITIALIZE RIGHT DECIMAL CTR & DECIMAL PT FLAG TO 0 + BCS LBD86 IF CARRY SET (NUMERIC CHARACTER), ASSUME ACCA CONTAINS FIRST +* NUMERIC CHAR, SIGN IS POSITIVE AND SKIP THE RAM HOOK + JSR XVEC19 CALL EXTENDED BASIC ADD-IN +LBD25 CMPA #'- * CHECK FOR A LEADING MINUS SIGN AND BRANCH + BNE LBD2D * IF NO MINUS SIGN + COM COEFCT TOGGLE SIGN; 0 = +; FF = - + BRA LBD31 INTERPRET THE REST OF THE STRING +LBD2D CMPA #'+ * CHECK FOR LEADING PLUS SlGN AND BRANCH + BNE LBD35 * IF NOT A PLUS SIGN +LBD31 JSR GETNCH GET NEXT INPUT CHARACTER FROM BASIC + BCS LBD86 BRANCH IF NUMERIC CHARACTER +LBD35 CMPA #'. DECIMAL POlNT? + BEQ LBD61 YES + CMPA #'E "E" SHORTHAND FORM (SCIENTIFIC NOTATION)? + BNE LBD65 NO +* EVALUATE EXPONENT OF EXPONENTIAL FORMAT + JSR GETNCH GET NEXT INPUT CHARACTER FROM BASIC + BCS LBDA5 BRANCH IF NUMERIC + CMPA #TOK_MINUS MINUS TOKEN? + BEQ LBD53 YES + CMPA #'- ASCII MINUS? + BEQ LBD53 YES + CMPA #TOK_PLUS PLUS TOKEN? + BEQ LBD55 YES + CMPA #'+ ASCII PLUS? + BEQ LBD55 YES + BRA LBD59 BRANCH IF NO SIGN FOUND +LBD53 COM V48 SET EXPONENT SIGN FLAG TO NEGATIVE +* STRIP A DECIMAL NUMBER FROM BASIC LINE, CONVERT IT TO BINARY IN V47 +LBD55 JSR GETNCH GET NEXT INPUT CHARACTER FROM BASIC + BCS LBDA5 IF NUMERIC CHARACTER, CONVERT TO BINARY +LBD59 TST V48 * CHECK EXPONENT SIGN FLAG + BEQ LBD65 * AND BRANCH IF POSITIVE + NEG V47 NEGATE VALUE OF EXPONENT + BRA LBD65 +LBD61 COM V46 *TOGGLE DECIMAL PT FLAG AND INTERPRET ANOTHER + BNE LBD31 *CHARACTER IF <> 0 - TERMINATE INTERPRETATION +* IF SECOND DECIMAL POINT +* ADJUST FPA0 FOR THE DECIMAL EXPONENT IN V47 +LBD65 LDA V47 * GET EXPONENT, SUBTRACT THE NUMBER OF + SUBA V45 * PLACES TO THE RIGHT OF DECIMAL POINT + STA V47 * AND RESAVE IT. + BEQ LBD7F EXIT ROUTINE IF ADJUSTED EXPONENT = ZERO + BPL LBD78 BRANCH IF POSITIVE EXPONENT +LBD6F JSR LBB82 DIVIDE FPA0 BY 10 + INC V47 INCREMENT EXPONENT COUNTER (MULTIPLY BY 10) + BNE LBD6F KEEP MULTIPLYING + BRA LBD7F EXIT ROUTINE +LBD78 JSR LBB6A MULTIPLY FPA0 BY 10 + DEC V47 DECREMENT EXPONENT COUNTER (DIVIDE BY 10) + BNE LBD78 KEEP MULTIPLYING +LBD7F LDA COEFCT GET THE SIGN FLAG + BPL LBD11 RETURN IF POSITIVE + JMP LBEE9 TOGGLE MANTISSA SIGN OF FPA0, IF NEGATIVE +*MULTIPLY FPA0 BY TEN AND ADD ACCA TO THE RESULT +LBD86 LDB V45 *GET THE RIGHT DECIMAL COUNTER AND SUBTRACT + SUBB V46 *THE DECIMAL POINT FLAG FROM IT. IF DECIMAL POINT + STB V45 *FLAG=0, NOTHING HAPPENS. IF DECIMAL POINT FLAG IS +* -1, THEN RIGHT DECIMAL COUNTER IS INCREMENTED BY ONE + PSHS A SAVE NEW DIGIT ON STACK + JSR LBB6A MULTIPLY FPA0 BY 10 + PULS B GET NEW DIGIT BACK + SUBB #'0 MASK OFF ASCII + BSR LBD99 ADD ACCB TO FPA0 + BRA LBD31 GET ANOTHER CHARACTER FROM BASIC +LBD99 JSR LBC2F PACK FPA0 AND SAVE IT IN FPA3 + JSR LBC7C CONVERT ACCB TO FP NUMBER IN FPA0 + LDX #V40 * ADD FPA0 TO + JMP LB9C2 * FPA3 + + +LBDA5 LDB V47 + ASLB TIMES 2 + ASLB TIMES 4 + ADDB V47 ADD 1 = TIMES 5 + ASLB TIMES 10 + SUBA #'0 *MASK OFF ASCII FROM ACCA, PUSH + PSHS B *RESULT ONTO THE STACK AND + ADDA ,S+ ADD lT TO ACCB + STA V47 SAVE IN V47 + BRA LBD55 INTERPRET ANOTHER CHARACTER +* +LBDB6 FCB $9B,$3E,$BC,$1F,$FD * 99999999.9 +LBDBB FCB $9E,$6E,$6B,$27,$FD * 999999999 +LBDC0 FCB $9E,$6E,$6B,$28,$00 * 1E + 09 +* +LBDC5 LDX #LABE8-1 POINT X TO " IN " MESSAGE + BSR LBDD6 COPY A STRING FROM (X) TO CONSOLE OUT + LDD CURLIN GET CURRENT BASIC LINE NUMBER TO ACCD +* CONVERT VALUE IN ACCD INTO A DECIMAL NUMBER +* AND PRINT IT TO CONSOLE OUT +LBDCC STD FPA0 SAVE ACCD IN TOP HALF OF FPA0 + LDB #$90 REQ’D EXPONENT IF TOP HALF OF ACCD = INTEGER + COMA SET CARRY FLAG - FORCE POSITIVE MANTISSA + JSR LBC86 ZERO BOTTOM HALF AND SIGN OF FPA0, THEN +* SAVE EXPONENT AND NORMALIZE IT + BSR LBDD9 CONVERT FP NUMBER TO ASCII STRING +LBDD6 JMP LB99C COPY A STRING FROM (X) TO CONSOLE OUT + +* CONVERT FP NUMBER TO ASCII STRING +LBDD9 LDU #STRBUF+3 POINT U TO BUFFER WHICH WILL NOT CAUSE +* THE STRING TO BE STORED IN STRING SPACE +LBDDC LDA #SPACE SPACE = DEFAULT SIGN FOR POSITIVE # + LDB FP0SGN GET SIGN OF FPA0 + BPL LBDE4 BRANCH IF POSITIVE + LDA #'- ASCII MINUS SIGN +LBDE4 STA ,U+ STORE SIGN OF NUMBER + STU COEFPT SAVE BUFFER POINTER + STA FP0SGN SAVE SIGN (IN ASCII) + LDA #'0 ASCII ZERO IF EXPONENT = 0 + LDB FP0EXP GET FPA0 EXPONENT + LBEQ LBEB8 BRANCH IF FPA0 = 0 + CLRA BASE 10 EXPONENT=0 FOR FP NUMBER > 1 + CMPB #$80 CHECK EXPONENT + BHI LBDFF BRANCH IF FP NUMBER > 1 +* IF FPA0 < 1.0, MULTIPLY IT BY 1E+09 TO SPEED UP THE CONVERSION PROCESS + LDX #LBDC0 POINT X TO FP 1E+09 + JSR LBACA MULTIPLY FPA0 BY (X) + LDA #-9 BASE 10 EXPONENT = -9 +LBDFF STA V45 BASE 10 EXPONENT +* PSEUDO - NORMALIZE THE FP NUMBER TO A VALUE IN THE RANGE +* OF 999,999,999 RO 99,999,999.9 - THIS IS THE LARGEST +* NUMBER RANGE IN WHICH ALL OF THE DIGITS ARE +* SIGNIFICANT WHICH CAN BE DISPLAYED WITHOUT USING +* SCIENTIFIC NOTATION +LBE01 LDX #LBDBB POINT X TO FP 999,999,999 + JSR LBCA0 COMPARE FPA0 TO 999,999,999 + BGT LBE18 BRANCH IF > 999,999,999 +LBE09 LDX #LBDB6 POINT X TO FP 99,999,999.9 + JSR LBCA0 COMPARE FPA0 TO 99,999,999.9 + BGT LBE1F BRANCH IF > 99,999,999.9 (IN RANGE) + JSR LBB6A MULTIPLY FPA0 BY 10 + DEC V45 SUBTRACT ONE FROM DECIMAL OFFSET + BRA LBE09 PSEUDO - NORMALIZE SOME MORE +LBE18 JSR LBB82 DIVIDE FPA0 BY 10 + INC V45 ADD ONE TO BASE 10 EXPONENT + BRA LBE01 PSEUDO - NORMALIZE SOME MORE +LBE1F JSR LB9B4 ADD .5 TO FPA0 (ROUND OFF) + JSR LBCC8 CONVERT FPA0 TO AN INTEGER + LDB #1 DEFAULT DECIMAL POINT FLAG (FORCE IMMED DECIMAL PT) + LDA V45 * GET BASE 10 EXPONENT AND ADD TEN TO IT + ADDA #9+1 * (NUMBER ‘NORMALIZED’ TO 9 PLACES & DECIMAL PT) + BMI LBE36 BRANCH IF NUMBER < 1.0 + CMPA #9+2 NINE PLACES MAY BE DISPLAYED WITHOUT +* USING SCIENTIFIC NOTATION + BCC LBE36 BRANCH IF SCIENTIFIC NOTATION REQUIRED + DECA * SUBTRACT 1 FROM MODIFIED BASE 10 EXPONENT CTR + TFR A,B * AND SAVE IT IN ACCB (DECiMAL POINT FLAG) + LDA #2 FORCE EXPONENT = 0 - DON'T USE SCIENTIFIC NOTATION +LBE36 DECA * SUBTRACT TWO (WITHOUT AFFECTING CARRY) + DECA * FROM BASE 10 EXPONENT + STA V47 SAVE EXPONENT - ZERO EXPONENT = DO NOT DISPLAY +* IN SCIENTIFIC NOTATION + STB V45 DECIMAL POINT FLAG - NUMBER OF PLACES TO +* LEFT OF DECIMAL POINT + BGT LBE4B BRANCH IF >= 1 + LDU COEFPT POINT U TO THE STRING BUFFER + LDA #'. * STORE A PERIOD + STA ,U+ * IN THE BUFFER + TSTB CHECK DECIMAL POINT FLAG + BEQ LBE4B BRANCH IF NOTHING TO LEFT OF DECIMAL POINT + LDA #'0 * STORE A ZERO + STA ,U+ * IN THE BUFFER + +* CONVERT FPA0 INTO A STRING OF ASCII DIGITS +LBE4B LDX #LBEC5 POINT X TO FP POWER OF 10 MANTISSA + LDB #0+$80 INITIALIZE DIGIT COUNTER TO 0+$80 +* BIT 7 SET IS USED TO INDICATE THAT THE POWER OF 10 MANTISSA +* IS NEGATIVE. WHEN YOU 'ADD' A NEGATIVE MANTISSA, IT IS +* THE SAME AS SUBTRACTING A POSITIVE ONE AND BIT 7 OF ACCB IS HOW +* THE ROUTINE KNOWS THAT A 'SUBTRACTION' IS OCCURING. +LBE50 LDA FPA0+3 * ADD MANTISSA LS + ADDA 3,X * BYTE OF FPA0 + STA FPA0+3 * AND (X) + LDA FPA0+2 = ADD MANTISSA + ADCA 2,X = NUMBER 3 BYTE OF + STA FPA0+2 = FPA0 AND (X) + LDA FPA0+1 * ADD MANTISSA + ADCA 1,X * NUMBER 2 BYTE OF + STA FPA0+1 * FPA0 AND (X) + LDA FPA0 = ADD MANTISSA + ADCA ,X = MS BYTE OF + STA FPA0 = FPA0 AND (X) + INCB ADD ONE TO DIGIT COUNTER + RORB ROTATE CARRY INTO BIT 7 + ROLB *SET OVERFLOW FLAG AND BRANCH IF CARRY = 1 AND + BVC LBE50 *POSITIVE MANTISSA OR CARRY = 0 AND NEG MANTISSA + BCC LBE72 BRANCH IF NEGATIVE MANTISSA + SUBB #10+1 * TAKE THE 9’S COMPLEMENT IF + NEGB * ADDING MANTISSA +LBE72 ADDB #'0-1 ADD ASCII OFFSET TO DIGIT + LEAX 4,X MOVE TO NEXT POWER OF 10 MANTISSA + TFR B,A SAVE DIGIT IN ACCA + ANDA #$7F MASK OFF BIT 7 (ADD/SUBTRACT FLAG) + STA ,U+ STORE DIGIT IN STRING BUFFER + DEC V45 DECREMENT DECIMAL POINT FLAG + BNE LBE84 BRANCH IF NOT TIME FOR DECIMAL POINT + LDA #'. * STORE DECIMAL POINT IN + STA ,U+ * STRING BUFFER +LBE84 COMB TOGGLE BIT 7 (ADD/SUBTRACT FLAG) + ANDB #$80 MASK OFF ALL BUT ADD/SUBTRACT FLAG + CMPX #LBEC5+36 COMPARE X TO END OF MANTISSA TABLE + BNE LBE50 BRANCH IF NOT AT END OF TABLE +* BLANK TRAILING ZEROS AND STORE EXPONENT IF ANY +LBE8C LDA ,-U GET THE LAST CHARACTER; MOVE POINTER BACK + CMPA #'0 WAS IT A ZERO? + BEQ LBE8C IGNORE TRAILING ZEROS IF SO + CMPA #'. CHECK FOR DECIMAL POINT + BNE LBE98 BRANCH IF NOT DECIMAL POINT + LEAU -1,U STEP OVER THE DECIMAL POINT +LBE98 LDA #'+ ASCII PLUS SIGN + LDB V47 GET SCIENTIFIC NOTATION EXPONENT + BEQ LBEBA BRANCH IF NOT SCIENTIFIC NOTATION + BPL LBEA3 BRANCH IF POSITIVE EXPONENT + LDA #'- ASCII MINUS SIGN + NEGB NEGATE EXPONENT IF NEGATIVE +LBEA3 STA 2,U STORE EXPONENT SIGN IN STRING + LDA #'E * GET ASCII ‘E’ (SCIENTIFIC NOTATION + STA 1,U * FLAG) AND SAVE IT IN THE STRING + LDA #'0-1 INITIALIZE ACCA TO ASCII ZERO + + +LBEAB INCA ADD ONE TO 10’S DIGIT OF EXPONENT + SUBB #10 SUBTRACT 10 FROM ACCB + BCC LBEAB ADD 1 TO 10’S DIGIT IF NO CARRY + ADDB #'9+1 CONVERT UNITS DIGIT TO ASCII + STD 3,U SAVE EXPONENT IN STRING + CLR 5,U CLEAR LAST BYTE (TERMINATOR) + BRA LBEBC GO RESET POINTER +LBEB8 STA ,U STORE LAST CHARACTER +LBEBA CLR 1,U CLEAR LAST BYTE (TERMINATOR - REQUIRED BY +* PRINT SUBROUTINES) +LBEBC LDX #STRBUF+3 RESET POINTER TO START OF BUFFER + RTS +* +LBEC0 FCB $80,$00,$00,$00,$00 FLOATING POINT .5 +* +*** TABLE OF UNNORMALIZED POWERS OF 10 +LBEC5 FCB $FA,$0A,$1F,$00 -100000000 +LBEC9 FCB $00,$98,$96,$80 10000000 +LBECD FCB $FF,$F0,$BD,$C0 -1000000 +LBED1 FCB $00,$01,$86,$A0 100000 +LBED5 FCB $FF,$FF,$D8,$F0 -10000 +LBED9 FCB $00,$00,$03,$E8 1000 +LBEDD FCB $FF,$FF,$FF,$9C -100 +LBEE1 FCB $00,$00,$00,$0A 10 +LBEE5 FCB $FF,$FF,$FF,$FF -1 +* +* +LBEE9 LDA FP0EXP GET EXPONENT OF FPA0 + BEQ LBEEF BRANCH IF FPA0 = 0 + COM FP0SGN TOGGLE MANTISSA SIGN OF FPA0 +LBEEF RTS +* EXPAND A POLYNOMIAL OF THE FORM +* AQ+BQ**3+CQ**5+DQ**7.... WHERE Q = FPA0 +* AND THE X REGISTER POINTS TO A TABLE OF +* COEFFICIENTS A,B,C,D.... +LBEF0 STX COEFPT SAVE COEFFICIENT TABLE POINTER + JSR LBC2F MOVE FPA0 TO FPA3 + BSR LBEFC MULTIPLY FPA3 BY FPA0 + BSR LBF01 EXPAND POLYNOMIAL + LDX #V40 POINT X TO FPA3 +LBEFC JMP LBACA MULTIPLY (X) BY FPA0 + +* CALCULATE THE VALUE OF AN EXPANDED POLYNOMIAL +* EXPRESSION. ENTER WITH (X) POINTING TO A TABLE +* OF COEFFICIENTS, THE FIRST BYTE OF WHICH IS THE +* NUMBER OF (COEFFICIENTS-1) FOLLOWED BY THAT NUMBER +* OF PACKED FLOATING POINT NUMBERS. THE +* POLYNOMIAL IS EVALUATED AS FOLLOWS: VALUE = +* (((FPA0*Y0+Y1)*FPA0+Y2)*FPA0…YN) +LBEFF STX COEFPT SAVE COEFFICIENT TABLE POINTER +LBF01 JSR LBC2A MOVE FPA0 TO FPA4 + LDX COEFPT GET THE COEFFICIENT POINTER + LDB ,X+ GET THE TOP OF COEFFICIENT TABLE TO + STB COEFCT * USE AND STORE IT IN TEMPORARY COUNTER + STX COEFPT SAVE NEW COEFFICIENT POINTER +LBF0C BSR LBEFC MULTIPLY (X) BY FPA0 + LDX COEFPT *GET COEFFICIENT POINTER + LEAX 5,X *MOVE TO NEXT FP NUMBER + STX COEFPT *SAVE NEW COEFFICIENT POINTER + JSR LB9C2 ADD (X) AND FPA0 + LDX #V45 POINT (X) TO FPA4 + DEC COEFCT DECREMENT TEMP COUNTER + BNE LBF0C BRANCH IF MORE COEFFICIENTS LEFT + RTS + +* RND +RND JSR LBC6D TEST FPA0 + BMI LBF45 BRANCH IF FPA0 = NEGATIVE + BEQ LBF3B BRANCH IF FPA0 = 0 + BSR LBF38 CONVERT FPA0 TO AN INTEGER + JSR LBC2F PACK FPA0 TO FPA3 + BSR LBF3B GET A RANDOM NUMBER: FPA0 < 1.0 + LDX #V40 POINT (X) TO FPA3 + BSR LBEFC MULTIPLY (X) BY FPA0 + LDX #LBAC5 POINT (X) TO FP VALUE OF 1.0 + JSR LB9C2 ADD 1.0 TO FPA0 +LBF38 JMP INT CONVERT FPA0 TO AN INTEGER +* CALCULATE A RANDOM NUMBER IN THE RANGE 0.0 < X <= 1.0 +LBF3B LDX RVSEED+1 * MOVE VARIABLE + STX FPA0 * RANDOM NUMBER + LDX RVSEED+3 * SEED TO + STX FPA0+2 * FPA0 +LBF45 LDX RSEED = MOVE FIXED + STX FPA1 = RANDOM NUMBER + LDX RSEED+2 = SEED TO + STX FPA1+2 = MANTISSA OF FPA0 + JSR LBAD0 MULTIPLY FPA0 X FPA1 + LDD VAD GET THE TWO LOWEST ORDER PRODUCT BYTES + ADDD #$658B ADD A CONSTANT + STD RVSEED+3 SAVE NEW LOW ORDER VARIABLE RANDOM # SEED + STD FPA0+2 SAVE NEW LOW ORDER BYTES OF FPA0 MANTISSA + LDD VAB GET 2 MORE LOW ORDER PRODUCT BYTES + ADCB #$B0 ADD A CONSTANT + ADCA #5 ADD A CONSTANT + STD RVSEED+1 SAVE NEW HIGH ORDER VARIABLE RANDOM # SEED + STD FPA0 SAVE NEW HIGH ORDER FPA0 MANTISSA + CLR FP0SGN FORCE FPA0 MANTISSA = POSITIVE + LDA #$80 * SET FPA0 BIASED EXPONENT + STA FP0EXP * TO 0 1 < FPA0 < 0 + LDA FPA2+2 GET A BYTE FROM FPA2 (MORE RANDOMNESS) + STA FPSBYT SAVE AS SUB BYTE + JMP LBA1C NORMALIZE FPA0 +* +RSEED FDB $40E6 *CONSTANT RANDOM NUMBER GENERATOR SEED + FDB $4DAB * + +* SIN +* THE SIN FUNCTION REQUIRES AN ARGUMENT IN RADIANS AND WILL REPEAT ITSELF EVERY +* 2*PI RADIANS. THE ARGUMENT IS DIVIDED BY 2*PI AND ONLY THE FRACTIONAL PART IS +* RETAINED. SINCE THE ARGUMENT WAS DIVIDED BY 2*P1, THE COEFFICIENTS MUST BE +* MULTIPLIED BY THE APPROPRIATE POWER OF 2*PI. + +* SIN IS EVALUATED USING THE TRIGONOMETRIC IDENTITIES BELOW: +* SIN(X)=SIN(PI-X) & -SIN(PI/2-X)=SIN((3*PI)/2+X) +SIN JSR LBC5F COPY FPA0 TO FPA1 + LDX #LBFBD POINT (X) TO 2*PI + LDB FP1SGN *GET MANTISSA SIGN OF FPA1 + JSR LBB89 *AND DIVIDE FPA0 BY 2*PI + JSR LBC5F COPY FPA0 TO FPA1 + BSR LBF38 CONVERT FPA0 TO AN INTEGER + CLR RESSGN SET RESULT SIGN = POSITIVE + LDA FP1EXP *GET EXPONENT OF FPA1 + LDB FP0EXP *GET EXPONENT OF FPA0 + JSR LB9BC *SUBTRACT FPA0 FROM FPA1 +* NOW FPA0 CONTAINS ONLY THE FRACTIONAL PART OF ARGUMENT/2*PI + LDX #LBFC2 POINT X TO FP (.25) + JSR LB9B9 SUBTRACT FPA0 FROM .25 (PI/2) + LDA FP0SGN GET MANTISSA SIGN OF FPA0 + PSHS A SAVE IT ON STACK + BPL LBFA6 BRANCH IF MANTISSA POSITIVE + JSR LB9B4 ADD .5 (PI) TO FPA0 + LDA FP0SGN GET SIGN OF FPA0 + BMI LBFA9 BRANCH IF NEGATIVE + COM RELFLG COM IF +(3*PI)/2 >= ARGUMENT >+ PI/2 (QUADRANT FLAG) +LBFA6 JSR LBEE9 TOGGLE MANTISSA SIGN OF FPA0 +LBFA9 LDX #LBFC2 POINT X TO FP (.25) + JSR LB9C2 ADD .25 (PI/2) TO FPA0 + PULS A GET OLD MANTISSA SIGN + TSTA * BRANCH IF OLD + BPL LBFB7 * SIGN WAS POSITIVE + JSR LBEE9 TOGGLE MANTISSA SIGN +LBFB7 LDX #LBFC7 POINT X TO TABLE OF COEFFICIENTS + JMP LBEF0 GO CALCULATE POLYNOMIAL VALUE + +LBFBD FCB $83,$49,$0F,$DA,$A2 6.28318531 (2*PI) +LBFC2 FCB $7F,$00,$00,$00,$00 .25 + + +LBFC7 FCB 6-1 SIX COEFFICIENTS +LBFC8 FCB $84,$E6,$1A,$2D,$1B * -((2*PI)**11)/11! +LBFCD FCB $86,$28,$07,$FB,$F8 * ((2*PI)**9)/9! +LBFD2 FCB $87,$99,$68,$89,$01 * -((2*PI)**7)/7! +LBFD7 FCB $87,$23,$35,$DF,$E1 * ((2*PI)**5)/5! +LBFDC FCB $86,$A5,$5D,$E7,$28 * -((2*PI)**3)/3! +LBFE1 FCB $83,$49,$0F,$DA,$A2 * + + FCB $A1,$54,$46,$8F,$13 UNUSED GARBAGE BYTES + FCB $8F,$52,$43,$89,$CD UNUSED GARBAGE BYTES +* EXTENDED BASIC + +* COS +* THE VALUE OF COS(X) IS DETERMINED BY THE TRIG IDENTITY COS(X)=SIN((PI/2)+X) +COS LDX #L83AB POINT X TO FP CONSTANT (P1/2) + JSR LB9C2 ADD FPA0 TO (X) +L837E JMP SIN JUMP TO SIN ROUTINE + +* TAN +* THE VALUE OF TAN(X) IS DETERMINED BY THE TRIG IDENTITY TAN(X)=SIN(X)/COS(X) +TAN JSR LBC2F PACK FPA0 AND MOVE IT TO FPA3 + CLR RELFLG RESET QUADRANT FLAG + BSR L837E CALCULATE SIN OF ARGUMENT + LDX #V4A POINT X TO FPA5 + JSR LBC35 PACK FPA0 AND MOVE IT TO FPA5 + LDX #V40 POINT X TO FPA3 + JSR LBC14 MOVE FPA3 TO FPA0 + CLR FP0SGN FORCE FPA0 MANTISSA TO BE POSITIVE + LDA RELFLG GET THE QUADRANT FLAG - COS NEGATIVE IN QUADS 2,3 + BSR L83A6 CALCULATE VALUE OF COS(FPA0) + TST FP0EXP CHECK EXPONENT OF FPA0 + LBEQ LBA92 ‘OV’ ERROR IF COS(X)=0 + LDX #V4A POINT X TO FPA5 +L83A3 JMP LBB8F DIVIDE (X) BY FPA0 - SIN(X)/COS(X) +L83A6 PSHS A SAVE SIGN FLAG ON STACK + JMP LBFA6 EXPAND POLYNOMIAL + +L83AB FCB $81,$49,$0F,$DA,$A2 1.57079633 (PI/2) + +* ATN +* A 12 TERM TAYLOR SERIES IS USED TO EVALUATE THE +* ARCTAN EXPRESSION. TWO DIFFERENT FORMULI ARE USED +* TO EVALUATE THE EXPRESSION DEPENDING UPON +* WHETHER OR NOT THE ARGUMENT SQUARED IS > OR < 1.0 + +* IF X**2<1 THEN ATN=X-(X**3)/3+(X**5)/5-(X**7)/7. . . +* IF X**2>=1 THEN ATN=PI/2-(1/X-1/((X**3)*3)+(1/((X**5)*5)-. . .) + +ATN LDA FP0SGN * GET THE SIGN OF THE MANTISSA AND + PSHS A * SAVE IT ON THE STACK + BPL L83B8 BRANCH IF POSITIVE MANTISSA + BSR L83DC CHANGE SIGN OF FPA0 +L83B8 LDA FP0EXP * GET EXPONENT OF FPA0 AND + PSHS A * SAVE IT ON THE STACK + CMPA #$81 IS FPAO < 1.0? + BLO L83C5 YES + LDX #LBAC5 POINT X TO FP CONSTANT 1.0 + BSR L83A3 GET RECIPROCAL OF FPA0 +L83C5 LDX #L83E0 POINT (X) TO TAYLOR SERIES COEFFICIENTS + JSR LBEF0 EXPAND POLYNOMIAL + PULS A GET EXPONENT OF ARGUMENT + CMPA #$81 WAS ARGUMENT < 1.0? + BLO L83D7 YES + LDX #L83AB POINT (X) TO FP NUMBER (PI/2) + JSR LB9B9 SUBTRACT FPA0 FROM (PI/2) +L83D7 PULS A * GET SIGN OF INITIAL ARGUMENT MANTISSA + TSTA * AND SET FLAGS ACCORDING TO IT + BPL L83DF RETURN IF ARGUMENT WAS POSITIVE +L83DC JMP LBEE9 CHANGE MANTISSA SIGN OF FPA0 +L83DF RTS +* +* TCHEBYSHEV MODIFIED TAYLOR SERIES COEFFICIENTS FOR ARCTANGENT +L83E0 FCB $0B TWELVE COEFFICIENTS +L83E1 FCB $76,$B3,$83,$BD,$D3 -6.84793912E-04 1/23 +L83E6 FCB $79,$1E,$F4,$A6,$F5 +4.85094216E-03 1/21 +L83EB FCB $7B,$83,$FC,$B0,$10 -0.0161117018 +L83F0 FCB $7C,$0C,$1F,$67,$CA 0.0342096381 +L83F5 FCB $7C,$DE,$53,$CB,$C1 -0.0542791328 +L83FA FCB $7D,$14,$64,$70,$4C 0.0724571965 +L83FF FCB $7D,$B7,$EA,$51,$7A -0.0898023954 +L8404 FCB $7D,$63,$30,$88,$7E 0.110932413 +L8409 FCB $7E,$92,$44,$99,$3A -0.142839808 +L840E FCB $7E,$4C,$CC,$91,$C7 0.199999121 +L8413 FCB $7F,$AA,$AA,$AA,$13 -0.333333316 +L8418 FCB $81,$00,$00,$00,$00 1 +* +*** TCHEBYSHEV MODIFIED TAYLOR SERIES COEFFICIENTS FOR LN(X) +* +L841D FCB 3 FOUR COEFFICIENTS +L841E FCB $7F,$5E,$56,$CB,$79 0.434255942 +L8423 FCB $80,$13,$9B,$0B,$64 0.576584541 +L8428 FCB $80,$76,$38,$93,$16 0.961800759 +L842D FCB $82,$38,$AA,$3B,$20 2.88539007 + +L8432 FCB $80,$35,$04,$F3,$34 1/SQR(2) + +L8437 FCB $81,$35,$04,$F3,$34 SQR(2) + +L843C FCB $80,$80,$00,$00,$00 -0.5 + +L8441 FCB $80,$31,$72,$17,$F8 LN(2) +* +* LOG - NATURAL LOGARITHM (LN) + +* THE NATURAL OR NAPERIAN LOGARITHM IS CALCULATED USING +* MATHEMATICAL IDENTITIES. FPA0 IS OF THE FORM FPA0=A*(2**B) (SCIENTIFIC +* NOTATION). THEREFORE, THE LOG ROUTINE DETERMINES THE VALUE OF +* LN(A*(2**B)). A SERIES OF MATHEMATICAL IDENTITIES WILL EXPAND THIS +* TERM: LN(A*(2**B))=(-1/2+(1/LN(2))*(LN(A*SQR(2)))+B)*LN(2). ALL OF +* THE TERMS OF THE LATTER EXPRESSION ARE CONSTANTS EXCEPT FOR THE +* LN(A*SQR(2)) TERM WHICH IS EVALUATED USING THE TAYLOR SERIES EXPANSION +LOG JSR LBC6D CHECK STATUS OF FPA0 + LBLE LB44A ‘FC’ ERROR IF NEGATIVE OR ZERO + LDX #L8432 POINT (X) TO FP NUMBER (1/SQR(2)) + LDA FP0EXP *GET EXPONENT OF ARGUMENT + SUBA #$80 *SUBTRACT OFF THE BIAS AND + PSHS A *SAVE IT ON THE STACK + LDA #$80 + STA FP0EXP + JSR LB9C2 ADD FPA0 TO (X) + LDX #L8437 POINT X TO SQR(2) + JSR LBB8F DIVIDE SQR(2) BY FPA0 + LDX #LBAC5 POINT X TO FP VALUE OF 1.00 + JSR LB9B9 SUBTRACT FPA0 FROM (X) +* NOW FPA0 = (1-SQR(2)*X)/(1+SQR(2)*X) WHERE X IS ARGUMENT + LDX #L841D POINT X TO TABLE OF COEFFICIENTS + JSR LBEF0 EXPAND POLYNOMIAL + LDX #L843C POINT X TO FP VALUE OF (-.5) + JSR LB9C2 ADD FPA0 TO X + PULS B GET EXPONENT OF ARGUMENT BACK (WITHOUT BIAS) + JSR LBD99 ADD ACCB TO FPA0 + LDX #L8441 POINT X TO LN(2) + JMP LBACA MULTIPLY FPA0 * LN(2) + +* SQR +SQR JSR LBC5F MOVE FPA0 TO FPA1 + LDX #LBEC0 POINT (X) TO FP NUMBER (.5) + JSR LBC14 COPY A PACKED NUMBER FROM (X) TO FPA0 + +* ARITHMETIC OPERATOR FOR EXPONENTIATION JUMPS +* HERE. THE FORMULA USED TO EVALUATE EXPONENTIATION +* IS A**X=E**(X LN A) = E**(FPA0*LN(FPA1)), E=2.7182818 +L8489 BEQ EXP DO A NATURAL EXPONENTIATION IF EXPONENT = 0 + TSTA *CHECK VALUE BEING EXPONENTIATED + BNE L8491 *AND BRANCH IF IT IS <> 0 + JMP LBA3A FPA0=0 IF RAISING ZERO TO A POWER +L8491 LDX #V4A * PACK FPA0 AND SAVE + JSR LBC35 * IT IN FPA5 (ARGUMENT’S EXPONENT) + CLRB ACCB=DEFAULT RESULT SIGN FLAG; 0=POSITIVE + LDA FP1SGN *CHECK THE SIGN OF ARGUMENT + BPL L84AC *BRANCH IF POSITIVE + JSR INT CONVERT EXPONENT INTO AN INTEGER + LDX #V4A POINT X TO FPA5 (ORIGINAL EXPONENT) + LDA FP1SGN GET MANTISSA SIGN OF FPA1 (ARGUMENT) + JSR LBCA0 *COMPARE FPA0 TO (X) AND + BNE L84AC *BRANCH IF NOT EQUAL + COMA TOGGLE FPA1 MANTISSA SIGN - FORCE POSITIVE + LDB CHARAC GET LS BYTE OF INTEGER VALUE OF EXPONENT (RESULT SIGN FLAG) +L84AC JSR LBC4C COPY FPA1 TO FPA0; ACCA = MANTISSA SIGN + PSHS B PUT RESULT SIGN FLAG ON THE STACK + JSR LOG + LDX #V4A POINT (X) TO FPA5 + JSR LBACA MULTIPLY FPA0 BY FPA5 + BSR EXP CALCULATE E**(FPA0) + PULS A * GET RESULT SIGN FLAG FROM THE STACK + RORA * AND BRANCH IF NEGATIVE + LBCS LBEE9 CHANGE SIGN OF FPA0 MANTISSA + RTS + +* CORRECTION FACTOR FOR EXPONENTIAL FUNCTION +L84C4 FCB $81,$38,$AA,$3B,$29 1.44269504 ( CF ) +* +* TCHEBYSHEV MODIFIED TAYLOR SERIES COEFFICIENTS FOR E**X +* +L84C9 FCB 7 EIGHT COEFFICIENTS +L84CA FCB $71,$34,$58,$3E,$56 2.14987637E-05: 1/(7!*(CF**7)) +L84CF FCB $74,$16,$7E,$B3,$1B 1.4352314E-04 : 1/(6!*(CF**6)) +L84D4 FCB $77,$2F,$EE,$E3,$85 1.34226348E-03: 1/(5!*(CF**5)) +L84D9 FCB $7A,$1D,$84,$1C,$2A 9.61401701E-03: 1/(4!*(CF**4)) +L84DE FCB $7C,$63,$59,$58,$0A 0.0555051269 +L84E3 FCB $7E,$75,$FD,$E7,$C6 0.240226385 +L84E8 FCB $80,$31,$72,$18,$10 0.693147186 +L84ED FCB $81,$00,$00,$00,$00 1 +* +* EXP ( E**X) +* THE EXPONENTIAL FUNCTION IS EVALUATED BY FIRST MULTIPLYING THE +* ARGUMENT BY A CORRECTION FACTOR (CF). AFTER THIS IS DONE, AN +* ARGUMENT >= 127 WILL YIELD A ZERO RESULT (NO UNDERFLOW) FOR A +* NEGATIVE ARGUMENT OR AN 'OV' (OVERFLOW) ERROR FOR A POSITIVE +* ARGUMENT. THE POLYNOMIAL COEFFICIENTS ARE MODIFIED TO REFLECT +* THE CF MULTIPLICATION AT THE START OF THE EVALUATION PROCESS. + +EXP LDX #L84C4 POINT X TO THE CORRECTION FACTOR + JSR LBACA MULTIPLY FPA0 BY (X) + JSR LBC2F PACK FPA0 AND STORE IT IN FPA3 + LDA FP0EXP *GET EXPONENT OF FPA0 AND + CMPA #$88 *COMPARE TO THE MAXIMUM VALUE + BLO L8504 BRANCH IF FPA0 < 128 +L8501 JMP LBB5C SET FPA0 = 0 OR ‘OV’ ERROR +L8504 JSR INT CONVERT FPA0 TO INTEGER + LDA CHARAC GET LS BYTE OF INTEGER + ADDA #$81 * WAS THE ARGUMENT =127, IF SO + BEQ L8501 * THEN ‘OV’ ERROR; THIS WILL ALSO ADD THE $80 BIAS +* * REQUIRED WHEN THE NEW EXPONENT IS CALCULATED BELOW + DECA DECREMENT ONE FROM THE EXPONENT, BECAUSE $81, NOT $80 WAS USED ABOVE + PSHS A SAVE EXPONENT OF INTEGER PORTION ON STACK + LDX #V40 POINT (X) TO FPA3 + JSR LB9B9 SUBTRACT FPA0 FROM (X) - GET FRACTIONAL PART OF ARGUMENT + LDX #L84C9 POINT X TO COEFFICIENTS + JSR LBEFF EVALUATE POLYNOMIAL FOR FRACTIONAL PART + CLR RESSGN FORCE THE MANTISSA TO BE POSITIVE + PULS A GET INTEGER EXPONENT FROM STACK + JSR LBB48 * CALCULATE EXPONENT OF NEW FPA0 BY ADDING THE EXPONENTS OF THE +* * INTEGER AND FRACTIONAL PARTS + RTS + +* FIX +FIX JSR LBC6D CHECK STATUS OF FPA0 + BMI L852C BRANCH IF FPA0 = NEGATIVE +L8529 JMP INT CONVERT FPA0 TO INTEGER +L852C COM FP0SGN TOGGLE SIGN OF FPA0 MANTISSA + BSR L8529 CONVERT FPA0 TO INTEGER + JMP LBEE9 TOGGLE SIGN OF FPA0 + +* EDIT +EDIT JSR L89AE GET LINE NUMBER FROM BASIC + LEAS $02,S PURGE RETURN ADDRESS OFF OF THE STACK +L8538 LDA #$01 ‘LIST’ FLAG + STA VD8 SET FLAG TO LIST LINE + JSR LAD01 GO FIND THE LINE NUMBER IN PROGRAM + LBCS LAED2 ERROR #7 ‘UNDEFINED LINE #' + JSR LB7C2 GO UNCRUNCH LINE INTO BUFFER AT LINBUF+1 + TFR Y,D PUT ABSOLUTE ADDRESS OF END OF LINE TO ACCD + SUBD #LINBUF+2 SUBTRACT OUT THE START OF LINE + STB VD7 SAVE LENGTH OF LINE +L854D LDD BINVAL GET THE HEX VALUE OF LINE NUMBER + JSR LBDCC LIST THE LINE NUMBER ON THE SCREEN + JSR LB9AC PRINT A SPACE + LDX #LINBUF+1 POINT X TO BUFFER + LDB VD8 * CHECK TO SEE IF LINE IS TO BE + BNE L8581 * LISTED TO SCREEN - BRANCH IF IT IS +L855C CLRB RESET DIGIT ACCUMULATOR - DEFAULT VALUE +L855D JSR L8687 GET KEY STROKE + JSR L90AA SET CARRY IF NOT NUMERIC + BLO L8570 BRANCH IF NOT NUMERIC + SUBA #'0' MASK OFF ASCII + PSHS A SAVE IT ON STACK + LDA #10 NUMBER BEING CONVERTED IS BASE 10 + MUL MULTIPLY ACCUMULATED VALUE BY BASE (10) + ADDB ,S+ ADD DIGIT TO ACCUMULATED VALUE + BRA L855D CHECK FOR ANOTHER DIGIT +L8570 SUBB #$01 * REPEAT PARAMETER IN ACCB; IF IT + ADCB #$01 *IS 0, THEN MAKE IT ‘1’ + CMPA #'A' ABORT? + BNE L857D NO + JSR LB958 PRINT CARRIAGE RETURN TO SCREEN + BRA L8538 RESTART EDIT PROCESS - CANCEL ALL CHANGES +L857D CMPA #'L' LIST? + BNE L858C NO +L8581 BSR L85B4 LIST THE LINE + CLR VD8 RESET THE LIST FLAG TO ‘NO LIST’ + JSR LB958 PRINT CARRIAGE RETURN + BRA L854D GO INTERPRET ANOTHER EDIT COMMAND +L858A LEAS $02,S PURGE RETURN ADDRESS OFF OF THE STACK +L858C CMPA #CR ENTER KEY? + BNE L859D NO + BSR L85B4 ECHO THE LINE TO THE SCREEN +L8592 JSR LB958 PRINT CARRIAGE RETURN + LDX #LINBUF+1 * RESET BASIC’S INPUT POINTER + STX CHARAD * TO THE LINE INPUT BUFFER + JMP LACA8 GO PUT LINE BACK IN PROGRAM +L859D CMPA #'E' EXIT? + BEQ L8592 YES - SAME AS ENTER EXCEPT NO ECHO + CMPA #'Q' QUIT? + BNE L85AB NO + JSR LB958 PRINT CARRIAGE RETURN TO SCREEN + JMP LAC73 GO TO COMMAND LEVEL - MAKE NO CHANGES +L85AB BSR L85AF INTERPRET THE REMAINING COMMANDS AS SUBROUTINES + BRA L855C GO INTERPRET ANOTHER EDIT COMMAND +L85AF CMPA #SPACE SPACE BAR? + BNE L85C3 NO +L85B3 FCB SKP2 SKIP TWO BYTES +* DISPLAY THE NEXT ACCB BYTES OF THE LINE IN THE BUFFER TO THE SCREEN +* +L85B4 LDB #LBUFMX-1 250 BYTES MAX IN BUFFER +L85B6 LDA ,X GET A CHARACTER FROM BUFFER + BEQ L85C2 EXIT IF IT’S A 0 + JSR PUTCHR SEND CHAR TO CONSOLE OUT + LEAX $01,X MOVE POINTER UP ONE + DECB DECREMENT CHARACTER COUNTER + BNE L85B6 LOOP IF NOT DONE +L85C2 RTS +L85C3 CMPA #'D' DELETE? + BNE L860F NO +L85C7 TST ,X * CHECK FOR END OF LINE + BEQ L85C2 * AND BRANCH IF SO + BSR L85D1 REMOVE A CHARACTER + DECB DECREMENT REPEAT PARAMETER + BNE L85C7 BRANCH IF NOT DONE + RTS +* REMOVE ONE CHARACTER FROM BUFFER +L85D1 DEC VD7 DECREMENT LENGTH OF BUFFER + LEAY $-01,X POINT Y TO ONE BEFORE CURRENT BUFFER POINTER +L85D5 LEAY $01,Y INCREMENT TEMPORARY BUFFER POINTER + LDA $01,Y GET NEXT CHARACTER + STA ,Y PUT IT IN CURRENT POSITION + BNE L85D5 BRANCH IF NOT END OF LINE + RTS +L85DE CMPA #'I' INSERT? + BEQ L85F5 YES + CMPA #'X' EXTEND? + BEQ L85F3 YES + CMPA #'H' HACK? + BNE L8646 NO + CLR ,X TURN CURRENT BUFFER POINTER INTO END OF LINE FLAG + TFR X,D PUT CURRENT BUFFER POINTER IN ACCD + SUBD #LINBUF+2 SUBTRACT INITIAL POINTER POSITION + STB VD7 SAVE NEW BUFFER LENGTH +L85F3 BSR L85B4 DISPLAY THE LINE ON THE SCREEN +L85F5 JSR L8687 GET A KEYSTROKE + CMPA #CR ENTER KEY? + BEQ L858A YES - INTERPRET ANOTHER COMMAND - PRINT LINE + CMPA #ESC ESCAPE? + BEQ L8625 YES - RETURN TO COMMAND LEVEL - DON’T PRINT LINE + CMPA #BS BACK SPACE? + BNE L8626 NO + CMPX #LINBUF+1 COMPARE POINTER TO START OF BUFFER + BEQ L85F5 DO NOT ALLOW BS IF AT START + BSR L8650 MOVE POINTER BACK ONE, BS TO SCREEN + BSR L85D1 REMOVE ONE CHARACTER FROM BUFFER + BRA L85F5 GET INSERT SUB COMMAND +L860F CMPA #'C' CHANGE? + BNE L85DE NO +L8613 TST ,X CHECK CURRENT BUFFER CHARACTER + BEQ L8625 BRANCH IF END OF LINE + JSR L8687 GET A KEYSTROKE + BLO L861E BRANCH IF LEGITIMATE KEY + BRA L8613 TRY AGAIN IF ILLEGAL KEY +L861E STA ,X+ INSERT NEW CHARACTER INTO BUFFER + BSR L8659 SEND NEW CHARACTER TO SCREEN + DECB DECREMENT REPEAT PARAMETER + BNE L8613 BRANCH IF NOT DONE +L8625 RTS +L8626 LDB VD7 GET LENGTH OF LINE + CMPB #LBUFMX-1 COMPARE TO MAXIMUM LENGTH + BNE L862E BRANCH IF NOT AT MAXIMUM + BRA L85F5 IGNORE INPUT IF LINE AT MAXIMUM LENGTH +L862E PSHS X SAVE CURRENT BUFFER POINTER +L8630 TST ,X+ * SCAN THE LINE UNTIL END OF + BNE L8630 * LINE (0) IS FOUND +L8634 LDB ,-X DECR TEMP LINE POINTER AND GET A CHARACTER + STB $01,X PUT CHARACTER BACK DOWN ONE SPOT + CMPX ,S HAVE WE REACHED STARTING POINT? + BNE L8634 NO - KEEP GOING + LEAS $02,S PURGE BUFFER POINTER FROM STACK + STA ,X+ INSERT NEW CHARACTER INTO THE LINE + BSR L8659 SEND A CHARACTER TO CONSOLE OUT + INC VD7 ADD ONE TO BUFFER LENGTH + BRA L85F5 GET INSERT SUB COMMAND +L8646 CMPA #BS BACKSPACE? + BNE L865C NO +L864A BSR L8650 MOVE POINTER BACK 1, SEND BS TO SCREEN + DECB DECREMENT REPEAT PARAMETER + BNE L864A LOOP UNTIL DONE + RTS +L8650 CMPX #LINBUF+1 COMPARE POINTER TO START OF BUFFER + BEQ L8625 DO NOT ALLOW BS IF AT START + LEAX $-01,X MOVE POINTER BACK ONE + LDA #BS BACK SPACE +L8659 JMP PUTCHR SEND TO CONSOLE OUT +L865C CMPA #'K' KILL? + BEQ L8665 YES + SUBA #'S' SEARCH? + BEQ L8665 YES + RTS +L8665 PSHS A SAVE KILL/SEARCH FLAG ON STACK + BSR L8687 * GET A KEYSTROKE (TARGET CHARACTER) + PSHS A * AND SAVE IT ON STACK +L866B LDA ,X GET CURRENT BUFFER CHARACTER + BEQ L8685 AND RETURN IF END OF LINE + TST $01,S CHECK KILL/SEARCH FLAG + BNE L8679 BRANCH IF KILL + BSR L8659 SEND A CHARACTER TO CONSOLE OUT + LEAX $01,X INCREMENT BUFFER POINTER + BRA L867C CHECK NEXT INPUT CHARACTER +L8679 JSR L85D1 REMOVE ONE CHARACTER FROM BUFFER +L867C LDA ,X GET CURRENT INPUT CHARACTER + CMPA ,S COMPARE TO TARGET CHARACTER + BNE L866B BRANCH IF NO MATCH + DECB DECREMENT REPEAT PARAMETER + BNE L866B BRANCH IF NOT DONE +L8685 PULS Y,PC THE Y PULL WILL CLEAN UP THE STACK FOR THE 2 PSHS A +* +* GET A KEYSTRKE +L8687 JSR LA171 CALL CONSOLE IN : DEV NBR=SCREEN + CMPA #$7F GRAPHIC CHARACTER? + BCC L8687 YES - GET ANOTHER CHAR + CMPA #$5F SHIFT UP ARROW (QUIT INSERT) + BNE L8694 NO + LDA #ESC REPLACE W/ESCAPE CODE +L8694 CMPA #CR ENTER KEY + BEQ L86A6 YES + CMPA #ESC ESCAPE? + BEQ L86A6 YES + CMPA #BS BACKSPACE? + BEQ L86A6 YES + CMPA #SPACE SPACE + BLO L8687 GET ANOTHER CHAR IF CONTROL CHAR + ORCC #$01 SET CARRY +L86A6 RTS + +* TRON +TRON FCB SKP1LD SKIP ONE BYTE AND LDA #$4F + +* TROFF +TROFF CLRA TROFF FLAG + STA TRCFLG TRON/TROFF FLAG:0=TROFF, <> 0=TRON + RTS + +* POS + +POS LDA #0 GET DEVICE NUMBER + LDB LPTPOS GET PRINT POSITION +LA5E8 SEX CONVERT ACCB TO 2 DIGIT SIGNED INTEGER + JMP GIVABF CONVERT ACCD TO FLOATING POINT + + +* VARPTR +VARPT JSR LB26A SYNTAX CHECK FOR ‘(‘ + LDD ARYEND GET ADDR OF END OF ARRAYS + PSHS B,A SAVE IT ON STACK + JSR LB357 GET VARIABLE DESCRIPTOR + JSR LB267 SYNTAX CHECK FOR ‘)‘ + PULS A,B GET END OF ARRAYS ADDR BACK + EXG X,D SWAP END OF ARRAYS AND VARIABLE DESCRIPTOR + CMPX ARYEND COMPARE TO NEW END OF ARRAYS + BNE L8724 ‘FC’ ERROR IF VARIABLE WAS NOT DEFINED PRIOR TO CALLING VARPTR + JMP GIVABF CONVERT VARIABLE DESCRIPTOR INTO A FP NUMBER + +* MID$(OLDSTRING,POSITION,LENGTH)=REPLACEMENT +L86D6 JSR GETNCH GET INPUT CHAR FROM BASIC + JSR LB26A SYNTAX CHECK FOR ‘(‘ + JSR LB357 * GET VARIABLE DESCRIPTOR ADDRESS AND + PSHS X * SAVE IT ON THE STACK + LDD $02,X POINT ACCD TO START OF OLDSTRING + CMPD FRETOP COMPARE TO START OF CLEARED SPACE + BLS L86EB BRANCH IF <= + SUBD MEMSIZ SUBTRACT OUT TOP OF CLEARED SPACE + BLS L86FD BRANCH IF STRING IN STRING SPACE +L86EB LDB ,X GET LENGTH OF OLDSTRING + JSR LB56D RESERVE ACCB BYTES IN STRING SPACE + PSHS X SAVE RESERVED SPACE STRING ADDRESS ON STACK + LDX $02,S POINT X TO OLDSTRING DESCRIPTOR + JSR LB643 MOVE OLDSTRING INTO STRING SPACE + PULS X,U * GET OLDSTRING DESCRIPTOR ADDRESS AND RESERVED STRING + STX $02,U * ADDRESS AND SAVE RESERVED ADDRESS AS OLDSTRING ADDRESS + PSHS U SAVE OLDSTRING DESCRIPTOR ADDRESS +L86FD JSR LB738 SYNTAX CHECK FOR COMMA AND EVALUATE LENGTH EXPRESSION + PSHS B SAVE POSITION PARAMETER ON STACK + TSTB * CHECK POSITION PARAMETER AND BRANCH + BEQ L8724 * IF START OF STRING + LDB #$FF DEFAULT REPLACEMENT LENGTH = $FF + CMPA #')' * CHECK FOR END OF MID$ STATEMENT AND + BEQ L870E * BRANCH IF AT END OF STATEMENT + JSR LB738 SYNTAX CHECK FOR COMMA AND EVALUATE LENGTH EXPRESSION +L870E PSHS B SAVE LENGTH PARAMETER ON STACK + JSR LB267 SYNTAX CHECK FOR ‘)‘ + LDB #TOK_EQUALS TOKEN FOR = + JSR LB26F SYNTAX CHECK FOR “=‘ + BSR L8748 EVALUATE REPLACEMENT STRING + TFR X,U SAVE REPLACEMENT STRING ADDRESS IN U + LDX $02,S POINT X TO OLOSTRING DESCRIPTOR ADDRESS + LDA ,X GET LENGTH OF OLDSTRING + SUBA $01,S SUBTRACT POSITION PARAMETER + BCC L8727 INSERT REPLACEMENT STRING INTO OLDSTRING +L8724 JMP LB44A ‘FC’ ERROR IF POSITION > LENGTH OF OLDSTRING +L8727 INCA * NOW ACCA = NUMBER OF CHARACTERS TO THE RIGHT +* * (INCLUSIVE) OF THE POSITION PARAMETER + CMPA ,S + BCC L872E BRANCH IF NEW STRING WILL FIT IN OLDSTRING + STA ,S IF NOT, USE AS MUCH OF LENGTH PARAMETER AS WILL FIT +L872E LDA $01,S GET POSITION PARAMETER + EXG A,B ACCA=LENGTH OF REPL STRING, ACCB=POSITION PARAMETER + LDX $02,X POINT X TO OLDSTRING ADDRESS + DECB * BASIC’S POSITION PARAMETER STARTS AT 1; THIS ROUTINE +* * WANTS IT TO START AT ZERO + ABX POINT X TO POSITION IN OLDSTRING WHERE THE REPLACEMENT WILL GO + TSTA * IF THE LENGTH OF THE REPLACEMENT STRING IS ZERO + BEQ L8746 * THEN RETURN + CMPA ,S + BLS L873F ADJUSTED LENGTH PARAMETER, THEN BRANCH + LDA ,S OTHERWISE USE AS MUCH ROOM AS IS AVAILABLE +L873F TFR A,B SAVE NUMBER OF BYTES TO MOVE IN ACCB + EXG U,X SWAP SOURCE AND DESTINATION POINTERS + JSR LA59A MOVE (B) BYTES FROM (X) TO (U) +L8746 PULS A,B,X,PC +L8748 JSR LB156 EVALUATE EXPRESSION + JMP LB654 *‘TM’ ERROR IF NUMERIC; RETURN WITH X POINTING +* *TO STRING, ACCB = LENGTH + +* STRING +STRING JSR LB26A SYNTAX CHECK FOR ‘(’ + JSR LB70B EVALUATE EXPRESSION; ERROR IF > 255 + PSHS B SAVE LENGTH OF STRING + JSR LB26D SYNTAX CHECK FOR COMMA + JSR LB156 EVALUATE EXPRESSION + JSR LB267 SYNTAX CHECK FOR ‘)‘ + LDA VALTYP GET VARIABLE TYPE + BNE L8768 BRANCH IF STRING + JSR LB70E CONVERT FPA0 INTO AN INTEGER IN ACCB + BRA L876B SAVE THE STRING IN STRING SPACE +L8768 JSR LB6A4 GET FIRST BYTE OF STRING +L876B PSHS B SAVE FIRST BYTE OF EXPRESSION + LDB $01,S GET LENGTH OF STRING + JSR LB50F RESERVE ACCB BYTES IN STRING SPACE + PULS A,B GET LENGTH OF STRING AND CHARACTER + BEQ L877B BRANCH IF NULL STRING +L8776 STA ,X+ SAVE A CHARACTER IN STRING SPACE + DECB DECREMENT LENGTH + BNE L8776 BRANCH IF NOT DONE +L877B JMP LB69B PUT STRING DESCRIPTOR ONTO STRING STACK + +* INSTR +INSTR JSR LB26A SYNTAX CHECK FOR ‘(‘ + JSR LB156 EVALUATE EXPRESSION + LDB #$01 DEFAULT POSITION = 1 (SEARCH START) + PSHS B SAVE START + LDA VALTYP GET VARIABLE TYPE + BNE L879C BRANCH IF STRING + JSR LB70E CONVERT FPA0 TO INTEGER IN ACCB + STB ,S SAVE START SEARCH VALUE + BEQ L8724 BRANCH IF START SEARCH AT ZERO + JSR LB26D SYNTAX CHECK FOR COMMA + JSR LB156 EVALUATE EXPRESSION - SEARCH STRING + JSR LB146 ‘TM’ ERROR IF NUMERIC +L879C LDX FPA0+2 SEARCH STRING DESCRIPTOR ADDRESS + PSHS X SAVE ON THE STACK + JSR LB26D SYNTAX CHECK FOR COMMA + JSR L8748 EVALUATE TARGET STRING EXPRESSION + PSHS X,B SAVE ADDRESS AND LENGTH ON STACK + JSR LB267 SYNTAX CHECK FOR ')' + LDX $03,S * LOAD X WITH SEARCH STRING DESCRIPTOR ADDRESS + JSR LB659 * AND GET THE LENGTH ANDADDRESS OF SEARCH STRING + PSHS B SAVE LENGTH ON STACK +* +* AT THIS POINT THE STACK HAS THE FOLLOWING INFORMATION +* ON IT: 0,S-SEARCH LENGTH; 1,S-TARGET LENGTH; 2 3,S-TARGET +* ADDRESS; 4 5,S-SEARCH DESCRIPTOR ADDRESS; 6,S-SEARCH POSITION + CMPB $06,S COMPARE LENGTH OF SEARCH STRING TO START + BLO L87D9 POSITION; RETURN 0 IF LENGTH < START + LDA $01,S GET LENGTH OF TARGET STRING + BEQ L87D6 BRANCH IF TARGET STRING = NULL + LDB $06,S GET START POSITION + DECB MOVE BACK ONE + ABX POINT X TO POSITION IN SEARCH STRING WHERE SEARCHING WILL START +L87BE LEAY ,X POINT Y TO SEARCH POSITION + LDU $02,S POINT U TO START OF TARGET + LDB $01,S LOAD ACCB WITH LENGTH OF TARGET + LDA ,S LOAD ACCA WITH LENGTH OF SEARCH + SUBA $06,S SUBTRACT SEARCH POSITION FROM SEARCH LENGTH + INCA ADD ONE + CMPA $01,S COMPARE TO TARGET LENGTH + BLO L87D9 RETURN 0 IF TARGET LENGTH > WHAT’S LEFT OF SEARCH STRING +L87CD LDA ,X+ GET A CHARACTER FROM SEARCH STRING + CMPA ,U+ COMPARE IT TO TARGET STRING + BNE L87DF BRANCH IF NO MATCH + DECB DECREMENT TARGET LENGTH + BNE L87CD CHECK ANOTHER CHARACTER +L87D6 LDB $06,S GET MATCH POSITION +L87D8 FCB SKP1 SKIP NEXT BYTE +L87D9 CLRB MATCH ADDRESS = 0 + LEAS $07,S CLEAN UP THE STACK + JMP LB4F3 CONVERT ACCB TO FP NUMBER +L87DF INC $06,S INCREMENT SEARCH POSITION + LEAX $01,Y MOVE X TO NEXT SEARCH POSITION + BRA L87BE KEEP LOOKING FOR A MATCH + +* EXTENDED BASIC RVEC19 HOOK CODE +XVEC19 CMPA #'&' * + BNE L8845 * RETURN IF NOT HEX OR OCTAL VARIABLE + LEAS $02,S PURGE RETURN ADDRESS FROM STACK +* PROCESS A VARIABLE PRECEEDED BY A ‘&‘ (&H,&O) +L87EB CLR FPA0+2 * CLEAR BOTTOM TWO + CLR FPA0+3 * BYTES OF FPA0 + LDX #FPA0+2 BYTES 2,3 OF FPA0 = (TEMPORARY ACCUMULATOR) + JSR GETNCH GET A CHARACTER FROM BASIC + CMPA #'O' + BEQ L880A YES + CMPA #'H' + BEQ L881F YES + JSR GETCCH GET CURRENT INPUT CHARACTER + BRA L880C DEFAULT TO OCTAL (&O) +L8800 CMPA #'8' + LBHI LB277 + LDB #$03 BASE 8 MULTIPLIER + BSR L8834 ADD DIGIT TO TEMPORARY ACCUMULATOR +* EVALUATE AN &O VARIABLE +L880A JSR GETNCH GET A CHARACTER FROM BASIC +L880C BLO L8800 BRANCH IF NUMERIC +L880E CLR FPA0 * CLEAR 2 HIGH ORDER + CLR FPA0+1 * BYTES OF FPA0 + CLR VALTYP SET VARXABLE TYPE TO NUMERIC + CLR FPSBYT ZERO OUT SUB BYTE OF FPA0 + CLR FP0SGN ZERO OUT MANTISSA SIGN OF FPA0 + LDB #$A0 * SET EXPONENT OF FPA0 + STB FP0EXP * + JMP LBA1C GO NORMALIZE FPA0 +* EVALUATE AN &H VARIABLE +L881F JSR GETNCH GET A CHARACTER FROM BASIC + BLO L882E BRANCH IF NUMERIC + JSR LB3A2 SET CARRY IF NOT ALPHA + BLO L880E BRANCH IF NOT ALPHA OR NUMERIC + CMPA #'G' CHECK FOR LETTERS A-F + BCC L880E BRANCH IF >= G (ILLEGAL HEX LETTER) + SUBA #7 SUBTRACT ASCII DIFFERENCE BETWEEN A AND 9 +L882E LDB #$04 BASE 16 DIGIT MULTIPLIER = 2**4 + BSR L8834 ADD DIGIT TO TEMPORARY ACCUMULATOR + BRA L881F KEEP EVALUATING VARIABLE +L8834 ASL $01,X * MULTIPLY TEMPORARY + ROL ,X * ACCUMULATOR BY TWO + LBCS LBA92 ‘OV' OVERFLOW ERROR + DECB DECREMENT SHIFT COUNTER + BNE L8834 MULTIPLY TEMPORARY ACCUMULATOR AGAIN + SUBA #'0' MASK OFF ASCII + ADDA $01,X * ADD DIGIT TO TEMPORARY + STA $01,X * ACCUMULATOR AND SAVE IT +L8845 RTS + +XVEC15 PULS U PULL RETURN ADDRESS AND SAVE IN U REGISTER + CLR VALTYP SET VARIABLE TYPE TO NUMERIC + LDX CHARAD CURRENT INPUT POINTER TO X + JSR GETNCH GET CHARACTER FROM BASIC + CMPA #'&' HEX AND OCTAL VARIABLES ARE PRECEEDED BY & + BEQ L87EB PROCESS A ‘&‘ VARIABLE + CMPA #TOK_FN TOKEN FOR FN + BEQ L88B4 PROCESS FN CALL + CMPA #$FF CHECK FOR SECONDARY TOKEN + BNE L8862 NOT SECONDARY + JSR GETNCH GET CHARACTER FROM BASIC + CMPA #TOK_USR TOKEN FOR USR + LBEQ L892C PROCESS USR CALL +L8862 STX CHARAD RESTORE BASIC’S INPUT POINTER + JMP ,U RETURN TO CALLING ROUTINE +L8866 LDX CURLIN GET CURRENT LINE NUMBER + LEAX $01,X IN DIRECT MODE? + BNE L8845 RETURN IF NOT IN DIRECT MODE + LDB #2*11 ‘ILLEGAL DIRECT STATEMENT’ ERROR +L886E JMP LAC46 PROCESS ERROR + +DEF LDX [CHARAD] GET TWO INPUT CHARS + CMPX #TOK_FF_USR TOKEN FOR USR + LBEQ L890F BRANCH IF DEF USR + BSR L88A1 GET DESCRIPTOR ADDRESS FOR FN VARIABLE NAME + BSR L8866 DON’T ALLOW DEF FN IF IN DIRECT MODE + JSR LB26A SYNTAX CHECK FOR ‘(‘ + LDB #$80 * GET THE FLAG TO INDICATE ARRAY VARIABLE SEARCH DISABLE + STB ARYDIS * AND SAVE IT IN THE ARRAY DISABLE FLAG + JSR LB357 GET VARIABLE DESCRIPTOR + BSR L88B1 ‘TM’ ERROR IF STRING + JSR LB267 SYNTAX CHECK FOR ‘)‘ + LDB #TOK_EQUALS TOKEN FOR ‘=‘ + JSR LB26F DO A SYNTAX CHECK FOR = + LDX V4B GET THE ADDRESS OF THE FN NAME DESCRIPTOR + LDD CHARAD * GET THE CURRENT INPUT POINTER ADDRESS AND + STD ,X * SAVE IT IN FIRST 2 BYTES OF THE DESCRIPTOR + LDD VARPTR = GET THE DESCRIPTOR ADDRESS OF THE ARGUMENT + STD $02,X = VARIABLE AND SAVE IT IN THE DESCRIPTOR OF THE FN NAME + JMP DATA MOVE INPUT POINTER TO END OF LINE OR SUBLINE +L88A1 LDB #TOK_FN TOKEN FOR FN + JSR LB26F DO A SYNTAX CHECK FOR FN + LDB #$80 * GET THE FLAG TO INDICATE ARRAY VARIABLE SEARCH DISABLE FLAG + STB ARYDIS * AND SAVE IT IN ARRAY VARIABLE FLAG + ORA #$80 SET BIT 7 OF CURRENT INPUT CHARACTER TO INDICATE AN FN VARIABLE + JSR LB35C * GET THE DESCRIPTOR ADDRESS OF THIS + STX V4B * VARIABLE AND SAVE IT IN V4B +L88B1 JMP LB143 ‘TM’ ERROR IF STRING VARIABLE +* EVALUATE AN FN CALL +L88B4 BSR L88A1 * GET THE DESCRIPTOR OF THE FN NAME + PSHS X * VARIABLE AND SAVE IT ON THE STACK + JSR LB262 SYNTAX CHECK FOR ‘(‘ & EVALUATE EXPR + BSR L88B1 ‘TM’ ERROR IF STRING VARIABLE + PULS U POINT U TO FN NAME DESCRIPTOR + LDB #2*25 ‘UNDEFINED FUNCTION CALL’ ERROR + LDX $02,U POINT X TO ARGUMENT VARIABLE DESCRIPTOR + BEQ L886E BRANCH TO ERROR HANDLER + LDY CHARAD SAVE CURRENT INPUT POINTER IN Y + LDU ,U * POINT U TO START OF FN FORMULA AND + STU CHARAD * SAVE IT IN INPUT POINTER + LDA $04,X = GET FP VALUE OF + PSHS A = ARGUMENT VARIABLE, CURRENT INPUT + LDD ,X = POINTER, AND ADDRESS OF START + LDU $02,X = OF FN FORMULA AND SAVE + PSHS U,Y,X,B,A = THEM ON THE STACK + JSR LBC35 PACK FPA0 AND SAVE IT IN (X) +L88D9 JSR LB141 EVALUATE FN EXPRESSION + PULS A,B,X,Y,U RESTORE REGISTERS + STD ,X * GET THE FP + STU $02,X * VALUE OF THE ARGUMENT + PULS A * VARIABLE OFF OF THE + STA $04,X * STACK AND RE-SAVE IT + JSR GETCCH GET FINAL CHARACTER OF THE FN FORMULA + LBNE LB277 ‘SYNTAX’ ERROR IF NOT END OF LINE + STY CHARAD RESTORE INPUT POINTER +L88EF RTS + + + +* DEF USR +L890F JSR GETNCH SKIP PAST SECOND BYTE OF DEF USR TOKEN + BSR L891C GET FN NUMBER + PSHS X SAVE FN EXEC ADDRESS STORAGE LOC + BSR L8944 CALCULATE EXEC ADDRESS + PULS U GET FN EXEC ADDRESS STORAGE LOC + STX ,U SAVE EXEC ADDRESS + RTS +L891C CLRB DEFAULT TO USR0 IF NO ARGUMENT + JSR GETNCH GET A CHARACTER FROM BASIC + BCC L8927 BRANCH IF NOT NUMERIC + SUBA #'0' MASK OFF ASCII + TFR A,B SAVE USR NUMBER IN ACCB + JSR GETNCH GET A CHARACTER FROM BASIC +L8927 LDX USRADR GET ADDRESS OF STORAGE LOCs FOR USR ADDRESS + ASLB X2 - 2 BYTES/USR ADDRESS + ABX ADD OFFSET TO START ADDRESS OF STORAGE LOCs + RTS +* PROCESS A USR CALL +L892C BSR L891C GET STORAGE LOC OF EXEC ADDRESS FOR USR N + LDX ,X * GET EXEC ADDRESS AND + PSHS X * PUSH IT ONTO STACK + JSR LB262 SYNTAX CHECK FOR ‘(‘ & EVALUATE EXPR + LDX #FP0EXP POINT X TO FPA0 + LDA VALTYP GET VARIABLE TYPE + BEQ L8943 BRANCH IF NUMERIC, STRING IF <> 0 + JSR LB657 GET LENGTH & ADDRESS OF STRING VARIABLE + LDX FPA0+2 GET POINTER TO STRING DESCRIPTOR + LDA VALTYP GET VARIABLE TYPE +L8943 RTS JUMP TO USR ROUTINE (PSHS X ABOVE) +L8944 LDB #TOK_EQUALS TOKEN FOR ‘=‘ + JSR LB26F DO A SYNTAX CHECK FOR = + JMP LB73D EVALUATE EXPRESSION, RETURN VALUE IN X + + + +* DEL +DEL LBEQ LB44A FC’ ERROR IF NO ARGUMENT + JSR LAF67 CONVERT A DECIMAL BASiC NUMBER TO BINARY + JSR LAD01 FIND RAM ADDRESS OF START OF A BASIC LINE + STX VD3 SAVE RAM ADDRESS OF STARTING LINE NUMBER + JSR GETCCH GET CURRENT INPUT CHARACTER + BEQ L8990 BRANCH IF END OF LINE + CMPA #TOK_MINUS TOKEN FOR ‘-' + BNE L89BF TERMINATE COMMAND IF LINE NUMBER NOT FOLLOWED BY ‘-‘ + JSR GETNCH GET A CHARACTER FROM BASIC + BEQ L898C IF END OF LINE, USE DEFAULT ENDING LINE NUMBER + BSR L89AE * CONVERT ENDING LINE NUMBER TO BINARY + BRA L8990 * AND SAVE IT IN BINVAL +L898C LDA #$FF = USE $FFXX AS DEFAULT ENDING + STA BINVAL = LINE NUMBER - SAVE IT IN BINVAL +L8990 LDU VD3 POINT U TO STARTING LINE NUMBER ADDRESS +L8992 FCB SKP2 SKIP TWO BYTES +L8993 LDU ,U POINT U TO START OF NEXT LINE + LDD ,U CHECK FOR END OF PROGRAM + BEQ L899F BRANCH IF END OF PROGRAM + LDD $02,U LOAD ACCD WITH THIS LINE’S NUMBER + SUBD BINVAL SUBTRACT ENDING LINE NUMBER ADDRESS + BLS L8993 BRANCH IF = < ENDING LINE NUMBER +L899F LDX VD3 GET STARTING LINE NUMBER + BSR L89B8 MOVE (U) TO (X) UNTIL END OF PROGRAM + JSR LAD21 RESET BASIC’S INPUT POINTER AND ERASE VARIABLES + LDX VD3 GET STARTING LINE NUMBER ADDRESS + JSR LACF1 RECOMPUTE START OF NEXT LINE ADDRESSES + JMP LAC73 JUMP TO BASIC’S MAIN COMMAND LOOP +L89AE JSR LAF67 GO GET LINE NUMBER CONVERTED TO BINARY + JMP LA5C7 MAKE SURE THERE’S NO MORE ON THIS LINE +L89B4 LDA ,U+ GET A BYTE FROM (U) + STA ,X+ MOVE THE BYTE TO (X) +L89B8 CMPU VARTAB COMPARE TO END OF BASIC + BNE L89B4 BRANCH IF NOT AT END + STX VARTAB SAVE (X) AS NEW END OF BASIC +L89BF RTS + + +L89C0 JSR L8866 ‘BS’ ERROR IF IN DIRECT MODE + JSR GETNCH GET A CHAR FROM BASIC +L89D2 CMPA #'"' CHECK FOR PROMPT STRING + BNE L89E1 BRANCH IF NO PROMPT STRING + JSR LB244 STRIP OFF PROMPT STRING & PUT IT ON STRING STACK + LDB #';' * + JSR LB26F * DO A SYNTAX CHECK FOR; + JSR LB99F REMOVE PROMPT STRING FROM STRING STACK & SEND TO CONSOLE OUT +L89E1 LEAS $-02,S RESERVE TWO STORAGE SLOTS ON STACK + JSR LB035 INPUT A LINE FROM CURRENT INPUT DEVICE + LEAS $02,S CLEAN UP THE STACK + JSR LB357 SEARCH FOR A VARIABLE + STX VARDES SAVE POINTER TO VARIABLE DESCRIPTOR + JSR LB146 ‘TM’ ERROR IF VARIABLE TYPE = NUMERIC + LDX #LINBUF POINT X TO THE STRING BUFFER WHERE THE INPUT STRING WAS STORED + CLRA TERMINATOR CHARACTER 0 (END OF LINE) + JSR LB51A PARSE THE INPUT STRING AND STORE IT IN THE STRING SPACE + JMP LAFA4 REMOVE DESCRIPTOR FROM STRING STACK +L89FC JSR LAF67 STRIP A DECIMAL NUMBER FROM BASIC INPUT LINE + LDX BINVAL GET BINARY VALUE + RTS +L8A02 LDX VD1 GET CURRENT OLD NUMBER BEING RENUMBERED +L8A04 STX BINVAL SAVE THE LINE NUMBER BEING SEARCHED FOR + JMP LAD01 GO FIND THE LINE NUMBER IN BASIC PROGRAM + +* RENUM +RENUM JSR LAD26 ERASE VARIABLES + LDD #10 DEFAULT LINE NUMBER INTERVAL + STD VD5 SAVE DEFAULT RENUMBER START LINE NUMBER + STD VCF SAVE DEFAULT INTERVAL + CLRB NOW ACCD = 0 + STD VD1 DEFAULT LINE NUMBER OF WHERE TO START RENUMBERING + JSR GETCCH GET CURRENT INPUT CHARACTER + BCC L8A20 BRANCH IF NOT NUMERIC + BSR L89FC CONVERT DECIMAL NUMBER IN BASIC PROGRAM TO BINARY + STX VD5 SAVE LINE NUMBER WHERE RENUMBERING STARTS + JSR GETCCH GET CURRENT INPUT CHARACTER +L8A20 BEQ L8A3D BRANCH IF END OF LINE + JSR LB26D SYNTAX CHECK FOR COMMA + BCC L8A2D BRANCH IF NEXT CHARACTER NOT NUMERIC + BSR L89FC CONVERT DECIMAL NUMBER IN BASIC PROGRAM TO BINARY + STX VD1 SAVE NEW RENUMBER LINE + JSR GETCCH GET CURRENT INPUT CHARACTER +L8A2D BEQ L8A3D BRANCH IF END OF LINE + JSR LB26D SYNTAX CHECK FOR COMMA + BCC L8A3A BRANCH IF NEXT CHARACTER NOT NUMERIC + BSR L89FC CONVERT DECIMAL NUMBER IN BASIC PROGRAM TO BINARY + STX VCF SAVE NEW INTERVAL + BEQ L8A83 ‘FC' ERROR +L8A3A JSR LA5C7 CHECK FOR MORE CHARACTERS ON LINE - ‘SYNTAX’ ERROR IF ANY +L8A3D BSR L8A02 GO GET ADDRESS OF OLD NUMBER BEING RENUMBERED + STX VD3 SAVE ADDRESS + LDX VD5 GET NEXT RENUMBERED LINE NUMBER TO USE + BSR L8A04 FIND THE LINE NUMBER IN THE BASIC PROGRAM + CMPX VD3 COMPARE TO ADDRESS OF OLD LINE NUMBER + BLO L8A83 ‘FC’ ERROR IF NEW ADDRESS < OLD ADDRESS + BSR L8A67 MAKE SURE RENUMBERED LINE NUMBERS WILL BE IN RANGE + JSR L8ADD CONVERT ASCII LINE NUMBERS TO ‘EXPANDED’ BINARY + JSR LACEF RECALCULATE NEXT LINE RAM ADDRESSES + BSR L8A02 GET RAM ADDRESS OF FIRST LINE TO BE RENUMBERED + STX VD3 SAVE IT + BSR L8A91 MAKE SURE LINE NUMBERS EXIST + BSR L8A68 INSERT NEW LINE NUMBERS IN LINE HEADERS + BSR L8A91 INSERT NEW LINE NUMBERS IN PROGRAM STATEMENTS + JSR L8B7B CONVERT PACKED BINARY LINE NUMBERS TO ASCII + JSR LAD26 ERASE VARIABLES + JSR LACEF RECALCULATE NEXT LINE RAM ADDRESS + JMP LAC73 GO BACK TO BASIC’S MAIN LOOP +L8A67 FCB SKP1LD SKIP ONE BYTE - LDA #$4F +L8A68 CLRA NEW LINE NUMBER FLAG - 0; INSERT NEW LINE NUMBERS + STA VD8 SAVE NEW LINE NUMBER FLAG; 0 = INSERT NEW NUMBERS + LDX VD3 GET ADDRESS OF OLD LINE NUMBER BEING RENUMBERED + LDD VD5 GET THE CURRENT RENUMBERED LINE NUMBER + BSR L8A86 RETURN IF END OF PROGRAM +L8A71 TST VD8 CHECK NEW LINE NUMBER FLAG + BNE L8A77 BRANCH IF NOT INSERTING NEW LINE NUMBERS + STD $02,X STORE THE NEW LINE NUMBER IN THE BASIC PROGRAM +L8A77 LDX ,X POINT X TO THE NEXT LINE IN BASIC + BSR L8A86 RETURN IF END OF PROGRAM + ADDD VCF ADD INTERVAL TO CURRENT RENUMBERED LINE NUMBER + BLO L8A83 ‘FC’ ERROR IF LINE NUMBER > $FFFF + CMPA #MAXLIN LARGEST LINE NUMBER = $F9FF + BLO L8A71 BRANCH IF LEGAL LINE NUMBER +L8A83 JMP LB44A ‘FC’ ERROR IF LINE NUMBER MS BYTE > $F9 +* TEST THE TWO BYTES POINTED TO BY (X). +* NORMAL RETURN IF <> 0. IF = 0 (END OF +* PROGRAM) RETURN IS PULLED OFF STACK AND +* YOU RETURN TO PREVIOUS SUBROUTINE CALL. +L8A86 PSHS B,A SAVE ACCD + LDD ,X TEST THE 2 BYTES POINTED TO BY X + PULS A,B RESTORE ACCD + BNE L8A90 BRANCH IF NOT END OF PROGRAM + LEAS $02,S PURGE RETURN ADDRESS FROM STACK +L8A90 RTS +L8A91 LDX TXTTAB GET START OF BASIC PROGRAM + LEAX $-01,X MOVE POINTER BACK ONE +L8A95 LEAX $01,X MOVE POINTER UP ONE + BSR L8A86 RETURN IF END OF PROGRAM +L8A99 LEAX $03,X SKIP OVER NEXT LINE ADDRESS AND LINE NUMBER +L8A9B LEAX $01,X MOVE POINTER TO NEXT CHARACTER + LDA ,X CHECK CURRENT CHARACTER + BEQ L8A95 BRANCH IF END OF LINE + STX TEMPTR SAVE CURRENT POINTER + DECA = + BEQ L8AB2 =BRANCH IF START OF PACKED NUMERIC LINE + DECA * + BEQ L8AD3 *BRANCH IF LINE NUMBER EXISTS + DECA = + BNE L8A9B =MOVE TO NEXT CHARACTER IF > 3 +L8AAC LDA #$03 * SET 1ST BYTE = 3 TO INDICATE LINE + STA ,X+ * NUMBER DOESN’T CURRENTLY EXIST + BRA L8A99 GO GET ANOTHER CHARACTER +L8AB2 LDD $01,X GET MS BYTE OF LINE NUMBER + DEC $02,X DECREMENT ZERO CHECK BYTE + BEQ L8AB9 BRANCH IF MS BYTE <> 0 + CLRA CLEAR MS BYTE +L8AB9 LDB $03,X GET LS BYTE OF LINE NUMBER + DEC $04,X DECREMENT ZERO CHECK FLAG + BEQ L8AC0 BRANCH IF IS BYTE <> 0 + CLRB CLEAR LS BYTE +L8AC0 STD $01,X SAVE BINARY LINE NUMBER + STD BINVAL SAVE TRIAL LINE NUMBER + JSR LAD01 FIND RAM ADDRESS OF A BASIC LINE NUMBER +L8AC7 LDX TEMPTR GET BACK POINTER TO START OF PACKED LINE NUMBER + BLO L8AAC BRANCH IF NO LINE NUMBER MATCH FOUND + LDD V47 GET START ADDRESS OF LINE NUMBER + INC ,X+ * SET 1ST BYTE = 2, TO INDICATE LINE NUMBER EXISTS IF CHECKING FOR +* * EXISTENCE OF LINE NUMBER, SET IT = 1 IF INSERTING LINE NUMBERS + + STD ,X SAVE RAM ADDRESS OF CORRECT LINE NUMBER + BRA L8A99 GO GET ANOTHER CHARACTER +L8AD3 CLR ,X CLEAR CARRY FLAG AND 1ST BYTE + LDX $01,X POINT X TO RAM ADDRESS OF CORRECT LINE NUMBER + LDX $02,X PUT CORRECT LINE NUMBER INTO (X) + STX V47 SAVE IT TEMPORARILY + BRA L8AC7 GO INSERT IT INTO BASIC LINE +L8ADD LDX TXTTAB GET BEGINNING OF BASIC PROGRAM + BRA L8AE5 +L8AE1 LDX CHARAD *GET CURRENT INPUT POINTER + LEAX $01,X *AND BUMP IT ONE +L8AE5 BSR L8A86 RETURN IF END OF PROGRAM + LEAX $02,X SKIP PAST NEXT LINE ADDRESS +L8AE9 LEAX $01,X ADVANCE POINTER BY ONE +L8AEB STX CHARAD SAVE NEW BASIC INPUT POINTER +L8AED JSR GETNCH GET NEXT CHARACTER FROM BASIC +L8AEF TSTA CHECK THE CHARACTER + BEQ L8AE1 BRANCH IF END OF LINE + BPL L8AED BRANCH IF NOT A TOKEN + LDX CHARAD GET CURRENT INPUT POINTER + CMPA #$FF IS THIS A SECONDARY TOKEN? + BEQ L8AE9 YES - IGNORE IT + CMPA #TOK_THEN TOKEN FOR THEN? + BEQ L8B13 YES + CMPA #TOK_ELSE TOKEN FOR ELSE? + BEQ L8B13 YES + CMPA #TOK_GO TOKEN FOR GO? + BNE L8AED NO + JSR GETNCH GET A CHARACTER FROM BASIC + CMPA #TOK_TO TOKEN FOR TO? + BEQ L8B13 YES + CMPA #TOK_SUB TOKEN FOR SUB? + BNE L8AEB NO +L8B13 JSR GETNCH GET A CHARACTER FROM BASIC + BLO L8B1B BRANCH IF NUMERIC +L8B17 JSR GETCCH GET CURRENT BASIC INPUT CHARRACTER + BRA L8AEF KEEP CHECKING THE LINE +L8B1B LDX CHARAD GET CURRENT INPUT ADDRESS + PSHS X SAVE IT ON THE STACK + JSR LAF67 CONVERT DECIMAL BASIC NUMBER TO BINARY + LDX CHARAD GET CURRENT INPUT POINTER +L8B24 LDA ,-X GET PREVIOUS INPUT CHARACTER + JSR L90AA CLEAR CARRY IF NUMERIC INPUT VALUE + BLO L8B24 BRANCH IF NON-NUMERIC + LEAX $01,X MOVE POINTER UP ONE + TFR X,D NOW ACCD POINTS TO ONE PAST END OF LINE NUMBER + SUBB $01,S SUBTRACT PRE-NUMERIC POINTER LS BYTE + SUBB #$05 MAKE SURE THERE ARE AT LEAST 5 CHARACTERS IN THE NUMERIC LINE +* + BEQ L8B55 BRANCH IF EXACTLY 5 + BLO L8B41 BRANCH IF < 5 + LEAU ,X TRANSFER X TO U + NEGB NEGATE B + LEAX B,X MOVE X BACK B BYTES + JSR L89B8 *MOVE BYTES FROM (U) TO (X) UNTIL +* *U = END OF BASIC; (I) = NEW END OF BASIC + BRA L8B55 +* FORCE FIVE BYTES OF SPACE FOR THE LINE NUMBER +L8B41 STX V47 SAVE END OF NUMERIC VALUE + LDX VARTAB GET END OF BASIC PROGRAM + STX V43 SAVE IT + NEGB NEGATE B + LEAX B,X ADD IT TO END OF NUMERIC POiNTER + STX V41 SAVE POINTER + STX VARTAB STORE END OF BASIC PROGRAM + JSR LAC1E ACCD = TOP OF ARRAYS - CHECK FOR ENOUGH ROOM + LDX V45 * GET AND SAVE THE + STX CHARAD * NEW CURRENT INPUT POINTER +L8B55 PULS X RESTORE POINTER TO START OF NUMERIC VALUE + LDA #$01 NEW LINE NUMBER FLAG + STA ,X * SAVE NEW LINE FLAG + STA $02,X * + STA $04,X * + LDB BINVAL GET MS BYTE OF BINARY LINE NUMBER + BNE L8B67 BRANCH IF IT IS NOT ZERO + LDB #$01 SAVE A 1 IF BYTE IS 0; OTHERWISE, BASIC WILL +* THINK IT IS THE END OF A LINE + INC $02,X IF 2,X = 2, THEN PREVIOUS BYTE WAS A ZERO +L8B67 STB $01,X SAVE MS BYTE OF BINARY LINE NUMBER + LDB BINVAL+1 GET IS BYTE OF BINARY LINE NUMBER + BNE L8B71 BRANCH IF NOT A ZERO BYTE + LDB #$01 SAVE A 1 IF BYTE IS A 0 + INC $04,X IF 4,X = 2, THEN PREVIOUS BYTE WAS A 0 +L8B71 STB $03,X SAVE LS BYTE OF BINARY LINE NUMBER + JSR GETCCH GET CURRENT INPUT CHARACTER + CMPA #',' IS IT A COMMA? + BEQ L8B13 YES - PROCESS ANOTHER NUMERIC VALUE + BRA L8B17 NO - GO GET AND PROCESS AN INPUT CHARACTER +L8B7B LDX TXTTAB POINT X TO START OF BASIC PROGRAM + LEAX $-01,X MOVE POINTER BACK ONE +L8B7F LEAX $01,X MOVE POINTER UP ONE + LDD $02,X GET ADDRESS OF NEXT LINE + STD CURLIN SAVE IT IN CURLIN + JSR L8A86 RETURN IF END OF PROGRAM + LEAX $03,X SKIP OVER ADDRESS OF NEXT LINE AND 1ST BYTE OF LINE NUMBER +L8B8A LEAX $01,X MOVE POINTER UP ONE +L8B8C LDA ,X GET CURRENT CHARACTER + BEQ L8B7F BRANCH IF END OF LINE + DECA INPUT CHARACTER = 1? - VALID LINE NUMBER + BEQ L8BAE YES + SUBA #$02 INPUT CHARACTER 3? - UL LINE NUMBER + BNE L8B8A NO + PSHS X SAVE CURRENT POSITION OF INPUT POINTER + LDX #L8BD9-1 POINT X TO ‘UL’ MESSAGE + JSR LB99C PRINT STRING TO THE SCREEN + LDX ,S GET INPUT POINTER + LDD $01,X GET THE UNDEFINED LINE NUMBER + JSR LBDCC CONVERT NUMBER IN ACCD TO DECIMAL AND DISPLAY IT + JSR LBDC5 PRINT ‘IN XXXX’ XXXX = CURRENT LINE NUMBER + JSR LB958 SEND A CR TO CONSOLE OUT + PULS X GET INPUT POINTER BACK +L8BAE PSHS X SAVE CURRENT POSITION OF INPUT POINTER + LDD $01,X LOAD ACCD WITH BINARY VALUE OF LINE NUMBER + STD FPA0+2 SAVE IN BOTTOM 2 BYTES OF FPA0 + JSR L880E ADJUST REST OF FPA0 AS AN INTEGER + JSR LBDD9 CONVERT FPA0 TO ASCII, STORE IN LINE NUMBER + PULS U LOAD U WITH PREVIOUS ADDRESS OF INPUT POINTER + LDB #$05 EACH EXPANDED LINE NUMBER USES 5 BYTES +L8BBE LEAX $01,X MOVE POINTER FORWARD ONE + LDA ,X GET AN ASCII BYTE + BEQ L8BC9 BRANCH IF END OF NUMBER + DECB DECREMENT BYTE COUNTER + STA ,U+ STORE ASCII NUMBER IN BASIC LINE + BRA L8BBE CHECK FOR ANOTHER DIGIT +L8BC9 LEAX ,U TRANSFER NEW LINE POINTER TO (X) + TSTB DOES THE NEW LINE NUMBER REQUIRE 5 BYTES? + BEQ L8B8C YES - GO GET ANOTHER INPUT CHARACTER + LEAY ,U SAVE NEW LINE POINTER IN Y + LEAU B,U POINT U TO END OF 5 BYTE PACKED LINE NUMBER BLOCK + JSR L89B8 MOVE BYTES FROM (U) TO (X) UNTIL END OF PROGRAM + LEAX ,Y LOAD (X) WITH NEW LINE POINTER + BRA L8B8C GO GET ANOTHER INPUT CHARACTER + +L8BD9 FCC "UL " UNKNOWN LINE NUMBER MESSAGE + FCB 0 + + +HEXDOL JSR LB740 CONVERT FPA0 INTO A POSITIVE 2 BYTE INTEGER + LDX #STRBUF+2 POINT TO TEMPORARY BUFFER + LDB #$04 CONVERT 4 NIBBLES +L8BE5 PSHS B SAVE NIBBLE COUNTER + CLRB CLEAR CARRY FLAG + LDA #$04 4 SHIFTS +L8BEA ASL FPA0+3 * SHIFT BOTTOM TWO BYTES OF + ROL FPA0+2 * FPA0 LEFT ONE BIT (X2) + ROLB IF OVERFLOW, ACCB <> 0 + DECA * DECREMENT SHIFT COUNTER AND + BNE L8BEA * BRANCH IF NOT DONE + TSTB CHECK FOR OVERFLOW + BNE L8BFF BRANCH IF OVERFLOW + LDA ,S * GET NIBBLE COUNTER, + DECA * DECREMENT IT AND + BEQ L8BFF * BRANCH IF DONE + CMPX #STRBUF+2 DO NOT DO A CONVERSION UNTIL A NON-ZERO + BEQ L8C0B BYTE IS FOUND - LEADING ZERO SUPPRESSION +L8BFF ADDB #'0' ADD IN ASCII ZERO + CMPB #'9' COMPARE TO ASCII 9 + BLS L8C07 BRANCH IF < 9 + ADDB #7 ADD ASCII OFFSET IF HEX LETTER +L8C07 STB ,X+ STORE HEX VALUE AND ADVANCE POINTER + CLR ,X CLEAR NEXT BYTE - END OF STRING FLAG +L8C0B PULS B * GET NIBBLE COUNTER, + DECB * DECREMENT IT AND + BNE L8BE5 * BRANCH IF NOT DONE + LEAS $02,S PURGE RETURN ADDRESS OFF OF STACK + LDX #STRBUF+1 RESET POINTER + JMP LB518 SAVE STRING ON STRING STACK +* PROCESS EXCLAMATION POINT +L8E37 LDA #$01 * SET SPACES + STA VD9 * COUNTER = 1 +* PROCESS STRING ITEM - LIST +L8E3B DECB DECREMENT FORMAT STRING LENGTH COUNTER + JSR L8FD8 SEND A '+' TO CONSOLE OUT IF VDA <>0 + JSR GETCCH GET CURRENT INPUT CHARACTER + LBEQ L8ED8 EXIT PRINT USING IF END OF LINE + STB VD3 SAVE REMAINDER FORMAT STRING LENGTH + JSR LB156 EVALUATE EXPRESSION + JSR LB146 ‘TM’ ERROR IF NUMERIC VARIABLE + LDX FPA0+2 * GET ITEM - LIST DESCRIPTOR ADDRESS + STX V4D * AND SAVE IT IN V4D + LDB VD9 GET SPACES COUNTER + JSR LB6AD PUT ACCB BYTES INTO STRING SPACE & PUT DESCRIPTOR ON STRING STACK + JSR LB99F PRINT THE FORMATTED STRING TO CONSOLE OUT +* PAD FORMAT STRING WITH SPACES IF ITEM - LIST STRING < FORMAT STRING LENGTH + LDX FPA0+2 POINT X TO FORMATTED STRING DESCRIPTOR ADDRESS + LDB VD9 GET SPACES COUNTER + SUBB ,X SUBTRACT LENGTH OF FORMATTED STRING +L8E5F DECB DECREMENT DIFFERENCE + LBMI L8FB3 GO INTERPRET ANOTHER ITEM - LIST + JSR LB9AC PAD FORMAT STRING WITH A SPACE + BRA L8E5F KEEP PADDING +* PERCENT SIGN - PROCESS A %SPACES% COMMAND +L8E69 STB VD3 * SAVE THE CURRENT FORMAT STRING + STX TEMPTR * COUNTER AND POINTER + LDA #$02 INITIAL SPACES COUNTER = 2 + STA VD9 SAVE IN SPACES COUNTER +L8E71 LDA ,X GET A CHARACTER FROM FORMAT STRING + CMPA #'%' COMPARE TO TERMINATOR CHARACTER + BEQ L8E3B BRANCH IF END OF SPACES COMMAND + CMPA #' ' BLANK + BNE L8E82 BRANCH IF ILLEGAL CHARACTER + INC VD9 ADD ONE TO SPACES COUNTER + LEAX $01,X MOVE FORMAT POINTER UP ONE + DECB DECREMENT LENGTH COUNTER + BNE L8E71 BRANCH IF NOT END OF FORMAT STRING +L8E82 LDX TEMPTR * RESTORE CURRENT FORMAT STRING COUNTER + LDB VD3 * AND POINTER TO POSITION BEFORE SPACES COMMAND + LDA #'%' SEND A ‘%’ TO CONSOLE OUT AS A DEBUGGING AID +* ERROR PROCESSOR - ILLEGAL CHARACTER OR BAD SYNTAX IN FORMAT STRING +L8E88 JSR L8FD8 SEND A ‘+' TO CONSOLE OUT IF VDA <> 0 + JSR PUTCHR SEND CHARACTER TO CONSOLE OUT + BRA L8EB9 GET NEXT CHARACTER IN FORMAT STRING + +* PRINT RAM HOOK +XVEC9 CMPA #TOK_USING USING TOKEN + BEQ L8E95 BRANCH IF PRINT USING + RTS + +* PRINT USING +* VDA IS USED AS A STATUS BYTE: BIT 6 = COMMA FORCE +* BIT 5=LEADING ASTERISK FORCE; BIT 4 = FLOATING $ FORCE +* BIT 3 = PRE SIGN FORCE; BIT 2 = POST SIGN FORCE; BIT 0 = EXPONENTIAL FORCE +L8E95 LEAS $02,S PURGE RETURN ADDRESS OFF THE STACK + JSR LB158 EVALUATE FORMAT STRING + JSR LB146 ‘TM’ ERROR IF VARIABLE TYPE = NUMERIC + LDB #';' CHECK FOR ITEM LIST SEPARATOR + JSR LB26F SYNTAX CHECK FOR ; + LDX FPA0+2 * GET FORMAT STRING DESCRIPTOR ADDRESS + STX VD5 * AND SAVE IT IN VD5 + BRA L8EAE GO PROCESS FORMAT STRING +L8EA8 LDA VD7 *CHECK NEXT PRINT ITEM FLAG AND + BEQ L8EB4 *‘FC’ ERROR IF NO FURTHER PRINT ITEMS + LDX VD5 RESET FORMAT STRING POINTER TO START OF STRING +L8EAE CLR VD7 RESET NEXT PRINT ITEM FLAG + LDB ,X GET LENGTH OF FORMAT STRING + BNE L8EB7 INTERPRET FORMAT STRING IF LENGTH > 0 +L8EB4 JMP LB44A ‘FC’ ERROR IF FORMAT STRING = NULL +L8EB7 LDX $02,X POINT X TO START OF FORMAT STRING +* INTERPRET THE FORMAT STRING +L8EB9 CLR VDA CLEAR THE STATUS BYTE +L8EBB CLR VD9 CLEAR LEFT DIGIT COUNTER + LDA ,X+ GET A CHARACTER FROM FORMAT STRING + CMPA #'!' EXCLAMATION POINT? + LBEQ L8E37 YES - STRING TYPE FORMAT + CMPA #'#' NUMBER SIGN? (DIGIT LOCATOR) + BEQ L8F24 YES - NUMERIC TYPE FORMAT + DECB DECREMENT FORMAT STRING LENGTH + BNE L8EE2 BRANCH IF NOT DONE + JSR L8FD8 SEND A ‘+‘ TO CONSOLE OUT IF VDA <> 0 + JSR PUTCHR SEND CHARACTER TO CONSOLE OUT +L8ED2 JSR GETCCH GET CURRENT CHARACTER FROM BASIC + BNE L8EA8 BRANCH IF NOT END OF LINE + LDA VD7 GET NEXT PRINT ITEM FLAG +L8ED8 BNE L8EDD BRANCH IF MORE PRINT ITEMS + JSR LB958 SEND A CARRIAGE RETURN TO CONSOLE OUT +L8EDD LDX VD5 POINT X TO FORMAT STRING DESCRIPTOR + JMP LB659 RETURN ADDRESS AND LENGTH OF FORMAT STRING - EXIT PRINT USING +L8EE2 CMPA #'+' CHECK FOR ‘+‘ (PRE-SIGN FORCE) + BNE L8EEF NO PLUS + JSR L8FD8 SEND A ‘+' TO CONSOLE OUT IF VDA <> 0 + LDA #$08 * LOAD THE STATUS BYTE WITH 8; + STA VDA * PRE-SIGN FORCE FLAG + BRA L8EBB INTERPRET THE REST OF THE FORMAT STRING +L8EEF CMPA #'.' DECIMAL POINT? + BEQ L8F41 YES + CMPA #'%' PERCENT SIGN? + LBEQ L8E69 YES + CMPA ,X COMPARE THE PRESENT FORMAT STRING INPUT +* CHARACTER TO THE NEXT ONE IN THE STRING +L8EFB BNE L8E88 NO MATCH - ILLEGAL CHARACTER +* TWO CONSECUTIVE EQUAL CHARACTERS IN FORMAT STRING + CMPA #'$' DOLLAR SIGN? + BEQ L8F1A YES - MAKE THE DOLLAR SIGN FLOAT + CMPA #'*' ASTERISK? + BNE L8EFB NO - ILLEGAL CHARACTER + LDA VDA * GRAB THE STATUS BYTE AND BET BIT 5 + ORA #$20 * TO INDICATE THAT THE OUTPUT WILL + STA VDA * BE LEFT PADDED WITH ASTERISKS + CMPB #2 * CHECK TO SEE IF THE $$ ARE THE LAST TWO + BLO L8F20 * CHARACTERS IN THE FORMAT STRING AND BRANCH IF SO + LDA $01,X GET THE NEXT CHARACTER AFTER ** + CMPA #'$' CHECK FOR **$ + BNE L8F20 CHECK FOR MORE CHARACTERS + DECB DECREMENT STRING LENGTH COUNTER + LEAX $01,X MOVE FORMAT STRING POINTER UP ONE + INC VD9 ADD ONE TO LEFT DIGIT COUNTER - FOR ASTERISK PAD AND +* FLOATING DOLLAR SIGN COMBINATION +L8F1A LDA VDA * GET THE STATUS BYTE AND SET + ORA #$10 * BIT 4 TO INDICATE A + STA VDA * FLOATING DOLLAR SIGN +L8F20 LEAX $01,X MOVE FORMAT STRING POINTER UP ONE + INC VD9 ADD ONE TO LEFT DIGIT (FLOATING $ OR ASTERISK PAD) +* PROCESS CHARACTERS TO THE LEFT OF THE DECIMAL POINT IN THE FORMAT STRING +L8F24 CLR VD8 CLEAR THE RIGHT DIGIT COUNTER +L8F26 INC VD9 ADD ONE TO LEFT DIGIT COUNTER + DECB DECREMENT FORMAT STRING LENGTH COUNTER + BEQ L8F74 BRANCH IF END OF FORMAT STRING + LDA ,X+ GET THE NEXT FORMAT CHARACTER + CMPA #'.' DECIMAL POINT? + BEQ L8F4F YES + CMPA #'#' NUMBER SIGN? + BEQ L8F26 YES + CMPA #',' COMMA? + BNE L8F5A NO + LDA VDA * GET THE STATUS BYTE + ORA #$40 * AND SET BIT 6 WHICH IS THE + STA VDA * COMMA SEPARATOR FLAG + BRA L8F26 PROCESS MORE CHARACTERS TO LEFT OF DECIMAL POINT +* PROCESS DECIMAL POINT IF NO DIGITS TO LEFT OF IT +L8F41 LDA ,X GET NEXT FORMAT CHARACTER + CMPA #'#' IS IT A NUMBER SIGN? + LBNE L8E88 NO + LDA #1 * SET THE RIGHT DIGIT COUNTER TO 1 - + STA VD8 * ALLOW ONE SPOT FOR DECIMAL POINT + LEAX $01,X MOVE FORMAT POINTER UP ONE +* PROCESS DIGITS TO RIGHT OF DECIMAL POINT +L8F4F INC VD8 ADD ONE TO RIGHT DIGIT COUNTER + DECB DECREMENT FORMAT LENGTH COUNTER + BEQ L8F74 BRANCH IF END OF FORMAT STRING + LDA ,X+ GET A CHARACTER FROM FORMAT STRING + CMPA #'#' IS IT NUMBER SIGN? + BEQ L8F4F YES - KEEP CHECKING +* CHECK FOR EXPONENTIAL FORCE +L8F5A CMPA #$5E CHECK FOR UP ARROW + BNE L8F74 NO UP ARROW + CMPA ,X IS THE NEXT CHARACTER AN UP ARROW? + BNE L8F74 NO + CMPA $01,X AND THE NEXT CHARACTER? + BNE L8F74 NO + CMPA $02,X HOW ABOUT THE 4TH CHARACTER? + BNE L8F74 NO, ALSO + CMPB #4 * CHECK TO SEE IF THE 4 UP ARROWS ARE IN THE + BLO L8F74 * FORMAT STRING AND BRANCH IF NOT + SUBB #4 * MOVE POINTER UP 4 AND SUBTRACT + LEAX $04,X * FOUR FROM LENGTH + INC VDA INCREMENT STATUS BYTE - EXPONENTIAL FORM + +* CHECK FOR A PRE OR POST - SIGN FORCE AT END OF FORMAT STRING +L8F74 LEAX $-01,X MOVE POINTER BACK ONE + INC VD9 ADD ONE TO LEFT DIGIT COUNTER FOR PRE-SIGN FORCE + LDA VDA * PRE-SIGN + BITA #$08 * FORCE AND + BNE L8F96 * BRANCH IF SET + DEC VD9 DECREMENT LEFT DIGIT — NO PRE-SIGN FORCE + TSTB * CHECK LENGTH COUNTER AND BRANCH + BEQ L8F96 * IF END OF FORMAT STRING + LDA ,X GET NEXT FORMAT STRING CHARACTER + SUBA #'-' CHECK FOR MINUS SIGN + BEQ L8F8F BRANCH IF MINUS SIGN + CMPA #$FE * WAS CMPA #('+')-('-') + BNE L8F96 BRANCH IF NO PLUS SIGN + LDA #$08 GET THE PRE-SIGN FORCE FLAG +L8F8F ORA #$04 ‘OR’ IN POST-SIGN FORCE FLAG + ORA VDA ‘OR’ IN THE STATUS BYTE + STA VDA SAVE THE STATUS BYTE + DECB DECREMENT FORMAT STRING LENGTH + +* EVALUATE NUMERIC ITEM-LIST +L8F96 JSR GETCCH GET CURRENT CHARACTER + LBEQ L8ED8 BRANCH IF END OF LINE + STB VD3 SAVE FORMAT STRING LENGTH WHEN FORMAT EVALUATION ENDED + JSR LB141 EVALUATE EXPRESSION + LDA VD9 GET THE LEFT DIGIT COUNTER + ADDA VD8 ADD IT TO THE RIGHT DIGIT COUNTER + CMPA #17 * + LBHI LB44A *‘FC’ ERROR IF MORE THAN 16 DIGITS AND DECIMAL POiNT + JSR L8FE5 CONVERT ITEM-LIST TO FORMATTED ASCII STRING + LEAX $-01,X MOVE BUFFER POINTER BACK ONE + JSR LB99C DISPLAY THE FORMATTED STRING TO CONSOLE OUT +L8FB3 CLR VD7 RESET NEXT PRINT ITEM FLAG + JSR GETCCH GET CURRENT INPUT CHARACTER + BEQ L8FC6 BRANCH IF END OF LINE + STA VD7 SAVE CURRENT CHARACTER (<>0) IN NEXT PRINT ITEM FLAG + CMPA #';' * CHECK FOR ; - ITEM-LIST SEPARATOR AND + BEQ L8FC4 * BRANCH IF SEMICOLON + JSR LB26D SYNTAX CHECK FOR COMMA + BRA L8FC6 PROCESS NEXT PRINT ITEM +L8FC4 JSR GETNCH GET NEXT INPUT CHARACTER +L8FC6 LDX VD5 GET FORMAT STRING DESCRIPTOR ADDRESS + LDB ,X GET LENGTH OF FORMAT STRING + SUBB VD3 SUBTRACT AMOUNT OF FORMAT STRING LEFT AFTER LAST PRINT ITEM + LDX $02,X *GET FORMAT STRING START ADDRESS AND ADVANCE + ABX *POINTER TO START OF UNUSED FORMAT STRING + LDB VD3 * GET AMOUNT OF UNUSED FORMAT STRING + LBNE L8EB9 * REINTERPRET FORMAT STRING FROM THAT POINT + JMP L8ED2 REINTERPRET FORMAT STRING FROM THE START IF ENTIRELY +* USED ON LAST PRINT ITEM + +* PRINT A ‘+‘ TO CONSOLE OUT IF THE STATUS BYTE <> 0 +L8FD8 PSHS A RESTORE ACCA AND RETURN + LDA #'+' GET ASCII PLUS SIGN + TST VDA * CHECK THE STATUS BYTE AND + BEQ L8FE3 * RETURN IF = 0 + JSR PUTCHR SEND A CHARACTER TO CONSOLE OUT +L8FE3 PULS A,PC RETURN ACCA AND RETURN + +* CONVERT ITEM-LIST TO DECIMAL ASCII STRING +L8FE5 LDU #STRBUF+4 POINT U TO STRING BUFFER + LDB #SPACE BLANK + LDA VDA * GET THE STATUS FLAG AND + BITA #$08 * CHECK FOR A PRE-SIGN FORCE + BEQ L8FF2 * BRANCH IF NO PRE-SIGN FORCE + LDB #'+' PLUS SIGN +L8FF2 TST FP0SGN CHECK THE SIGN OF FPA0 + BPL L8FFA BRANCH IF POSITIVE + CLR FP0SGN FORCE FPA0 SIGN TO BE POSITIVE + LDB #'-' MINUS SIGN +L8FFA STB ,U+ SAVE THE SIGN IN BUFFER + LDB #'0' * PUT A ZERO INTO THE BUFFER + STB ,U+ * + ANDA #$01 * CHECK THE EXPONENTIAL FORCE FLAG IN + LBNE L910D * THE STATUS BYTE - BRANCH IF ACTIVE + LDX #LBDC0 POINT X TO FLOATING POINT 1E + 09 + JSR LBCA0 COMPARE FPA0 TO (X) + BMI L9023 BRANCH IF FPA0 < 1E+09 + JSR LBDD9 CONVERT FP NUMBER TO ASCII STRING +L9011 LDA ,X+ * ADVANCE POINTER TO END OF + BNE L9011 * ASCII STRING (ZERO BYTE) +L9015 LDA ,-X MOVE THE + STA $01,X ENTIRE STRING + CMPX #STRBUF+3 UP ONE + BNE L9015 BYTE + LDA #'%' * INSERT A % SIGN AT START OF + STA ,X * STRING - OVERFLOW ERROR + RTS + +L9023 LDA FP0EXP GET EXPONENT OF FPA0 + STA V47 AND SAVE IT IN V74 + BEQ L902C BRANCH IF FPA0 = 0 + JSR L91CD CONVERT FPA0 TO NUMBER WITH 9 SIGNIFICANT +* PLACES TO LEFT OF DECIMAL POINT +L902C LDA V47 GET BASE 10 EXPONENT OFFSET + LBMI L90B3 BRANCH IF FPA0 < 100,000,000 + NEGA * CALCULATE THE NUMBER OF LEADING ZEROES TO INSERT - + ADDA VD9 * SUBTRACT BASE 10 EXPONENT OFFSET AND 9 (FPA0 HAS + SUBA #$09 * 9 PLACES TO LEFT OF EXPONENT) FROM LEFT DIGIT COUNTER + JSR L90EA PUT ACCA ZEROES IN STRING BUFFER + JSR L9263 INITIALIZE DECIMAL POINT AND COMMA COUNTERS + JSR L9202 CONVERT FPA0 TO DECIMAL ASCII IN THE STRING BUFFER + LDA V47 * GET BASE 10 EXPONENT AND PUT THAT MANY + JSR L9281 * ZEROES IN STRING BUFFER - STOP AT DECIMAL POINT + LDA V47 WASTED INSTRUCTION - SERVES NO PURPOSE + JSR L9249 CHECK FOR DECIMAL POINT + LDA VD8 GET THE RIGHT DIGIT COUNTER + BNE L9050 BRANCH IF RIGHT DIGlT COUNTER <> 0 + LEAU $-01,U * MOVE BUFFER POINTER BACK ONE - DELETE +* * DECIMAL POINT IF NO RIGHT DIGITS SPECiFIED +L9050 DECA SUBTRACT ONE (DECIMAL POINT) + JSR L90EA PUT ACCA ZEROES INTO BUFFER (TRAILING ZEROES) +L9054 JSR L9185 INSERT ASTERISK PADDING, FLOATING $, AND POST-SIGN + TSTA WAS THERE A POST-SIGN? + BEQ L9060 NO + CMPB #'*' IS THE FIRST CHARACTER AN $? + BEQ L9060 YES + STB ,U+ STORE THE POST-SIGN +L9060 CLR ,U CLEAR THE LAST CHARACTER IN THE BUFFER +* +* REMOVE ANY EXTRA BLANKS OR ASTERISKS FROM THE +* STRING BUFFER TO THE LEFT OF THE DECIMAL POINT + LDX #STRBUF+3 POINT X TO THE START OF THE BUFFER +L9065 LEAX $01,X MOVE BUFFER POINTER UP ONE + STX TEMPTR SAVE BUFFER POINTER IN TEMPTR + LDA VARPTR+1 * GET ADDRESS OF DECIMAL POINT IN BUFFER, SUBTRACT + SUBA TEMPTR+1 * CURRENT POSITION AND SUBTRACT LEFT DIGIT COUNTER - + SUBA VD9 * THE RESULT WILL BE ZERO WHEN TEMPTR+1 IS POINTING +* * TO THE FIRST DIGIT OF THE FORMAT STRING + BEQ L90A9 RETURN IF NO DIGITS TO LEFT OF THE DECiMAL POINT + LDA ,X GET THE CURRENT BUFFER CHARACTER + CMPA #SPACE SPACE? + BEQ L9065 YES - ADVANCE POINTER + CMPA #'*' ASTERISK? + BEQ L9065 YES - ADVANCE POINTER + CLRA A ZERO ON THE STACK IS END OF DATA POINTER +L907C PSHS A PUSH A CHARACTER ONTO THE STACK + LDA ,X+ GET NEXT CHARACTER FROM BUFFER + CMPA #'-' MINUS SIGN? + BEQ L907C YES + CMPA #'+' PLUS SIGN? + BEQ L907C YES + CMPA $'$' DOLLAR SIGN? + BEQ L907C YES + CMPA #'0' ZERO? + BNE L909E NO - ERROR + LDA $01,X GET CHARACTER FOLLOWING ZERO + BSR L90AA CLEAR CARRY IF NUMERIC + BLO L909E BRANCH IF NOT A NUMERIC CHARACTER - ERROR +L9096 PULS A * PULL A CHARACTER OFF OF THE STACK + STA ,-X * AND PUT IT BACK IN THE STRING BUFFER + BNE L9096 * KEEP GOING UNTIL ZERO FLAG + BRA L9065 KEEP CLEANING UP THE INPUT BUFFER +L909E PULS A + TSTA * THE STACK AND EXIT WHEN + BNE L909E * ZERO FLAG FOUND + LDX TEMPTR GET THE STRING BUFFER START POINTER + LDA #'%' * PUT A % SIGN BEFORE THE ERROR POSITION TO + STA ,-X * INDICATE AN ERROR +L90A9 RTS +* +* CLEAR CARRY IF NUMERIC +L90AA CMPA #'0' ASCII ZERO + BLO L90B2 RETURN IF ACCA < ASCII 0 + SUBA #$3A * #'9'+1 + SUBA #$C6 * #-('9'+1) CARRY CLEAR IF NUMERIC +L90B2 RTS +* +* PROCESS AN ITEM-LIST WHICH IS < 100,000,000 +L90B3 LDA VD8 GET RIGHT DIGIT COUNTER + BEQ L90B8 BRANCH IF NO FORMATTED DIGITS TO THE RIGHT OF DECIMAL PT + DECA SUBTRACT ONE FOR DECIMAL POINT +L90B8 ADDA V47 *ADD THE BASE 10 EXPONENT OFFSET - ACCA CONTAINS THE +* *NUMBER OF SHIFTS REQUIRED TO ADJUST FPA0 TO THE SPECIFIED +* *NUMBER OF DlGITS TO THE RIGHT OF THE DECIMAL POINT + BMI L90BD IF ACCA >= 0 THEN NO SHIFTS ARE REQUIRED + CLRA FORCE SHIFT COUNTER = 0 +L90BD PSHS A SAVE INITIAL SHIFT COUNTER ON THE STACK +L90BF BPL L90CB EXIT ROUTINE IF POSITIVE + PSHS A SAVE SHIFT COUNTER ON STACK + JSR LBB82 DIVIDE FPA0 BY 10 - SHIFT ONE DIGIT TO RIGHT + PULS A GET SHIFT COUNTER FROM THE STACK + INCA BUMP SHIFT COUNTER UP BY ONE + BRA L90BF CHECK FOR FURTHER DIVISION +L90CB LDA V47 * GET BASE 10 EXPONENT OFFSET, ADD INITIAL SHIFT COUNTER + SUBA ,S+ * AND SAVE NEW BASE 10 EXPONENT OFFSET - BECAUSE + STA V47 * FPA0 WAS SHIFTED ABOVE + ADDA #$09 * ADD NINE (SIGNIFICANT PLACES) AND BRANCH IF THERE ARE NO + BMI L90EE * ZEROES TO THE LEFT OF THE DECIMAL POINT IN THIS PRINT ITEM + LDA VD9 *DETERMINE HOW MANY FILLER ZEROES TO THE LEFT OF THE DECIMAL + SUBA #$09 *POINT. GET THE NUMBER OF FORMAT PLACES TO LEFT OF DECIMAL + SUBA V47 *POINT, SUBTRACT THE BASE 10 EXPONENT OFFSET AND THE CONSTANT 9 + BSR L90EA *(UNNORMALIZATION)-THEN OUTPUT THAT MANY ZEROES TO THE BUFFER + JSR L9263 INITIALIZE DECIMAL POINT AND COMMA COUNTERS + BRA L90FF PROCESS THE REMAINDER OF THE PRINT ITEM +* +* PUT (ACCA+1) ASCII ZEROES IN BUFFER +L90E2 PSHS A SAVE ZERO COUNTER + LDA #'0' * INSERT A ZERO INTO + STA ,U+ * THE BUFFER + PULS A RESTORE ZERO COUNTER + +* PUT ACCA ASCII ZEROES INTO THE BUFFER +L90EA DECA DECREMENT ZERO COUNTER + BPL L90E2 BRANCH IF NOT DONE + RTS + +L90EE LDA VD9 * GET THE LEFT DIGIT COUNTER AND PUT + BSR L90EA * THAT MANY ZEROES IN THE STRiNG BUFFER + JSR L924D PUT THE DECIMAL POINT IN THE STRING BUFFER + LDA #-9 *DETERMINE HOW MANY FILLER ZEROES BETWEEN THE DECIMAL POINT + SUBA V47 *AND SIGNIFICANT DATA. SUBTRACT BASE 10 EXPONENT FROM -9 + BSR L90EA *(UNNORMALIZATION) AND OUTPUT THAT MANY ZEROES TO BUFFER + CLR V45 CLEAR THE DECIMAL POINT COUNTER - SUPPRESS THE DECIMAL POINT + CLR VD7 CLEAR THE COMMA COUNTER - SUPPRESS COMMAS +L90FF JSR L9202 DECODE FPA0 INTO A DECIMAL ASCII STRING + LDA VD8 GET THE RIGHT DIGIT COUNTER + BNE L9108 BRANCH IF RIGHT DIGIT COUNTER <> 0 + LDU VARPTR RESET BUFFER PTR TO THE DECIMAL POINT IF NO DIGITS TO RIGHT +L9108 ADDA V47 *ADD BASE 10 EXPONENT - A POSITIVE ACCA WILL CAUSE THAT MANY +* *FILLER ZEROES TO BE OUTPUT TO THE RIGHT OF LAST SIGNIFICANT DATA +* *SIGNIFICANT DATA + LBRA L9050 INSERT LEADING ASTERISKS, FLOATING DOLLAR SIGN, ETC +* +* FORCE THE NUMERIC OUTPUT FORMAT TO BE EXPONENTIAL FORMAT +L910D LDA FP0EXP * GET EXPONENT OF FPA0 AND + PSHS A * SAVE IT ON THE STACK + BEQ L9116 BRANCH IF FPA0 = 0 + JSR L91CD *CONVERT FPA0 INTO A NUMBER WITH 9 SIGNIFICANT +* *DIGITS TO THE LEFT OF THE DECIMAL POINT +L9116 LDA VD8 GET THE RIGHT DIGIT COUNTER + BEQ L911B BRANCH IF NO FORMATTED DIGITS TO THE RIGHT + DECA SUBTRACT ONE FOR THE DECIMAL POINT +L911B ADDA VD9 ADD TO THE LEFT DIGIT COUNTER + CLR STRBUF+3 CLEAR BUFFER BYTE AS TEMPORARY STORAGE LOCATION + LDB VDA * GET THE STATUS BYTE FOR A + ANDB #$04 * POST-BYTE FORCE; BRANCH IF + BNE L9129 * A POST-BYTE FORCE + COM STRBUF+3 TOGGLE BUFFER BYTE TO -1 IF NO POST-BYTE FORCE +L9129 ADDA STRBUF+3 SUBTRACT 1 IF NO POST BYTE FORCE + SUBA #$09 *SUBTRACT 9 (DUE TO THE CONVERSION TO 9 +* *SIGNIFICANT DIGITS TO LEFT OF DECIMAL POINT) + PSHS A * SAVE SHIFT COUNTER ON THE STACK - ACCA CONTAINS THE NUMBER +* OF SHIFTS REQUIRED TO ADJUST FPA0 FOR THE NUMBER OF +* FORMATTED PLACES TO THE RIGHT OF THE DECIMAL POINT. +L9130 BPL L913C NO MORE SHIFTS WHEN ACCA >= 0 + PSHS A SAVE SHIFT COUNTER + JSR LBB82 DIVIDE FPA0 BY 10 - SHIFT TO RIGHT ONE + PULS A RESTORE THE SHIFT COUNTER + INCA ADD 1 TO SHIFT COUNTER + BRA L9130 CHECK FOR FURTHER SHIFTING (DIVISION) +L913C LDA ,S *GET THE INITIAL VALUE OF THE SHIFT COUNTER + BMI L9141 *AND BRANCH IF SHIFTING HAS TAKEN PLACE + CLRA RESET ACCA IF NO SHIFTING HAS TAKEN PLACE +L9141 NEGA *CALCULATE THE POSITION OF THE DECIMAL POINT BY + ADDA VD9 *NEGATING SHIFT COUNTER, ADDING THE LEFT DIGIT COUNTER + INCA *PLUS ONE AND THE POST-BYTE POSlTION, IF USED + ADDA STRBUF+3 * + STA V45 SAVE DECIMAL POINT COUNTER + CLR VD7 CLEAR COMMA COUNTER - NO COMMAS INSERTED + JSR L9202 CONVERT FPA0 INTO ASCII DECIMAL STRING + PULS A * GET THE INITIAL VALUE OF SHIFT COUNTER AND + JSR L9281 * INSERT THAT MANY ZEROES INTO THE BUFFER + LDA VD8 *GET THE RIGHT DIGIT COUNTER AND BRANCH + BNE L915A *IF NOT ZERO + LEAU $-01,U MOVE BUFFER POINTER BACK ONE + +* CALCULATE VALUE OF EXPONENT AND PUT IN STRING BUFFER +L915A LDB ,S+ GET ORIGINAL EXPONENT OF FPA0 + BEQ L9167 BRANCH IF EXPONENT = 0 + LDB V47 GET BASE 10 EXPONENT + ADDB #$09 ADD 9 FOR 9 SIGNIFICANT DIGIT CONVERSION + SUBB VD9 SUBTRACT LEFT DIGIT COUNTER + SUBB STRBUF+3 ADD ONE TO EXPONENT IF POST-SIGN FORCE +L9167 LDA #'+' PLUS SIGN + TSTB TEST EXPONENT + BPL L916F BRANCH IF POSITIVE EXPONENT + LDA #'-' MINUS SIGN + NEGB CONVERT EXPONENT TO POSITIVE NUMBER +L916F STA $01,U PUT SIGN OF EXPONENT IN STRING BUFFER + LDA #'E' * PUT AN ‘E’ (EXPONENTIATION FLAG) IN + STA ,U++ * BUFFER AND SKIP OVER THE SIGN + LDA #$2F * WAS LDA #'0'-1 +*CONVERT BINARY EXPONENT IN ACCB TO ASCII VALUE IN ACCA +L9177 INCA ADD ONE TO TENS DIGIT COUNTER + SUBB #10 *SUBTRACT 10 FROM EXPONENT AND ADD ONE TO TENS + BCC L9177 * DIGIT IF NO CARRY. TENS DIGIT DONE IF THERE IS A CARRY + ADDB #$3A WAS ADDB #'9'+1 + STD ,U++ SAVE EXPONENT IN BUFFER + CLR ,U CLEAR FINAL BYTE IN BUFFER - PRINT TERMINATOR + JMP L9054 INSERT ASTERISK PADDING, FLOATING DOLLAR SIGN, ETC. + +* INSERT ASTERISK PADDING, FLOATING $ AND PRE-SIGN +L9185 LDX #STRBUF+4 POINT X TO START OF PRINT ITEM BUFFER + LDB ,X * GET SIGN BYTE OF ITEM-LIST BUFFER + PSHS B * AND SAVE IT ON THE STACK + LDA #SPACE DEFAULT PAD WITH BLANKS + LDB VDA * GET STATUS BYTE AND CHECK FOR + BITB #$20 * ASTERISK LEFT PADDING + PULS B GET SIGN BYTE AGAIN + BEQ L919E BRANCH IF NO PADDING + LDA #'*' PAD WITH ASTERISK + CMPB #SPACE WAS THE FIRST BYTE A BLANK (POSITIVE)? + BNE L919E NO + TFR A,B TRANSFER PAD CHARACTER TO ACCB +L919E PSHS B SAVE FIRST CHARACTER ON STACK +L91A0 STA ,X+ STORE PAD CHARACTER IN BUFFER + LDB ,X GET NEXT CHARACTER IN BUFFER + BEQ L91B6 INSERT A ZERO IF END OF BUFFER + CMPB #'E' * CHECK FOR AN ‘E’ AND + BEQ L91B6 * PUT A ZERO BEFORE IT + CMPB #'0' * REPLACE LEADING ZEROES WITH + BEQ L91A0 * PAD CHARACTERS + CMPB #',' * REPLACE LEADING COMMAS + BEQ L91A0 * WITH PAD CHARACTERS + CMPB #'.' * CHECK FOR DECIMAL POINT + BNE L91BA * AND DON’T PUT A ZERO BEFORE IT +L91B6 LDA #'0' * REPLACE PREVIOUS CHARACTER + STA ,-X * WITH A ZERO +L91BA LDA VDA * GET STATUS BYTE, CHECK + BITA #$10 * FOR FLOATING $ + BEQ L91C4 * BRANCH IF NO FLOATING $ + LDB #'$' * STORE A $ IN + STB ,-X * BUFFER +L91C4 ANDA #$04 CHECK PRE-SIGN FLAG + PULS B GET SIGN CHARACTER + BNE L91CC RETURN IF POST-SIGN REQUIRED + STB ,-X STORE FIRST CHARACTER +L91CC RTS +* +* CONVERT FPA0 INTO A NUMBER OF THE FORM - NNN,NNN,NNN X 10**M. +* THE EXPONENT M WILL BE RETURNED IN V47 (BASE 10 EXPONENT). +L91CD PSHS U SAVE BUFFER POINTER + CLRA INITIAL EXPONENT OFFSET = 0 +L91D0 STA V47 SAVE EXPONENT OFFSET + LDB FP0EXP GET EXPONENT OF FPA0 + CMPB #$80 * COMPARE TO EXPONENT OF .5 + BHI L91E9 * AND BRANCH IF FPA0 > = 1.0 + +* IF FPA0 < 1.0, MULTIPLY IT BY 1E+09 UNTIL IT IS >= 1 + LDX #LBDC0 POINT X TO FP NUMBER (1E+09) + JSR LBACA MULTIPLY FPA0 BY 1E+09 + LDA V47 GET EXPONENT OFFSET + SUBA #$09 SUBTRACT 9 (BECAUSE WE MULTIPLIED BY 1E+09 ABOVE) + BRA L91D0 CHECK TO SEE IF > 1.0 +L91E4 JSR LBB82 DIVIDE FPA0 BY 10 + INC V47 INCREMENT EXPONENT OFFSET +L91E9 LDX #LBDBB POINT X TO FP NUMBER (999,999,999) + JSR LBCA0 COMPARE FPA0 TO X + BGT L91E4 BRANCH IF FPA0 > 999,999,999 +L91F1 LDX #LBDB6 POINT X TO FP NUMBER (99,999,999.9) + JSR LBCA0 COMPARE FPA0 TO X + BGT L9200 RETURN IF 999,999,999 > FPA0 > 99,999,999.9 + JSR LBB6A MULTIPLY FPA0 BY 10 + DEC V47 DECREMENT EXPONENT OFFSET + BRA L91F1 KEEP UNNORMALIZING +L9200 PULS U,PC RESTORE BUFFER POINTER AND RETURN +* +* CONVERT FPA0 INTO AN INTEGER, THEN DECODE IT +* INTO A DECIMAL ASCII STRING IN THE BUFFER +L9202 PSHS U SAVE BUFFER POINTER + JSR LB9B4 ADD .5 TO FPA0 (ROUND OFF) + JSR LBCC8 CONVERT FPA0 TO INTEGER FORMAT + PULS U RESTORE BUFFER POINTER +* +* CONVERT FPA0 INTO A DECIMAL ASCII STRING + LDX #LBEC5 POINT X TO UNNORMALIZED POWERS OF 10 + LDB #$80 INITIALIZE DIGIT COUNTER TO 0 + $80. +* BIT 7 SET IS USED TO INDICATE THAT THE POWER OF 10 MANTISSA +* IS NEGATIVE. WHEN YOU ‘ADD’ A NEGATIVE MANTISSA, IT IS +* THE SAME AS SUBTRACTING A POSITIVE ONE AND BIT 7 OF ACCB +* IS HOW THIS ROUTINE KNOWS THAT A ‘SUBTRACTION’ IS OCCURRING. +L9211 BSR L9249 CHECK FOR COMMA INSERTION +L9213 LDA FPA0+3 * ‘ADD’ A POWER OF 10 MANTISSA TO FPA0. + ADDA $03,X * IF THE MANTISSA IS NEGATIVE, A SUBTRACTION + STA FPA0+3 * WILL BE WHAT REALLY TAKES PLACE. + LDA FPA0+2 * + ADCA $02,X * + STA FPA0+2 * + LDA FPA0+1 * + ADCA $01,X * + STA FPA0+1 * + LDA FPA0 * + ADCA ,X * + STA FPA0 * + INCB ADD ONE TO DIGIT COUNTER + RORB ROTATE CARRY INTO BIT 7 + ROLB * SET OVERFLOW FLAG - BRANCH IF CARRY SET AND + BVC L9213 * ADDING MANTISSA OR CARRY CLEAR AND SUBTRACTING MANTISSA + BCC L9235 BRANCH IF SUBTRACTING MANTISSA + SUBB #10+1 WAS SUBB #10+1 + NEGB * IF ADDING MANTISSA +L9235 ADDB #$2F WAS ADDB #'0'-1 + LEAX $04,X MOVE TO NEXT POWER OF 10 MANTISSA + TFR B,A SAVE DIGIT IN ACCA + ANDA #$7F MASK OFF ADD/SUBTRACT FLAG (BIT 7) + STA ,U+ STORE DIGIT IN BUFFER + COMB TOGGLE ADD/SUBTRACT FLAG + ANDB #$80 MASK OFF EVERYTHING BUT ADD/SUB FLAG + CMPX #LBEE9 COMPARE TO END OF UNNORMALIZED POWERS OF 10 + BNE L9211 BRANCH IF NOT DONE + CLR ,U PUT A ZERO AT END OF INTEGER + +* DECREMENT DECIMAL POINT COUNTER AND CHECK FOR COMMA INSERTION +L9249 DEC V45 DECREMENT DECIMAL POINT COUNTER + BNE L9256 NOT TIME FOR DECIMAL POINT +L924D STU VARPTR SAVE BUFFER POINTER-POSITION OF THE DECIMAL POINT + LDA #'.' * STORE A DECIMAL + STA ,U+ * POINT IN THE OUTPUT BUFFER + CLR VD7 * CLEAR COMMA COUNTER - NOW IT WILL TAKE 255 +* * DECREMENTS BEFORE ANOTHER COMMA WILL BE INSERTED + RTS +L9256 DEC VD7 DECREMENT COMMA COUNTER + BNE L9262 RETURN IF NOT TIME FOR COMMA + LDA #$03 * RESET COMMA COUNTER TO 3; THREE + STA VD7 * DIGITS BETWEEN COMMAS + LDA #',' * PUT A COMMA INTO + STA ,U+ * THE BUFFER +L9262 RTS + +* INITIALIZE DECIMAL POINT AND COMMA COUNTERS +L9263 LDA V47 GET THE BASE 10 EXPONENT OFFSET + ADDA #10 * ADD 10 (FPA0 WAS ‘NORMALIZED’ TO 9 PLACES LEFT + STA V45 * OF DECIMAL POINT) - SAVE IN DECIMAL POINT COUNTER + INCA ADD ONE FOR THE DECIMAL POINT +L926A SUBA #$03 * DIVIDE DECIMAL POINT COUNTER BY 3; LEAVE + BCC L926A * THE REMAINDER IN ACCA + ADDA #$05 CONVERT REMAINDER INTO A NUMBER FROM 1-3 + STA VD7 SAVE COMMA COUNTER + LDA VDA GET STATUS BYTE + ANDA #$40 CHECK FOR COMMA FLAG + BNE L927A BRANCH IF COMMA FLAG ACTIVE + STA VD7 CLEAR COMMA COUNTER - 255 DIGITS OUTPUT BEFORE A COMMA +L927A RTS +* +* INSERT ACCA ZEROES INTO THE BUFFER +L927B PSHS A SAVE ZEROES COUNTER + BSR L9249 CHECK FOR DECIMAL POINT + PULS A RESTORE ZEROES COUNTER +L9281 DECA * DECREMENT ZEROES COUNTER AND + BMI L928E * RETURN IF < 0 + PSHS A SAVE ZEROES COUNTER + LDA #'0' * PUT A ZERO INTO + STA ,U+ * THE BUFFER + LDA ,S+ RESTORE THE ZEROES COUNTER + BNE L927B BRANCH IF NOT DONE +L928E RTS + + +* LINE +LINE CMPA #TOK_INPUT ‘INPUT’ TOKEN + LBEQ L89C0 GO DO ‘LINE INPUT’ COMMAND + JMP LB277 ‘SYNTAX ERROR’ IF NOT "LINE INPUT" + + +* END OF EXTENDED BASIC +* INTERRUPT VECTORS + ORG $FFF0 +LBFF0 FDB $0000 RESERVED +LBFF2 FDB SW3VEC SWI3 +LBFF4 FDB SW2VEC SWI2 +LBFF6 FDB FRQVEC FIRQ +LBFF8 FDB IRQVEC IRQ +LBFFA FDB SWIVEC SWI +LBFFC FDB NMIVEC NMI +LBFFE FDB RESVEC RESET diff --git a/MC6809/MC6809.Test/roms/searle/ExBasROM.hex b/MC6809/MC6809.Test/roms/searle/ExBasROM.hex new file mode 100644 index 0000000..ceceb8a --- /dev/null +++ b/MC6809/MC6809.Test/roms/searle/ExBasROM.hex @@ -0,0 +1,513 @@ +:20C00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF40 +:20C02000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF20 +:20C04000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00 +:20C06000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE0 +:20C08000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC0 +:20C0A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA0 +:20C0C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF80 +:20C0E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF60 +:20C10000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3F +:20C12000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1F +:20C14000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +:20C16000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDF +:20C18000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBF +:20C1A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9F +:20C1C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7F +:20C1E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5F +:20C20000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3E +:20C22000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1E +:20C24000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE +:20C26000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDE +:20C28000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBE +:20C2A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9E +:20C2C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7E +:20C2E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5E +:20C30000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3D +:20C32000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1D +:20C34000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD +:20C36000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDD +:20C38000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBD +:20C3A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9D +:20C3C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7D +:20C3E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D +:20C40000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3C +:20C42000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1C +:20C44000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC +:20C46000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDC +:20C48000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBC +:20C4A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C +:20C4C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7C +:20C4E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5C +:20C50000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3B +:20C52000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B +:20C54000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB +:20C56000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB +:20C58000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB +:20C5A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B +:20C5C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7B +:20C5E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5B +:20C60000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3A +:20C62000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1A +:20C64000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA +:20C66000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDA +:20C68000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBA +:20C6A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9A +:20C6C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7A +:20C6E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5A +:20C70000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF39 +:20C72000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF19 +:20C74000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9 +:20C76000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD9 +:20C78000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB9 +:20C7A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF99 +:20C7C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF79 +:20C7E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF59 +:20C80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF38 +:20C82000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF18 +:20C84000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8 +:20C86000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD8 +:20C88000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB8 +:20C8A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF98 +:20C8C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF78 +:20C8E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF58 +:20C90000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF37 +:20C92000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF17 +:20C94000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7 +:20C96000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD7 +:20C98000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7 +:20C9A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF97 +:20C9C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF77 +:20C9E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF57 +:20CA0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF36 +:20CA2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF16 +:20CA4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6 +:20CA6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD6 +:20CA8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB6 +:20CAA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF96 +:20CAC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF76 +:20CAE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF56 +:20CB0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF35 +:20CB2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF15 +:20CB4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5 +:20CB6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD5 +:20CB8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB5 +:20CBA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF95 +:20CBC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF75 +:20CBE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF55 +:20CC0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF34 +:20CC2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF14 +:20CC4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4 +:20CC6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD4 +:20CC8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB4 +:20CCA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF94 +:20CCC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF74 +:20CCE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF54 +:20CD0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF33 +:20CD2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF13 +:20CD4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3 +:20CD6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD3 +:20CD8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB3 +:20CDA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF93 +:20CDC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF73 +:20CDE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53 +:20CE0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF32 +:20CE2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF12 +:20CE4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2 +:20CE6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD2 +:20CE8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB2 +:20CEA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92 +:20CEC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF72 +:20CEE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF52 +:20CF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF31 +:20CF2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF11 +:20CF4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1 +:20CF6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD1 +:20CF8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB1 +:20CFA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF91 +:20CFC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF71 +:20CFE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF51 +:20D00000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF30 +:20D02000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF10 +:20D04000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0 +:20D06000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD0 +:20D08000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB0 +:20D0A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF90 +:20D0C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF70 +:20D0E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF50 +:20D10000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2F +:20D12000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0F +:20D14000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF +:20D16000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCF +:20D18000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAF +:20D1A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8F +:20D1C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6F +:20D1E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4F +:20D20000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2E +:20D22000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0E +:20D24000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEE +:20D26000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCE +:20D28000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAE +:20D2A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8E +:20D2C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E +:20D2E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4E +:20D30000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2D +:20D32000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0D +:20D34000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED +:20D36000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCD +:20D38000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAD +:20D3A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8D +:20D3C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6D +:20D3E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D +:20D40000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2C +:20D42000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0C +:20D44000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC +:20D46000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCC +:20D48000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAC +:20D4A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8C +:20D4C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6C +:20D4E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4C +:20D50000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2B +:20D52000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +:20D54000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEB +:20D56000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCB +:20D58000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAB +:20D5A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8B +:20D5C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6B +:20D5E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4B +:20D60000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF2A +:20D62000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0A +:20D64000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEA +:20D66000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCA +:20D68000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA +:20D6A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF8A +:20D6C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6A +:20D6E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4A +:20D70000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF29 +:20D72000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF09 +:20D74000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9 +:20D76000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC9 +:20D78000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA9 +:20D7A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF89 +:20D7C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF69 +:20D7E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF49 +:20D80000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF28 +:20D82000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF08 +:20D84000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE8 +:20D86000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC8 +:20D88000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA8 +:20D8A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF88 +:20D8C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF68 +:20D8E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF48 +:20D90000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF27 +:20D92000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF07 +:20D94000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE7 +:20D96000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7 +:20D98000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA7 +:20D9A000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF87 +:20D9C000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF67 +:20D9E000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF47 +:20DA0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF26 +:20DA2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06 +:20DA4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6 +:20DA6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6 +:20DA8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6 +:20DAA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF86 +:20DAC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66 +:20DAE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF46 +:20DB00008D0327FC39B6A00085012706B6A001847F394F398D243402810D270BB7A0010CEA +:20DB2000799679917825100F798D0F860DB7A0018D08860AB7A0013502393402B6A0008512 +:20DB40000227F935023910CE01EE966E8155260A9E6FA684811226026E848E02186F8330AE +:20DB60000126FA8E02176F809F19A60243A702A10226063001630120F19F719F279F233065 +:20DB800089FF389F211F148EDBCECE0076C612BDDCAECE00A7C604BDDCAE863997F0BDDFD0 +:20DBA000BA8E00B59F8DCEE6CEC60AEF815A26FB8695B7A0008EDC03BDEBE58EDBC69F6F56 +:20DBC0008655976E200412BDDFD47EDF223B10405000E6CE0C8426020C83B600007EDCBF9B +:20DBE0007EDCBE7EDBCD7EE6CE804FC7525932DD1DDE2A1DDDBDDCCE0000000000000000DF +:20DC0000000000003638303920455854454E4445442042415349430D2843292031393832A5 +:20DC2000204259204D4943524F534F46540D0D0034169E76DC789F6AD76C976D35960F73EA +:20DC40008E00F4C601BDDB00810826075A27EF301F20348115260A5A27E48608BDDB142095 +:20DC6000F681031A012705810D260D4F3401BDEBA56F848E00F33581812025C9817B24C5B3 +:20DC8000C1FA24C1A7805CBDDB1420B92705BDE9C19F7A6E9F007A7EE0A396732603BDDBDE +:20DCA000050F73975310260C6A97567EE91FA680A7C05A26F939399D8227FB7EE5003B81FC +:20DCC0003A240A812026020E7C803080D039EEC3EF37EEDC00ADF168F1BDE9D4E905E781E8 +:20DCE000E99AE924E910F26DF235F23EF3AFF3E1F303F569F33DFA3BE92FE94CE953DC9AB7 +:20DD0000E772F571F631F60179EC0E79EC057BED157BEDDA7FF34650E55946E558464FD25A +:20DD200047CF5245CDA7454C53C549C6444154C15052494ED44FCE494E5055D4454EC44E91 +:20DD40004558D44449CD524541C45255CE524553544F52C55245545552CE53544FD0504F7E +:20DD60004BC5434F4ED44C4953D4434C4541D24E45D7455845C354524FCE54524F46C64425 +:20DD800045CC4445C64C494EC552454E55CD454449D4544142A854CF5355C2544845CE4EC5 +:20DDA0004FD4535445D04F46C6ABADAAAFDE414EC44FD2BEBDBC46CE5553494EC75347CE6D +:20DDC000494ED44142D35553D2524EC45349CE504545CB4C45CE535452A45641CC4153C3DF +:20DDE000434852A44154CE434FD35441CE4558D04649D84C4FC7504FD35351D2484558A4D0 +:20DE00004C454654A45249474854A44D4944A4494E4B4559A44D45CD5641525054D2494E1A +:20DE20005354D2535452494E47A4DFE8E133E190E190E190E1C1E18DEB6AE1EFE29CE0BA73 +:20DE4000E381E5D2E2D6E128E09CE16DE0BEE9DBE0E3E9E2E0F4DFB8DC8CF564F565F7E0CF +:20DE6000F724FECEF86AF3F04E46534E52474F4446434F564F4D554C425344442F304944A1 +:20DE8000544D4F534C535354434E4644414F444E494F464D4E4F4945445355464E4520453C +:20DEA00052524F520020494E20000D4F4B0D000D425245414B003064C6129F0FA6848080DC +:20DEC0002615AE019F119E3B27099C1127099E0F3A20E59E119F3B9E0F4D398D17DE413324 +:20DEE000419E433001A68236029C4726F8DF45394F58D31FC3003A250810DF171093172569 +:20DF0000EEC60CBDDFD4BDEBA9BDEBF88EDE683A8D318D2F8EDE9DBDEBE596684C2703BD91 +:20DF2000F00EBDEBA98EDEAABDEBE5BDDC3ECEFFFFDF6825F69F839D7C27F0250BBDEA972A +:20DF40007EE071A6807EEBFABDE2149E2B9FF1BDEA97D7038D4C2512DC47A384D31BDD1B05 +:20DF6000EE843702A7809C1B26F896F3271CDC1BDD43DB038900DD41BDDEDBCE00EF370226 +:20DF8000A7809C4526F89E419F1B8D368D02209B9E19EC8427213304A6C026FCEF84AE84E2 +:20DFA00020F0DC2B9E19EE84270910A3022306AE8420F31A019F473926FB9E196F806F80DE +:20DFC0009F1B9E19BDE1689E279F23BDE09C9E1B9F1D9F1F8E00C99F0BAEE410DE216FE2E4 +:20DFE0000F2D0F2E0F086E8486809708BDE236BDDEB6326226049E0F3285C609BDDEF0BD9B +:20E00000E195DC683416C6A0BDE4F8BDE3CCBDE3CAD654CA7FD450D750108EE0207EE473F6 +:20E020008EED0EBDEE5D9D8281A426059D7CBDE3CABDEEB6BDE46FDC3B3406868034021C43 +:20E04000AF8D609E839F2FA6802707813A27227EE500A68197002772EC80DD689F83968C2E +:20E06000270F865BBDDB149668BDF015865DBDDB149D7C8D0220C827294D102A01B881FFEE +:20E08000270F819E22C9BEDBF1481F893A9D7C6E949D7C8197102714F07EE5009E19301F9C +:20E0A0009F3339BDDB05270A8103271281132703977339BDDB0527FB20EE9D8220021A01A0 +:20E0C00026319E839F2F060032629E688CFFFF27069F299E2F9F2D8EDEAE0D00102AFE42A1 +:20E0E0007EDF17260EC6209E2D1027FE169F839E299F6839272CBDE66A34069E279D8227AE +:20E100000CBDE4F6BDE9C1301F9C7122181F10A3E125121F0383003A250B931B2507DF218C +:20E120009F277EDFC77EDF019D821027FE94BDDFC720191F899D7CC1A02716C1A12645C621 +:20E1400003BDDEF0DE839E6886A134528D037EE03F9D82BDE2148D403001DC2B10936822EC +:20E16000029E19BDDFA62517301F9F833926FD86FF973BBDDEB61F148121270BC6048CC6D0 +:20E180000E7EDF037EE50035529F68DF838D068C8D069F8339C63A865FD7015F9E831F98BD +:20E1A000D6019701A68427EC3404A1E027E63001812227EA4C26023001818626E70C04201F +:20E1C000E3BDE3CA9D8281812705C6A2BDE4F8964F26130F048DB64D27BA9D7C818426F5C9 +:20E1E0000A042AF19D7C9D821025FF657EE077BDE98FC681BDE4F8340281A1270481A02671 +:20E20000830A53260535047EE1359D7C8D06812C27EF35849E749F2B246180309701DC2B4E +:20E22000811822DB58495849D32B5849DB018900DD2B9D7C20E2BDE5DB9F3BC6AEBDE4F87B +:20E2400096063402BDE3DF350246BDE3D110270C2B9E52DC2110A30224119C1B250DE684E7 +:20E26000BDE7919E4DBDE8C78E00569F4DBDE8F9DE4D9E3B3726A78410AF02393F52454404 +:20E280004F0D007EDF03960927079E319F687EE5008EE27BBDEBE59E2F9F8339C6169E683A +:20E2A000300127DF8D01398122260BBDE4CDC63BBDE4F8BDEBE88E00F36F848D06C62CE714 +:20E2C000842016BDEBF8BDEBF5BDDC3E240532647EE0C6C62E399E33864F97099F35BDE5A4 +:20E2E000DB9F3B9E839F2B9E35A684260996092651BDEBF88DCD9F839D7CD60627239E83C0 +:20E3000097018122270E301F4F9701BDDC30863A9701862C9702BDE7A2BDE4D2BDE2512022 +:20E3200006BDEF5BBDEE7C9D822706812C1026FF529E839F359E2B9F839D822721BDE4F64B +:20E34000209C9F83BDE19530014D260AC606EE812741EC81DD31A684818626E620989E3518 +:20E36000D6091026FD3AA68427068EE3707EEBE5393F45585452412049474E4F5245440D9A +:20E380000026049E742003BDE5DB9F3BBDDEB62704C60020471F143003BDEE5DA6689754B7 +:20E3A0009E3BBDEC0BBDEE7C3069BDEEDFE068270CAE6E9F68AEE8109F837EE03F32E81257 +:20E3C0009D82812C26F49D7C8DBD8D131CFE7D1A010D0625032A998C2B96C6187EDF038D8C +:20E3E0006E4F8C34043402C601BDDEF0BDE4AC0F3F9D8280AD25138103240F810149983F9C +:20E40000913F2564973F9D7C20E9D63F26331024006B8B07246799061027047789FF340272 +:20E4200048ABE08EDD0830863502A18424558D9C34028D299E3D3502261D4D1027006A2093 +:20E440004B0806598D098EE454D73F0F0620D99E837EE16864E578A184243120D3EC013453 +:20E46000068D08D63F16FF7B7EE500D654A68435203404D64F9E50DE5234546EA49E74A683 +:20E48000E0272681642703BDE3CC9F3D3504815A2719817D271554D70A3552975C9F5DDFE0 +:20E4A0005F3504D761D854D762D64F39BDF6F90F069D7C24037EEF5BBDE6262450812E27ED +:20E4C000F481A7274081A627E38122260A9E83BDE79C9E649F833981A3260D865ABDE3E33D +:20E4E000BDE67143537EE7784C272E8D06BDE3DFC6298CC6288CC62CE19F008326020E7C46 +:20E50000C6027EDF03867DBDE3E37EF132BDE5DB9F52960626957EEE5D9D7C1F89589D7CEC +:20E52000C13823037EE5003404C12A251EC130241C8DC0A6E4BDE3DF8DBCBDE3CF3502DE9F +:20E54000523442BDE98F350234068E8D9E3504BEDBF63AAD947EE3CC864F9703BDE671DDC4 +:20E5600001BDEE93BDE6710D0326069401D40220049A01DA027EE778BDE3D1261096618A01 +:20E580007F945D975D8E005CBDEEDF20360F060A3FBDE8DBD7569F589E5FBDE8DD965634AC +:20E5A00004A0E0270786012403D656409754DE585C5A2604D654200BA680A1C027F3C6FFD3 +:20E5C000240150CB0159D40A2702C6FF7EEEC5BDE4F6C6018D089D8226F5395F9D82D705E4 +:20E5E00097379D828D401025FF165FD7069D7C25048D33250A1F899D7C25FC8D2924F88175 +:20E600002426060306CB809D7CD7389A088028102700750F089E1BDC379C1D271210A3812F +:20E62000273E300520F381412504805B80A5398E0074EEE41183E5102728DC1FDD43C3007F +:20E6400007DD419E1D9F47BDDEDB9E419F1F9E459F1D9E47DC37ED814F5FED84ED02A70423 +:20E660009F393990800000009D7CBDE3CA96542B5DBDE3CC964F819025088EE663BDEEDF94 +:20E68000264CBDEF11DC5239DC053406125F9E3734148DD435349F37DE5234605C9D8281DB +:20E6A0002C27EBD703BDE4F03506DD059E1D9C1F2721DC3710A3842706EC02308B20EFC6E1 +:20E6C000129605260BD603E1042759C6108CC6087EDF03CC0005DD64DC37ED84D603E70434 +:20E6E000BDDEF09F41C60B4F0D0527053506C30001ED058D5DDD6430020A0326E89F0FD367 +:20E700000F1025F7FC1F01BDDEF4830035DD1F4F301FA7059C0F26F89E41961F9341ED02F5 +:20E720009605262DE604D7034F5FDD643506DD5210A305243ADE6427048D17D35230020A46 +:20E740000326E7EDE358495849E3E1308B30059F393986109745EC05DD174F5F5849250FF8 +:20E76000086509642404D31725050A4526EE397EE6CB1F40931F214F0F06DD50C6907EEE33 +:20E78000CBBDE3CCCE01F0BDF02532628E01EF200B9F4D8D5C9F58D75639301F86229701B3 +:20E7A000970230019F629F58C6FF5CA680270C91012704910226F381222702301F9F64D7BF +:20E7C00056DE62118301F022078DC69E62BDE8C99E0B8C00F12605C61E7EDF039656A7000C +:20E7E000DC58ED0286FF97069F0D9F5230059F0B390F074F3406DC23A3E0109321250ADD2E +:20E80000239E2330019F253584C61A030727CA8D04350420DE9E279F234F5FDD4B9E219F08 +:20E82000478E00C99C0B27048D3220F89E1B9C1D27048D2220F89F419E419C1F2735EC0269 +:20E84000D341DD41A6012AF0E60458CB053A9C4127E88D0820F8A60130022A14E684271028 +:20E86000EC02109323220910934723049F4BDD473005399E4B27FB4FE6845AD347DD439E36 +:20E88000239F41BDDEDD9E4BDC45ED029E45301F7EE817DC523406BDE4ACBDE3CF35109F4D +:20E8A00062E6849E52EB842405C61C7EDF03BDE7919E62E6848D109E4D8D228D0C9E628DC6 +:20E8C0001CBDE7D07EE3F1AE02DE255C2004A680A7C05A26F9DF2539BDE3CF9E52E6848D8A +:20E8E000182613AE07301F9C2326083404D323DD233504300139AE02399C0D26079F0B306C +:20E900001B9F0D4F398D037EE7778DCC0F065D39BDE992C601BDE7F19653BDE795A7843225 +:20E92000627EE7D08D0220DF8DE0275EE684398D484FE1842303E6844F3406BDE7939E4D59 +:20E940008D9B35043A3504BDE8C920D58D2BA0844020DFC6FFD7539D8281292705BDE4F6EA +:20E960008D2D8D1527245F4AA18424CD1F89E08450D15323C4D65320C0BDE4F0EEE4AE654B +:20E980009F4DA664E66432671F357EE6CE9D7CBDE3CABDE66D4D26F20E82BDE90A102702A7 +:20E9A000E1DE839F833AA68434526F849D82BDEF5B3552A784DF83398D079F2BBDE4F6208E +:20E9C000CEBDE3CA96542BC2964F819022BCBDEF119E52398DEEE6847EE7778DDB9E2BE795 +:20E9E00084393401BDE214BDDFA29F66350127129D82271381A726099D7C2706BDE21427F0 +:20EA00000639CEFFFFDF2B32629E66BDEBA9BDDC97EC8426037EDF229F66EC0210932B22CD +:20EA2000F4BDF015BDEBF59E668D10AE9F0066CE00F4A6C027D5BDEBFA20F73004108E0080 +:20EA4000F4A68027512B15813A260DE684C18427F0C18327EC8C86218D3020E5CEDBE481D6 +:20EA6000FF2604A6803345847F334A6DC427E7A0C42AF6ABC4EE414A2B066DC02AFC20F709 +:20EA8000A6C48D066DC02AF820B7108C01ED2406847FA7A06FA4399E83CE00F30F430F4482 +:20EAA000A68027210D43270FBDE626241881302504813923100F438120270A9742812227CF +:20EAC000380D442719A7C02706813A27CF20D16FC06FC01F308300F18E00F29F8339813F7B +:20EAE0002604868720DF81272613CC3A83EDC10F42A68027D0914227CCA7C020F481302543 +:20EB000004813C25C0301F34500F41CEDBE40F42334AA6C4273110AE41AEE4E6A0E0802771 +:20EB2000FAC180263832623540DA4296412606C1842606863AEDC12094E7C0C18626020C5F +:20EB400044C18227AA2086CEDBE9034126C03550A680A7C0BDE62625EC034320E80C424A29 +:20EB600027AE313FE6A02AFC20AF27398D0139BDFACF273E819F2753812C2737813B2760DB +:20EB8000BDE3DF960634022606BDF022BDE79A8D573504BDDC305D26089D82812C27148DE6 +:20EBA000549D8226CF860D2051BDDC3027F7966C26F339BDDC30270AD66CD16B25068DE599 +:20EBC000201ED66CD06A24FC502010BDE98D81291026F92CBDDC30D06C23058D185A26FB56 +:20EBE0009D7C7EEB72BDE79CBDE8DB5C5A27C3A6808D0720F786208C863F7EDB148EF10904 +:20EC00002009BDED78035403622003BDED785D102702808E005C1F895D276CD04F2769253C +:20EC20000A974F966197548E004F50C1F82F594F6401BDED03D6622A0B6301630263036334 +:20EC40000443890097639653996097539652995F97529651995E97519650995D97505D2A45 +:20EC60004425028D5D5F9650262E965197509652975196539752966397530F63CB08C12825 +:20EC80002DE44F974F9754398D6D5F20A85C086309530952095109502AF3964F3404A0E0FE +:20ECA000974F23DE8C2508086386009763200C0C4F2728065006510652065324048D0D27AC +:20ECC000EE39035403500351035203539E5230019F5226069E5030019F5039C60A7EDF03AF +:20ECE0008E0012A6049763A603A704A602A703A601A702965BA701CB082FE89663C008276F +:20ED00000C6701660266036604465C26F43981000000008D6327608D7886009713971497E0 +:20ED2000159716D6538D22D663D78BD6528D1AD663D78AD6518D12D663D789D6508D0CD641 +:20ED400063D788BDEE547EEC652795439613562726241696169B6097169615995F97159665 +:20ED600014995E97149613995D46971306140615061606634F20D539EC0197618A80DD5DEE +:20ED8000D661D854D762EC03DD5FA684975CD64F394D27169B4F464928108B80974F270CD2 +:20EDA000966297543996544320023262102AFED27EECDBBDEEA8270D8B0225F40F62BDECBE +:20EDC000160C4F27EB398420000000BDEEA88EEDC65FD762BDEE5D8C8D9E2773004F8DB1C1 +:20EDE0000C4F27CC8E0013C604D703C6019650915D26139651915E260D9652915F26079608 +:20EE00005391602601431FA859240AE7800A032B34272EC6011F8A250E0860095F095E09EB +:20EE20005D25E32BC820DF966090539760965F9252975F965E9251975E965D9250975D2027 +:20EE4000D8C64020D0565656D7638D087EEC65C6147EDF039E139F509E159F52393402EC6B +:20EE60000197548A80DD500F63E684AE039F52D74F35828E004520068E00408C9E3B964F03 +:20EE8000A78496548A7F9450A7019651A702DE52EF0339966197549E5C9F4F0F63965E9716 +:20EEA0005196549E5F9F5239DC4FDD5C9E519F5E9E539F604D39D64F2708D65459C6FF2569 +:20EEC0000150398DF1D7500F51C68896508080D74FDC74DD52976397547EEC610F5439E698 +:20EEE0008427D3E601D8542BD1D64FE184261DE601CA7FD450E1012613D651E102260DD636 +:20EF000052E1032607D653E00426013956D85420ABD64F273DC0A096542A05035BBDECC407 +:20EF20008E004FC1F82E06BDECF70F5B390F5B96544906507EED03D64FC1A0241D8DD2D766 +:20EF4000639654D754808086A0974F965397017EEC61D750D751D752D753399E749F549F62 +:20EF60004F9F519F529F479F452564BDF698812D260403552004812B26049D7C2551812E5B +:20EF80002728814526289D7C256481A7270E812D270A81A62708812B2704200603489D7C79 +:20EFA000254C0D48270800472004034626CC96479045974727122A09BDEDCB0C4726F920B3 +:20EFC00007BDEDB30A4726F996552A8E7EF132D645D046D7453402BDEDB33504C0308D0281 +:20EFE0002098BDEE78BDEEC58E00407EEC0BD6475858DB475880303404ABE09747209F9B91 +:20F000003EBC1FFD9E6E6B27FD9E6E6B28008EDEA48D0CDC68DD50C69043BDEECF8D037E65 +:20F02000EBE5CE01F18620D6542A02862DA7C0DF6497548630D64F102700C64FC18022086A +:20F040008EF009BDED1386F797458EF004BDEEE92E0F8EEFFFBDEEE92E0EBDEDB30A4520A8 +:20F06000F1BDEDCB0C4520E2BDEBFDBDEF11C60196458B0A2B09810B24054A1F8986024A91 +:20F080004A9747D7452E0DDE64862EA7C05D27048630A7C08EF10EC6809653AB0397539605 +:20F0A00052A90297529651A90197519650A98497505C565928E32403C00B50CB2F30041F52 +:20F0C00098847FA7C00A452604862EA7C053C4808CF13226C4A6C2813027FA812E26023326 +:20F0E0005F862BD647271C2A03862D50A7428645A741862F4CC00A24FBCB3AED436F4520E1 +:20F1000004A7C46F418E01F1398000000000FA0A1F0000989680FFF0BDC0000186A0FFFF35 +:20F12000D8F0000003E8FFFFFF9C0000000AFFFFFFFF964F27020354399F64BDEE788D0527 +:20F140008D088E00407EED139F64BDEE739E64E680D7559F648DEE9E6430059F64BDEC0BAD +:20F160008E00450A5526EE39BDEEB62B1F27158D10BDEE788D0E8E00408DCA8EED0EBDEC77 +:20F180000B7EEF379EB19F509EB39F52BEF1B99F5DBEF1BB9F5FBDED19DC8AC3658BDDB308 +:20F1A000DD52DC88C9B08905DDB1DD500F548680974F961597637EEC6540E64DABBDEEA8C6 +:20F1C0008EF202D661BDEDD2BDEEA88DB40F62965CD64FBDEC058EF207BDEC0296543402DE +:20F1E0002A09BDEBFD96542B05030ABDF1328EF207BDEC0B35024D2A03BDF1328EF20C7E5A +:20F20000F13983490FDAA27F000000000584E61A2D1B862807FBF88799688901872335DFA5 +:20F22000E186A55DE72883490FDAA2A154468F138F524389CD8EF268BDEC0B7EF1BDBDEE35 +:20F24000780F0A8DF68E004ABDEE7E8E0040BDEE5D0F54960A8D0C0D4F1027FA7E8E004A44 +:20F260007EEDD834027EF1EB81490FDAA2965434022A028D24964F3402818125058EED0E99 +:20F280008DDE8EF29DBDF1393502818125068EF268BDEC0235024D2A037EF132390B76B349 +:20F2A00083BDD3791EF4A6F57B83FCB0107C0C1F67CA7CDE53CBC17D1464704C7DB7EA512A +:20F2C0007A7D6330887E7E9244993A7E4CCC91C77FAAAAAA138100000000037F5E56CB79FE +:20F2E00080139B0B6480763893168238AA3B20803504F334813504F3348080000000803169 +:20F300007217F8BDEEB6102FF3C48EF2EF964F808034028680974FBDEC0B8EF2F4BDEDD8F5 +:20F320008EED0EBDEC028EF2DABDF1398EF2F9BDEC0B3504BDEFE28EF2FE7EED13BDEEA815 +:20F340008EF109BDEE5D27674D26037EEC838E004ABDEE7E5F96612A10BDEF378E004A964A +:20F3600061BDEEE9260343D601BDEE953404BDF3038E004ABDED138D363502461025FDB271 +:20F38000398138AA3B29077134583E5674167EB31B772FEEE3857A1D841C2A7C6359580A08 +:20F3A0007E75FDE7C6803172181081000000008EF381BDED13BDEE78964F818825037EED81 +:20F3C000A5BDEF3796018B8127F44A34028E0040BDEC028EF386BDF1480F623502BDED910E +:20F3E00039BDEEB62B037EEF3703548DF97EF132BDF81E326286019798BDDFA21025ED7F27 +:20F40000BDEA3B1F208300F5D797DC2BBDF015BDEBF58E00F4D69826255FBDF544BDFCE94D +:20F42000250B80303402860A3DEBE020EDC001C90181412605BDEBA520BB814C260B8D31B5 +:20F440000F98BDEBA520C33262810D260D8D22BDEBA58E00F49F837EDF4B814527F1815188 +:20F460002606BDEBA57EDF228D0220AD812026108CC6F9A6842708BDDB1430015A26F43933 +:20F48000814426486D8427F78D045A26F7390A97311F3121A621A7A426F8398149271381B8 +:20F4A00058270D8148265C6F841F108300F5D7978DBFBDF544810D278E811B272581082651 +:20F4C000228C00F427EC8D458DC420E6814326CB6D84270EBDF544250220F5A7808D375AFC +:20F4E00026EE39D697C1F9260220C734106D8026FCE682E701ACE426F83262A7808D170CCD +:20F500009720AF810826128D045A26FB398C00F427D0301F86087EDB14814B2705805327CC +:20F52000013934028D1E3402A68427166D6126068DE430012003BDF48EA684A1E426E95AFD +:20F5400026E635A0BDDB00817F24F9815F2602861B810D270E811B270A8108270681202560 +:20F56000E31A0139864F978C398600D6791D7EE778BDE4F3DC1F3406BDE5DBBDE4F0350642 +:20F580001E109C1F26517EE7789D7CBDE4F3BDE5DB3410EC02109321230493272312E6848E +:20F5A000BDE7F13410AE62BDE8C73550AF423440BDE9BC34045D271FC6FF81292703BDE990 +:20F5C000BC3404BDE4F0C6AEBDE4F88D2E1F13AE62A684A06124037EE6CE4CA1E42402A77A +:20F5E000E4A6611E89AE025A3A4D270DA1E42302A6E41F891E31BDDCAE3596BDE3DF7EE892 +:20F60000D8BDE4F3BDE98F3404BDE4F6BDE3DFBDE4F096062605BDE9922003BDE928340442 +:20F62000E661BDE79335062705A7805A26FB7EE91FBDE4F3BDE3DFC601340496062610BD1C +:20F64000E992E7E42791BDE4F6BDE3DFBDE3CF9E523410BDE4F6BDF5FB3414BDE4F0AE63C5 +:20F66000BDE8DD3404E1662523A661271CE6665A3A3184EE62E661A6E4A0664CA161250CBC +:20F68000A680A1C0260C5A26F7E666215F32677EE7776C66302120D98126265C32620F52BF +:20F6A0000F538E00529D7C814F2712814827239D82200C81381022EE47C6038D2A9D7C25AA +:20F6C000F20F500F510F060F630F54C6A0D74F7EEC659D7C250BBDE62625E6814724E280C9 +:20F6E00007C6048D0220EB680169841025F5EC5A26F58030AB01A7013935400F069E839D39 +:20F700007C8126279981B0275E81FF26089D7C8183102700AB9F836EC49E68300126D9C653 +:20F72000167EDF03AE9F00838CFF83102700748D238DE6BDE4F3C680D708BDE5DB8D25BD02 +:20F74000E4F0C6AEBDE4F89E4BDC83ED84DC39ED027EE18DC6B0BDE4F8C680D7088A80BD24 +:20F76000E5E09F4B7EE3CC8DEB3410BDE4EB8DF43540C632AE4227A9109E83EEC4DF83A6CC +:20F78000043402EC84EE023476BDEE7EBDE3CA3576ED84EF023502A7049D821026ED6110F0 +:20F7A0009F83399D7C8D0934108D2D3540AFC4395F9D7C240680301F899D7C9E8D583A3917 +:20F7C0008DEEAE843410BDE4EB8E004F96062707BDE8DB9E52960639C6AEBDE4F87EE9C18B +:20F7E0001027EEEABDE214BDDFA29F939D82271081A7263B9D7C27048D24200486FF972B98 +:20F80000DE938CEEC4ECC42706EC42932B23F49E938D15BDDFC29E93BDDF927EDF22BDE2AB +:20F82000147EDCB7A6C0A78011931B26F79F1B39BDF7199D7C8122260BBDE4CDC63BBDE47D +:20F84000F8BDEBE8327EBDE2C93262BDE5DB9F3BBDE3CF8E00F34FBDE7A07EE251BDE21436 +:20F860009E2B399E919F2B7EDFA2BDDFC7CC000ADD95DD8F5FDD919D8224068DE09F959D23 +:20F8800082271BBDE4F624068DD39F919D82270EBDE4F624068DC69F8F2749BDDCB78DC3AD +:20F8A0009F939E958DBF9C93253A8D1CBDF93EBDDF908DAF9F938D3A8D0F8D36BDF9D9BD60 +:20F8C000DFC7BDDF907EDF22864F97989E93DC958D150D982602ED02AE848D0BD38F25047E +:20F8E00081FA25EE7EE6CE3406EC84350626023262399E19301F30018DED30033001A6842F +:20F9000027F49F0F4A270C4A272A4A26EF8603A78020E7EC016A0227014FE6036A042701A1 +:20F920005FED01DD2BBDDFA29E0F25E1DC476C80ED8420C66F84AE01AE029F4720EA9E1922 +:20F9400020049E8330018D9F300230019F839D7C4D27EF2AF99E8381FF27EF81A22712814D +:20F9600084270E818126E79D7C81A0270481A126DB9D7C25049D8220D79E833410BDE214C7 +:20F980009E83A682BDFCE925F930011F10E061C0052720250A3384503085BDF82820149F16 +:20F9A000479E1B9F435030859F419F1BBDDEDB9E459F8335108601A784A702A704D62B26D9 +:20F9C00004C6016C02E701D62C2604C6016C04E7039D82812C279A209C9E19301F3001EC4D +:20F9E00002DD68BDF8E730033001A68427EF4A271B800226F334108EFA36BDEBE5AEE4EC4C +:20FA000001BDF015BDF00EBDEBA535103410EC01DD52BDF6C1BDF0223540C6053001A68498 +:20FA200027055AA7C020F530C45D27BE31C433C5BDF82830A420B3554C2000BDE9C48E0163 +:20FA4000F0C60434045F860408530952594A26F85D260AA6E44A27058C01F0270CCB30C15B +:20FA6000392302CB07E7806F8435045A26D532628E01EF7EE79C860197995ABDFC179D825B +:20FA800010270093D793BDE3DFBDE3CF9E529F4DD699BDE931BDEBE89E52D699E0845A1065 +:20FAA0002B014FBDEBF520F6D7939F0F86029799A684812527C4812026070C9930015A2669 +:20FAC000EF9E0FD6938625BDFC17BDDB14202981B12701393262BDE3E1BDE3CFC63BBDE4F8 +:20FAE000F89E529F952006969727089E950F97E68426037EE6CEAE020F9A0F99A680812101 +:20FB00001027FF728123275B5A2616BDFC17BDDB149D8226D296972603BDEBA59E957EE8B2 +:20FB2000DD812B2609BDFC178608979A20CC812E274E81251027FF70A184268B8124271967 +:20FB4000812A26F6969A8A20979AC1022511A6018124260B5A30010C99969A8A10979A3002 +:20FB6000010C990F980C995A2749A680812E271E812327F1812C2621969A8A40979A20E5CF +:20FB8000A68481231026FF3F8601979830010C985A2720A680812327F5815E2616A18426AB +:20FBA00012A101260EA102260AC1042506C00430040C9A301F0C99969A850826180A995D0D +:20FBC0002713A684802D270681FE260986088A049A9A979A5A9D821027FF3CD793BDE3CAF9 +:20FBE00096999B9881111022EAE4BDFC24301FBDEBE50F979D82270D9797813B2705BDE4A8 +:20FC0000F620029D7C9E95E684D093AE023AD6931026FEE47EFB113402862B0D9A2703BD49 +:20FC2000DB143582CE01F2C620969A85082702C62B0D542A040F54C62DE7C0C630E7C084F3 +:20FC400001102601078EF009BDEEE92B15BDF022A68026FCA682A7018C01F126F78625A736 +:20FC60008439964F97472703BDFE0C9647102B0081409B998009BDFD29BDFEA2BDFE4196AB +:20FC800047BDFEC09647BDFE8896982602335F4ABDFD29BDFDC44D2706C12A2702E7C06F4B +:20FCA000C48E01F130019F0F963A901090992738A684812027EE812A27EA4F3402A6808161 +:20FCC0002D27F8812B27F4910027F08130260EA6018D1625083502A78226FA20C735024D22 +:20FCE00026FB9E0F8625A7823981302504803A80C639969827014A9B472B014F34022A0AAF +:20FD00003402BDEDCB35024C20F49647A0E097478B092B199699800990478D0DBDFEA220E8 +:20FD20001D34028630A7C035024A2AF53996998DF8BDFE8C86F790478DEF0F450F97BDFEFA +:20FD40004196982602DE399B4716FF43964F34022703BDFE0C969827014A9B997F01F1D694 +:20FD60009AC40426037301F1BB01F1800934022A0A3402BDEDCB35024C20F4A6E42B014FAC +:20FD8000409B994CBB01F197450F97BDFE413502BDFEC096982602335FE6E02709D647CB00 +:20FDA00009D099F001F1862B5D2A03862D50A7418645A7C1862F4CC00A24FBCB3AEDC16F8A +:20FDC000C47EFC938E01F2E68434048620D69AC52035042708862AC12026021F893404A78C +:20FDE00080E6842710C145270CC13027F2C12C27EEC12E26048630A782969A85102704C6EF +:20FE000024E782840435042602E7823934404F9747D64FC18022118EF009BDED13964780EF +:20FE20000920ECBDEDCB0C478EF004BDEEE92EF38EEFFFBDEEE92E07BDEDB30A4720F13575 +:20FE4000C03440BDEBFDBDEF1135408EF10EC6808D369653AB0397539652A902975296511D +:20FE6000A90197519650A98497505C565928E32403C00B50CB2F30041F98847FA7C053C438 +:20FE8000808CF13226CA6FC40A452609DF39862EA7C00F97390A97260886039797862CA7A1 +:20FEA000C03996478B0A97454C800324FC8B059797969A8440260297973934028DCA350207 +:20FEC0004A2B0A34028630A7C0A6E026ED3981891027F95C7EE500FFFFFFFFFFFFFFFFFF8E +:20FEE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF22 +:20FF0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF01 +:20FF2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE1 +:20FF4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC1 +:20FF6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA1 +:20FF8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF81 +:20FFA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF61 +:20FFC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF41 +:20FFE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000009B009E00AA00A700A100A4DB4621 +:00000001FF diff --git a/MC6809/MC6809.Test/roms/searle/ExBasRom.zip b/MC6809/MC6809.Test/roms/searle/ExBasRom.zip new file mode 100644 index 0000000000000000000000000000000000000000..4e0a1d1c5579cb15e04a5e932cc111532df4fea2 GIT binary patch literal 180465 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%0A=fd375 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%0ADU7~rlxnRiKej4R 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 literal 0 HcmV?d00001