├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── cusp-updates └── fit │ ├── fit.diff │ ├── fit.tsk │ └── fitbld.com ├── decnete ├── nsp1.pat └── nsp1.txt ├── docs ├── AA-5286M-TC-RT-11-V5.7_System_Release_Notes_Oct1998.pdf ├── AV-RK36A-TE-RSTS_E-V10.1A_Cover_Letter_Year_2000_Update_1999.pdf └── SPD-13_01_37-RSTS_E-Version_10.1.pdf ├── layered └── dibol │ └── dibol.txt ├── micros ├── DISASB.COM ├── DISASM.B2S ├── DISASM.TSK ├── INTEL.B2S ├── INTEL.TSK ├── INTELB.COM ├── SCMBLD.COM ├── SCMPCA.B2S ├── SCMPCA.TSK ├── X65.B2S ├── X65.TSK ├── X65BLD.COM ├── X80.B2S ├── X80.HLP ├── X80.TSK └── X80BLD.COM ├── photos └── DECtape-RSTS-E-V06B.jpeg └── software ├── ahl_basic_games.dta ├── rk05-games-rsts0-0.dsk ├── rl01-games-rsts0-0.dsk ├── rl01-games.dsk ├── rl02-ker363.dsk └── rl02-zemu25.dsk /.gitattributes: -------------------------------------------------------------------------------- 1 | # Default is to keep crlf line endings 2 | text=auto 3 | 4 | LICENSE text eol=crlf 5 | README.md text eol=crlf 6 | *.diff text eof=crlf 7 | *.doc text eof=crlf 8 | *.ini text eof=crlf 9 | *.pat text eof=crlf linguist-language=DIGITAL Command Language 10 | *.txt text eof=crlf 11 | *.tsk binary 12 | *.TSK binary 13 | *.jpeg binary 14 | *.txt text eof=crlf 15 | *.mac text eol=crlf linguist-language=Assembly 16 | *.com text eol=crlf 17 | *.COM text eol=crlf 18 | *.HLP text eol=crlf 19 | *.B2S text eol=crlf linguist-language=BASIC 20 | *.obj binary 21 | *.zip binary 22 | *.bz2 binary 23 | *.pdf binary 24 | *.dsk binary 25 | *.dta binary 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/.*.swp 2 | **/.DS_Store 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2020, Tony Nicholson 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RSTS-E 2 | ## Updates, Information and Software for the PDP-11 RSTS/E V10.1 Operating System 3 | 4 | In this repository I aim to collect various software updates, information 5 | and software for the RSTS/E Operating System for the PDP-11. 6 | 7 | Most of these are for RSTS/E V10.1 which I run under emulation 8 | using SIMH PDP11 on my PiDP11 front panel. 9 | 10 | Recently some source-kits became available on the bitsavers web site 11 | for RSTS/E V10.1 and I started investigations into fixing some Y2K issues 12 | that I had found while tinkering. 13 | 14 | I've also zipped up a complete set of the RSTS/E V10.1 documentation. 15 | It's a very large file (1.68Gb) of PDF files and can be downloaded 16 | from my Google Drive at 17 | 18 | https://drive.google.com/file/d/1-cZsyJmAzsTWDDu5iPlD_o9_rYwahaGs/view?usp=sharing 19 | 20 | 21 | ## FIT 22 | 23 | The first of these concerned transferring files from an RT-11 disk 24 | image onto RSTS/E where the file dates should have been preserved by 25 | the FIT program. They were instead wrapping to an earlier date. 26 | 27 | Part of the RT-11 Y2K updates to RT-11 V5.7 included 28 | using additional bits in the RT-11 date word to store dates beyond 29 | 2003. I've included the SPD 30 | [here](https://github.com/agn453/RSTS-E/blob/master/docs/AA-5286M-TC-RT-11-V5.7_System_Release_Notes_Oct1998.pdf) 31 | for reference (see Appendix E). 32 | 33 | I've patched the source-code for FIT to fix this. 34 | 35 | You'll find a context diff for the source-code changes in the 36 | [cusp-updates/fit](https://github.com/agn453/RSTS-E/blob/master/cusp-updates/fit) 37 | subdirectory, along with the command file I used to build 38 | [this](https://github.com/agn453/RSTS-E/blob/master/cusp-updates/fit/fit.tsk) 39 | updated task image for RSTS/E V10.1. Just rename the original one in 40 | the AUXLIB$ (or SY:[0,14]) directory and copy the update (with <232> 41 | mode protection and RSX run-time system) in place. 42 | 43 | 44 | ## Paul Koning's DECnet/E Updates 45 | 46 | Paul Koning has some additional updates for DECnet/E for the 47 | Event Logger (EVTLOG.TSK) and for Async DDCMP support over a serial 48 | line. 49 | 50 | [Update 25-Aug-2020] There's also a replacement NCP program to fix 51 | the "SHOW NODE" command. 52 | 53 | [Update 11-Nov-2021] The DECnet/E event logger (EVTLOG.TSK) has been 54 | updated again. "There were two errors triggered by the fact that, as 55 | of 10-Nov-2021 the Julian-half-day value has the top bit set, making it 56 | look negative to PDP-11s. One was in the conversion from RSTS internal 57 | format to Julian-half-day, triggering an ```%integer error``` message. 58 | The other was in decoding such Julian-half-day values when displaying 59 | events -- doing an ASR to convert half days to whole days is not a 60 | good idea..." 61 | 62 | [Update 05-Jan-2022] A shutdown patch has been added to Paul Koning's 63 | repository in patches/shut.cmd. This resolves a problem in RSTS V10.1 64 | that seems to come and go with no clear pattern. The failure is a crash, 65 | sometimes a halt, during system shutdown. The cause was a write to the 66 | wrong location when removing the DCL runtime system, because of a 67 | register not being set before that action. 68 | 69 | This shutdown patch can be installed with ONLPAT; it takes effect 70 | immediately (because it patches a non-resident overlay). 71 | 72 | You'll find Paul's patches on his GitHub repository at 73 | 74 | https://github.com/pkoning2/decstuff 75 | 76 | In addition, I have included one of his patches to improve Ethernet 77 | throughput with RSTS/E V10.1 under SIMH PDP11 emulation. 78 | 79 | You'll find this in the decnete subdirectory and a patch script 80 | [nsp1.pat](https://github.com/agn453/RSTS-E/blob/master/decnete/nsp1.pat) 81 | that you can apply with ONLPAT to the monitor SIL. The 82 | [nsp1.txt](https://github.com/agn453/RSTS-E/blob/master/decnete/nsp1.txt) 83 | file has the details. 84 | 85 | 86 | ## Installing DIBOL from the PATCH$ directory 87 | 88 | Not related to updates - but may be useful/informative and nostalgic! 89 | 90 | I posted to the USENET newsgroup alt.sys.pdp11 recently describing 91 | how to install PDP-11 DIBOL V6.1-F from the PATCH$ directory. A 92 | full install kit exists on the system if you include patches when 93 | installing RSTS/E V10.1 - and you don't need original media to get it 94 | working. The details are 95 | [here](https://github.com/agn453/RSTS-E/blob/master/layered/dibol/dibol.txt). 96 | 97 | 98 | ## On the look-out for other Y2K updates for RSTS/E 99 | 100 | I remember seeing a TK50 tape of further Y2K updates that was 101 | released by Mentec in around the 1999 timeframe. Sadly, I don't have a 102 | copy of this - but I have managed to track down the following 103 | [Cover Letter](https://github.com/agn453/RSTS-E/blob/master/docs/AV-RK36A-TE-RSTS_E-V10.1A_Cover_Letter_Year_2000_Update_1999.pdf) 104 | for this tape. If anyone has a tape-image copy of this please 105 | let me know. It has EDT updates as well as date changes to the 106 | RT11.RTS and system utilities PIP.SAV, LINK.SAV, LIBR.SAV and SYSMAC.SML 107 | 108 | 109 | ## Software 110 | 111 | I've previously posted to various mailing lists concerning some software 112 | that enhances your nostaligia for RSTS/E. I'm adding a few disk images and a 113 | DECtape image to the software folder for the following - 114 | 115 | ### PDP-11 Kermit (Kermit-11 T3.63 dated 3rd October 2006). 116 | 117 | This is on an RL02 disk image in RSTS Level 1.2 format (label 118 | KER363) that I used to re-create various versions of Kermit-11 (for 119 | RSTS/E, RSX-11M-Plus, P/OS and RT-11). 120 | Updates were downloaded from Johnny Billquist's HECnet node MIM:: and 121 | applied to the most recent official kermit sources. 122 | You'll find the source files, batch build command files 123 | and binaries in the account [11,6] 124 | 125 | ``` 126 | $ mount dl0: ker363 127 | $ dir dl0:[11,6] 128 | ``` 129 | 130 | A direct download link for the Kermit RL02 image is 131 | [rl02-ker363.dsk](https://github.com/agn453/RSTS-E/blob/master/software/rl02-ker363.dsk) 132 | 133 | ### Dave Ahl's 101 BASIC computer games. 134 | 135 | I've supplied two RL01 disk images, 136 | One in RSTS Level 1.2 format for RSTS/E V8.0 and later, and the other in the 137 | original RSTS Level 0.0 format for use under RSTS V04 to V07). The disk 138 | files have been updated so the games can be played on recent versions of 139 | BASIC-Plus. The files are in two accounts [100,100] and [100,101]. Also 140 | included on this disk is a copy of the original adventure game that 141 | was ported from a PDP-10 to run under PDP-11 Fortran by Kent Blackett and 142 | Bob Supnik. You'll find this in the account [100,102]. 143 | 144 | ``` 145 | $ mount dl0: games 146 | ``` 147 | 148 | Also I've included a DECtape image (in 149 | DOS-11 format). This is directly readable by a RSTS system that includes 150 | DECtape (DT device) device support. 151 | 152 | The RL01 GAMES disk image is 153 | [rl01-games.dsk](https://github.com/agn453/RSTS-E/blob/master/software/rl01-games.dsk) 154 | and the image for older versions of RSTS V04A to V07 is 155 | [rl01-games-rsts0-0.dsk](https://github.com/agn453/RSTS-E/blob/master/software/rl01-games-rsts0-0.dsk) (an RL01) or 156 | [rk05-games-rsts0-0.dsk](https://github.com/agn453/RSTS-E/blob/master/software/rk05-games-rsts0-0.dsk) (an RK05). 157 | An image of an original DECtape containing volume 1 of the games is 158 | [ahl_basic_games.dta](https://github.com/agn453/RSTS-E/blob/master/software/ahl_basic_games.dta). 159 | 160 | ### ZEMU - the Infocom Z-machine interpreter 161 | 162 | This is my V2.5 (originally written by Johnny Billquist 163 | and Megan Gentry). This version includes the capability to run various 164 | Infocom interactive adventure games (like ZORK1, ZORK2, ZORK3...) under RSTS/E 165 | using the RT11 run-time system. This disk is in RT-11 format and the files 166 | need to be copied using the FIT command into an empty account on the 167 | system disk. The ZEMU.DOC file describes how to install this software. 168 | 169 | ``` 170 | $ create/account sy:[11,10]/name="ZEMU 2.5" 171 | $ fit sy:[11,10]=dl0:*.*/rt 172 | ``` 173 | 174 | The RL02 disk image (in RT-11 format) is 175 | [rl02-zemu25.dsk](https://github.com/agn453/RSTS-E/blob/master/software/rl02-zemu25.dsk) 176 | 177 | 178 | ## Forth RTS 179 | 180 | Some may not realise this - but a port of FIG-Forth V2 as a run-time system 181 | under RSTS/E is available if you choose to install the Unsupported software. 182 | The porting to RSTS/E was done by Paul Koning and was used as an internal 183 | RSTS/E development tool. It runs on any version of RSTS/E from V7.2 or 184 | later. 185 | 186 | The public domain sourcecode for the Forth RTS in Macro-11 is also 187 | included in the UNSUPP$:FORTH.MAC file. 188 | 189 | To enable the Forth RTS, add the following to your SY:[0,1]START.COM file 190 | under the section " Installing run-time systems and libraries" - 191 | 192 | ``` 193 | install/runtime_system UNSUPP$:FORTH 194 | ``` 195 | 196 | This will add it to the system when you reboot (or alternatively you 197 | can try it out using the following) 198 | 199 | ``` 200 | $ run $utlmgr 201 | Utlmgr> install/runtime_system UNSUPP$:FORTH 202 | Utlmgr> ^Z 203 | ``` 204 | 205 | Forth compiled programs have a .4TH file type or you 206 | can interactively enter them by switching to the newly installed RTS. 207 | By convention, Forth source files have the .FTH file type. 208 | 209 | For example - to multiply the integers 123 and 45 and print the result - 210 | 211 | ``` 212 | $ sw forth 213 | 214 | FIG-FORTH V2.0+ 215 | 123 45 * . 216 | 5535 ok 217 | ``` 218 | 219 | To exit back to DCL use 220 | 221 | ``` 222 | ccl switch dcl 223 | $ 224 | ``` 225 | 226 | Two Forth programs are included in the UNSUPP$: directory - ODT and 227 | SDA. ODT is the octal debugging tool and it handles large files; and 228 | SDA is an interactive crash dump analyser (inspired by the VMS tool 229 | of the same name). You can run like any other program - 230 | 231 | ``` 232 | $ run unsupp$:sda 233 | 234 | SDA V10.1-0G for RSTS/E V10.1-0L RSTS V10.1-L PDP11/70 SIMH 235 | 236 | Sil ? 237 | [Using DU0:[0,1]SIMH70.SIL] 238 | Crash dump file ? 239 | [Using DU0:[0,1]CRASH .SYS] 240 | 241 | [Help is available] 242 | 243 | Sda> help 244 | Type 'HELP ' to get help for 245 | Type 'HELP INTRODUCTION' for an introduction to SDA 246 | 247 | HELP is available for the following functions: 248 | TAG->A LB LX LS L DEFINE TAB E 249 | USE MODULE M->A %. A. AO. U.R U. 250 | EXIT FIND .CCLS .CCLDEF .FCBLIST .FILE 251 | .WCB .FCB B J->JCR NARROW 2K@ .NODE .NODEID 252 | .TIME .DATE 2%. .POS . .R CRASH SIL 253 | WIDE C->A K@ CA. CO. SPACES O. WO. 254 | SHOW 255 | 256 | HELP is also available for: 257 | DO INTRODUCTION FORTH NUMBERS SYMBOLS 258 | 259 | Sda> ^Z 260 | $ 261 | ``` 262 | 263 | The source-code for SDA is in UNSUPP$:SDA.FTH for your perusal and 264 | enjoyment. 265 | 266 | There's also a great deal of information about Forth on the 267 | [www.forth.org](http://www.forth.org) web site. The source-code 268 | also has information about Forth's handling of program SCREENs and 269 | files. 270 | 271 | 272 | ## Microcomputer cross-assemblers etc. 273 | 274 | In the 275 | [micros](https://github.com/agn453/RSTS-E/blob/master/micros) 276 | subdirectory, I've added a few of the microcomputer cross-assemblers 277 | that I developed whilst an undergraduate. These were originally 278 | written in BASIC-PLUS - and the source files have been converted 279 | to a format now acceptable to both BASIC-PLUS and the PDP-11 280 | BASIC-PLUS-2 V2.7-00 compiler. (The original source files used 281 | continuation lines of a LF CR NUL, with CR LF at the 282 | end of each statement). 283 | 284 | Cross-assemblers for 285 | 286 | * National Semiconductor SC/MP 287 | [SCMPCA.B2S](https://github.com/agn453/RSTS-E/blob/master/micros/SCMPCA.B2S) 288 | 289 | * Intel 8080/8085 with some Zilog Z80 op-codes (using Intel/TDL-style 290 | mnemonics) 291 | [X80.B2S](https://github.com/agn453/RSTS-E/blob/master/micros/X80.B2S) 292 | 293 | * MOS Technology 6502 294 | [X65.B2S](https://github.com/agn453/RSTS-E/blob/master/micros/X65.B2S) 295 | 296 | A dis-assembler for 297 | 298 | * National Semiconductor SC/MP 299 | [DISASM.B2S](https://github.com/agn453/RSTS-E/blob/master/micros/DISASM.B2S) 300 | 301 | and, 302 | 303 | * A program to convert hexadecimal output from the cross-assembler 304 | to an Intel HEX format absolute loader format file 305 | [INTEL.B2S](https://github.com/agn453/RSTS-E/blob/master/micros/INTEL.B2S) 306 | 307 | There are DCL command files to compile them, and I've included a binary 308 | task-image for each. 309 | 310 | 311 | ## Paul Koning's Ethernet driver patches and broadcast NTP client 312 | 313 | Paul Koning has released two more updates for RSTS/E V10.1. 314 | 315 | The first are patches to the Ethernet DEUNA and DEQNA drivers to fix 316 | user I/O and allow unit numbers beyond the first. See the xedvr.cmd and 317 | xhdvr.cmd files in the patches directory at 318 | https://github.com/pkoning2/decstuff 319 | 320 | The second is a broadcast NTP client that will synchronize the system clock 321 | with a Network Time Protocol server on the local Ethernet LAN (when it's 322 | configured to send out broadcast packets on UDP port 123). It includes 323 | handling of timezone rules so that the right thing will happen at daylight 324 | savings time changeovers. 325 | 326 | See https://github.com/pkoning2/decstuff/tree/master/ntp for details. 327 | 328 | 329 | ## Background 330 | 331 | I've been a User/Systems Programmer/System Manager/Computer Networking 332 | Engineer since my University days. 333 | 334 | My first contact was with RSTS/E V04A-12 in 1975 on a PDP-11/20 with 335 | a Teletype model 33 console. In 1977 a PDP-11/45 was purchased along 336 | with RSX-11D for the Electrical Engineering department for research 337 | purposes. I managed to get access to this machine and was able to book 338 | one or two hour exclusive sessions in the evenings. With things being 339 | how they were in those days, an RK05 copy "came into my hands" containing 340 | the installation kit for RSTS/E V06B. I no longer have the RK05, but I 341 | do have this 342 | [DECtape](https://github.com/agn453/RSTS-E/blob/master/photos/DECtape-RSTS-E-V06B.jpeg) 343 | that contains the sysgened monitor for V06B 344 | that one day I might be able to get at! 345 | 346 | Not being overly enthusiastic about RSX-11D, I used my allotted time 347 | to run RSTS/E and develop various cross-assemblers for 8085/Z80/6502 348 | microcomputers. It had a VT05 console (20 lines of 72 columns) so I could 349 | do this without wasting paper! 350 | 351 | Also at this time, a campus-wide time-sharing system using a PDP-11/45 352 | was being deployed - at first with 16 terminals (LA30S) running 353 | RSTS/E V06B. This was later updated to an PDP-11/70 with more memory 354 | and a fleet of additional video terminals (mainly ADM3A but with a few 355 | VT52s). 356 | 357 | I'll add more here later... 358 | 359 | Tony 360 | -------------------------------------------------------------------------------- /cusp-updates/fit/fit.diff: -------------------------------------------------------------------------------- 1 | *** FIT.BAS Fri Jul 3 08:19:16 2020 2 | --- FIT.BAS-orig Fri Jul 3 08:19:16 2020 3 | *************** 4 | *** 1,7 **** 5 | 2! PROGRAM : FIT.BAS 6 | 5! VERSION : V10.1 7 | ! 6! EDIT : B 8 | ! 7! EDIT DATE : 03-APR-20 9 | 10 EXTEND ! USE BASIC-PLUS EXTEND MODE 10 | 11! & 11 | ! & 12 | --- 1,7 ---- 13 | 2! PROGRAM : FIT.BAS 14 | 5! VERSION : V10.1 15 | ! 6! EDIT : A 16 | ! 7! EDIT DATE : 10-MAY-91 17 | 10 EXTEND ! USE BASIC-PLUS EXTEND MODE 18 | 11! & 19 | ! & 20 | *************** 21 | *** 32,45 **** 22 | 20 ! & 23 | ! & 24 | ! & 25 | ! ! M O D I F I C A T I O N H I S T O R Y & 26 | ! & 27 | 28 | 21 ! VER/ED EDIT DATE REASON & 29 | ! & 30 | ! V9.0-08 08-OCT-84 (DP) Check if user has TMPPRV priv & 31 | ! V9.0-10 25-Jan-85 (PRL) Fix help file loc -> HELP$: & 32 | - ! V10.1-B 03-Apr-20 (AGN) Y2K for RT-11 date word & 33 | & 34 | 100 ! & 35 | ! & 36 | --- 32,44 ---- 37 | 20 ! & 38 | ! & 39 | ! & 40 | ! ! M O D I F I C A T I O N H I S T O R T & 41 | ! & 42 | 43 | 21 ! VER/ED EDIT DATE REASON & 44 | ! & 45 | ! V9.0-08 08-OCT-84 (DP) Check if user has TMPPRV priv & 46 | ! V9.0-10 25-Jan-85 (PRL) Fix help file loc -> HELP$: & 47 | & 48 | 100 ! & 49 | ! & 50 | *************** 51 | *** 137,143 **** 52 | ! SET UP STANDARD ERROR TRAP. & 53 | ! DROP PRIVILEGES TEMPORARILY. & 54 | 55 | ! 1010 IDENT.STG$="V10.1-B" & 56 | ! SET UP VERSION/EDIT FOR HEADER. & 57 | 58 | 1030 PRINT FNRET$;"FIT";CHR$(9%);IDENT.STG$;CHR$(9%);FNE$(0%) & 59 | --- 136,142 ---- 60 | ! SET UP STANDARD ERROR TRAP. & 61 | ! DROP PRIVILEGES TEMPORARILY. & 62 | 63 | ! 1010 IDENT.STG$="V10.1-A" & 64 | ! SET UP VERSION/EDIT FOR HEADER. & 65 | 66 | 1030 PRINT FNRET$;"FIT";CHR$(9%);IDENT.STG$;CHR$(9%);FNE$(0%) & 67 | *************** 68 | *** 2186,2213 **** 69 | DEF* FNRT11.DATE%(T0%) & 70 | \ T0$=DATE$(T0%) & 71 | \ IF INSTR(1%,T0$,"-") THEN & 72 | - Y2%=VAL(RIGHT(T0$,8%)) & 73 | - ELSE Y2%=VAL(LEFT(T0$,2%)) & 74 | - ! & 75 | - ! Year needs to be split for Y2K & 76 | - 77 | - 15211 IF Y2% < 72% THEN & 78 | - Y2%=Y2%+100% & 79 | - 80 | - 15212 Y2%=Y2%-72% & 81 | - \ Y3%=0% & 82 | - \ IF Y2% > 31% THEN & 83 | - Y2%=((Y2% AND 96%)*512%) OR (Y2% AND 31%) & 84 | - 85 | - 15215 IF INSTR(1%,T0$,"-") THEN & 86 | FNRT11.DATE%= & 87 | ((INSTR(1%,"Xanebarprayunulugepctovec",MID(T0$,5%,2%))/2%)*32% & 88 | +VAL(LEFT(T0$,2%)))*32% & 89 | ! +Y2% & 90 | ELSE FNRT11.DATE%= & 91 | (VAL(MID(T0$,4%,2%))*32% & 92 | +VAL(RIGHT(T0$,7%)))*32% & 93 | ! +Y2% & 94 | ! & 95 | ! GET THE RSTS DATE STRING FOR DATE T0%. & 96 | ! PACK THE STRING INTO RT11 INTEGER DATE FORMAT. & 97 | --- 2185,2198 ---- 98 | DEF* FNRT11.DATE%(T0%) & 99 | \ T0$=DATE$(T0%) & 100 | \ IF INSTR(1%,T0$,"-") THEN & 101 | FNRT11.DATE%= & 102 | ((INSTR(1%,"Xanebarprayunulugepctovec",MID(T0$,5%,2%))/2%)*32% & 103 | +VAL(LEFT(T0$,2%)))*32% & 104 | ! +VAL(RIGHT(T0$,8%))-72% & 105 | ELSE FNRT11.DATE%= & 106 | (VAL(MID(T0$,4%,2%))*32% & 107 | +VAL(RIGHT(T0$,7%)))*32% & 108 | ! +VAL(LEFT(T0$,2%))-72% & 109 | ! & 110 | ! GET THE RSTS DATE STRING FOR DATE T0%. & 111 | ! PACK THE STRING INTO RT11 INTEGER DATE FORMAT. & 112 | *************** 113 | *** 2215,2223 **** 114 | ! BITS MEANING & 115 | ! 0-4 YEAR SINCE 1972. & 116 | ! 5-9 DAY OF MONTH. & 117 | ! ! 10-13 MONTH. & 118 | ! ! 14-15 AGE (HIGH YEAR BITS). & 119 | ! ! (See AA-5286M-TC RT-11 V5.7 Release Notes E.1) & 120 | 121 | 15220 FNEND & 122 | ! END OF FNRT11.DATE%(T0%) & 123 | --- 2200,2207 ---- 124 | ! BITS MEANING & 125 | ! 0-4 YEAR SINCE 1972. & 126 | ! 5-9 DAY OF MONTH. & 127 | ! ! 10-14 MONTH. & 128 | ! ! 15 RESERVED. & 129 | 130 | 15220 FNEND & 131 | ! END OF FNRT11.DATE%(T0%) & 132 | *************** 133 | *** 2242,2248 **** 134 | ! RETURNS: THE SPECIFIED DATE IN RSTS/E FORMAT. & 135 | ! & 136 | DEF* FNRSTS.DATE%(T0%) & 137 | ! \ YR%=(T0% AND 31%) OR ((T0%/512%) AND 96%) & 138 | \ DA%=T0%/32% AND 31% & 139 | \ MO%=T0%/1024% AND 15% & 140 | \ DA%=DA%+28%+VAL(MID("303232332323",T0%,1%)) FOR T0%=1% TO MO%-1% & 141 | --- 2226,2232 ---- 142 | ! RETURNS: THE SPECIFIED DATE IN RSTS/E FORMAT. & 143 | ! & 144 | DEF* FNRSTS.DATE%(T0%) & 145 | ! \ YR%=T0% AND 31% & 146 | \ DA%=T0%/32% AND 31% & 147 | \ MO%=T0%/1024% AND 15% & 148 | \ DA%=DA%+28%+VAL(MID("303232332323",T0%,1%)) FOR T0%=1% TO MO%-1% & 149 | -------------------------------------------------------------------------------- /cusp-updates/fit/fit.tsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/cusp-updates/fit/fit.tsk -------------------------------------------------------------------------------- /cusp-updates/fit/fitbld.com: -------------------------------------------------------------------------------- 1 | $! Build FIT.TSK from Y2K patched source 2 | $! supporting RT-11 dates > 31-Dec-2003 3 | $! 4 | $! Uses BP2 compiler 5 | $! 6 | $ run $bp2ic2 7 | old fit.bas 8 | compile fit/obj/chain/nowarn/list/cross:nokey 9 | build fit 10 | scratch 11 | exit 12 | $ tkb @fit 13 | $ set file/prot=232 fit.tsk 14 | $! 15 | $! To install, copy the FIT.TSK to AUXLIB$: 16 | $! 17 | $! $ rename auxlib$:fit.tsk auxlib$:fitold.tsk 18 | $! $ copy fit.tsk auxlib$: 19 | $! 20 | $ exit 21 | $! Alternative is to compile using BASIC-PLUS to FIT.BAC using 22 | $! 23 | $! $ SW BASIC 24 | $! 25 | $! Ready 26 | $! 27 | $! OLD FIT 28 | $! 29 | $! Ready 30 | $! 31 | $! COMPILE <232> 32 | $! 33 | -------------------------------------------------------------------------------- /decnete/nsp1.pat: -------------------------------------------------------------------------------- 1 | File to patch? 2 | Module name? NSP 3 | Base address? NSP1@OVR 4 | Offset address? 13054 5 | Base Offset Old New? 6 | ?????? 013054 005200 ? 4737 7 | ?????? 013056 005001 ? NSPPAT@OVR 8 | ?????? 013060 032702 ? ^Z 9 | Offset address? ^Z 10 | Base address? NSPPAT@OVR 11 | Offset address? 0 12 | Base Offset Old New? 13 | ?????? 000000 000000 ? 16301 14 | ?????? 000002 000000 ? 2 15 | ?????? 000004 000000 ? 4737 16 | ?????? 000006 000000 ? NSP1@OVR+12702 17 | ?????? 000010 000000 ? 5200 18 | ?????? 000012 000000 ? 5001 19 | ?????? 000014 000000 ? 207 20 | ?????? 000016 ?????? ? ^Z 21 | Offset address? ^Z 22 | Base address? ^Z 23 | Module name? ^Z 24 | File to patch? ^Z 25 | -------------------------------------------------------------------------------- /decnete/nsp1.txt: -------------------------------------------------------------------------------- 1 | NSP1.PAT is a patch for RSTS V10.1 for DECnet/E to improve dataflow 2 | under SIMH - see Paul Koning's e-mail to the simh mailing list dated 3 | 03-May-2016 4 | 5 | > On Apr 19, 2016, at 2:46 PM, Paul Koning wrote: 6 | > 7 | > With help from Mark Pizzolato, I've been looking at why RSTS (DECnet/E) 8 | > operates so slowly when it's dealing with one way transfers. 9 | > This is independent of protocol and datalink type; it shows up very clearly 10 | > in NFT (any kind of file transfer or directory listing) and also in NET 11 | > (Set Host). The symptom is that data comes across in fairly short bursts, 12 | > separated by about a second of pause. 13 | > 14 | > This turns out to be an interaction between the DECnet/E queueing rules 15 | > and the very fast operation of SIMH on modern hosts. DECnet/E will queue 16 | > up to some small number of NSP segments for any given connection, set by 17 | > the executor parameter "data transmit queue max". The default value is 18 | > 4 or 5, but it can be set higher, and that helps some. 19 | > 20 | > The trouble is this: if you have a one way data flow, for example NFT or 21 | > FAL doing a copy, the sending program simply fires off a sequence of 22 | > send-packet operations until it gets a "queue full" reject from the kernel. 23 | > At that point it delays, but the delay is one second since sleep operations 24 | > have one second granularity. The other end acks all that data quite 25 | > promptly, but since the emulation runs so fast, the whole transmit queue 26 | > can fill up before the ack from the other end arrives, so the queue full 27 | > condition occurs, then a one second delay, then the process starts over. 28 | > 29 | > This sort of thing doesn't happen on request/response exchanges; for example 30 | > the NCP command LOOP NODE runs at top speed because traffic is going both 31 | > ways. 32 | > 33 | > I tried fiddling with the data queue limit to see if increasing it would 34 | > help. It seems to, but it's not sufficient. What does work is a larger 35 | > queue limit (32 looks good) combined with CPU throttling to slow things 36 | > down a bit. I used "set throttle 2000/1" (which produces a 1 ms delay 37 | > every 2000 instructions, i.e., roughly 2 MIPS processing speed which is at 38 | > the high end of what real PDP-11s can do). Those two changes combined 39 | > make file transfer run smoothly and fast. 40 | > 41 | > Ideally DECnet/E should cancel the program sleep when the queue transitions 42 | > from full to not-full, but that's not part of the existing logic (at least 43 | > not unless the program explicitly asks for "link status notifications"). 44 | > I could probably add that; the question is how large a change it is -- 45 | > does it exceed what's feasible for a patch. I may still do that, but at 46 | > least for now the above should be helpful. 47 | 48 | Followup: I created a patch that implements the "wake up when the queue goes 49 | not-full". Or more precisely, it wakes up the process whenever an ack is 50 | received; that covers the problem case and probably doesn't create many other 51 | wakeups since the program is unlikely to be sleeping otherwise. 52 | 53 | The attached patch script does the job. This is for RSTS V10.1. I will take a 54 | look at RSTS 9.6; the patch is unlikely to apply there (offsets probably don't 55 | match) but the concept will apply there too. I don't have other DECnet/E 56 | versions, let alone source listings which is what's needed to create the patch. 57 | 58 | With this patch, you can run at full emulation speed, with the default queue 59 | limit (5). In fact, I would recommend setting that limit; if you make the 60 | queue limit significantly larger, the patch doesn't help and things are still 61 | slow. I suspect that comes from overrunning the queue limits at the receiving 62 | end. (Note that DECnet/E leaves the flow control choice to the application, 63 | and most use "no" flow control, i.e., on/off only which isn't effective if the 64 | sender can overrun the buffer pool of the receiver.) 65 | 66 | To apply the patch, give it to ONLPAT and select the monitor SIL (just 67 | will give you the installed one). Or you can do it with the PATCH option at 68 | boot time, in that case enter the information manually. The manual will spell 69 | this out some more, I expect. 70 | 71 | I have no idea if this issue can appear on real PDP-11 systems. Possibly, if 72 | you have a fast CPU, a fast network (Ethernet) and enough latency to make the 73 | issue visible (more than a few milliseconds but way under a second). In any 74 | case, it's unlikely to hurt, and it clearly helps a great deal in emulated 75 | systems. 76 | 77 | paul 78 | -------------------------------------------------------------------------------- /docs/AA-5286M-TC-RT-11-V5.7_System_Release_Notes_Oct1998.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/docs/AA-5286M-TC-RT-11-V5.7_System_Release_Notes_Oct1998.pdf -------------------------------------------------------------------------------- /docs/AV-RK36A-TE-RSTS_E-V10.1A_Cover_Letter_Year_2000_Update_1999.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/docs/AV-RK36A-TE-RSTS_E-V10.1A_Cover_Letter_Year_2000_Update_1999.pdf -------------------------------------------------------------------------------- /docs/SPD-13_01_37-RSTS_E-Version_10.1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/docs/SPD-13_01_37-RSTS_E-Version_10.1.pdf -------------------------------------------------------------------------------- /layered/dibol/dibol.txt: -------------------------------------------------------------------------------- 1 | On Monday, April 6, 2020 at 11:27:41 AM UTC+10, Tony Nicholson wrote: 2 | > 3 | > While re-reading the Release Notes for RSTS/E V10.1 I found a 4 | > reference to DIBOL suggesting that a full install kit is in the 5 | > PATCH$: directory as SY:[0,200]DBLKIT.BCK 6 | > 7 | > Indeed it is DIBOL V6.1-F for RSTS/E and it needs a bit of 8 | > trickery to install it without the media kit for an older 9 | > version of DIBOL. Use something like the following as a 10 | > guide - 11 | > 12 | > $ create/account sy:[0,59]/name="DIBOL" 13 | > Non-user account _SY:[0,59] created at DCN 23091 14 | > $ copy patch$:dibol.com patch$:dibolo.com ! preserve original 15 | > [File [0,200]DIBOL .COM copied to [0,200]DIBOLO.COM] 16 | > $ edit/edt/nocommand patch$:dibol.com !edit in line-mode 17 | > 1 $ ! 18 | > *109 19 | > 109 $ ! 20 | > *i 21 | > $ _goto DIBOLV61 !force install from PATCH$:DBLKIT.BCK 22 | > ^Z 23 | > 109 $ ! 24 | > *290 25 | > 290 $ _DISMOUNT'UNL' 'LIB' ! We no longer need the load device any longer 26 | > *s/$/$!/ 27 | > 290 $! _DISMOUNT'UNL' 'LIB' ! We no longer need the load device any longer 28 | > 1 substitution 29 | > *ex 30 | > SY:[0,200]DIBOL .COM 552 lines 31 | > 32 | > $ assign/sys sy:[1,2] syslib$$: 33 | > $ assign/sys sy:[1,1] lb$$: 34 | > $ @patch$:dibol DIBOL$ "Y" WORK$ HELP$ PATCH$: NL0: 35 | > 36 | > Answer the configuration questions (I chose YES to all, and IVP test output to KB: instead of LP:) 37 | > 38 | > At the completion of the IVP all is installed. 39 | > 40 | > Next just add lines to your [0,1]START.COM start-up file to 41 | > include DIBOL in your operating environment (just before 42 | > LOGINs are enabled) - 43 | > 44 | > $!AGN - added DIBOL V6.1-F (installed from the PATCH$ directory) 45 | > $ _write 0 f$time()+ " Starting DIBOL" 46 | > $ _if f$search("DIBOL$:DIBV61.COM") .nes. "" then @DIBOL$:DIBV61.COM 47 | > 48 | > Enjoy! 49 | > 50 | > Tony 51 | -------------------------------------------------------------------------------- /micros/DISASB.COM: -------------------------------------------------------------------------------- 1 | $! Command file to build DISASM.B2S (with Basic-Plus-2) 2 | $! 3 | $ set noOn 4 | $ run $bp2ic2 5 | SCALE 0 6 | OLD DISASM.B2S 7 | COMPILE DISASM/OBJECT/CHAIN/NODEBUG/NOCROSS/NOLIST/NOWARN 8 | BUILD DISASM 9 | SCRATCH 10 | EXIT 11 | $ tkb @DISASM 12 | $ del disasm.odl, disasm.obj, disasm.cmd 13 | $ exit 14 | -------------------------------------------------------------------------------- /micros/DISASM.B2S: -------------------------------------------------------------------------------- 1 | 1010 REM & 2 | REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! & 3 | REM !! !! & 4 | REM !! SC/MP DIS ASSEMBLER !! & 5 | REM !! !! 6 | 1020 REM !! A.G. NICHOLSON, NEWCASTLE UNI. !! & 7 | REM !! !! & 8 | REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! & 9 | 10 | 1030 REM ! LAST EDITED 13-MAY-77 ! & 11 | 12 | 1040 DIM O$(46%), O%(46%), X(3%), L(100%), C$(32%) 13 | 1050 ! INITIALISE 14 | 1060 D%,F%,N0%,T%=0% & 15 | \ P%=1% 16 | 1070 L(0%)=-1% 17 | 1080 U$=" #### \ \ \\ \\ \ \ \ \ \ \ " 18 | 1090 H$="0123456789ABCDEF" & 19 | \ READ X(I%) FOR I%=0% TO 3% 20 | 1100 DATA 1,16,256,4096 21 | 1110 READ O$(I%), O%(I%) FOR I%=1% TO 46% 22 | 1120 ! MEMORY REFERENCE INSTRUCTIONS 1-8 23 | 1130 DATA LD,192,ST,200,AND,208,OR,216,XOR,224,DAD,232,ADD,240,CAD,248 24 | 1140 ! TRANSFER INSTRUCTIONS 9-12 25 | 1150 DATA JMP,144,JP,148,JZ,152,JNZ,156 26 | 1160 ! MEMORY INCREMENT, DECREMENT INSTRUCTIONS 13-14 27 | 1170 DATA ILD,168,DLD,184 28 | 1180 ! IMMEDIATE INSTRUCTIONS 15-21 29 | 1190 DATA LDI,196,ANI,212,ORI,220,XRI,228,DAI,236,ADI,244,CAI,252 30 | 1200 ! DELAY INSTRUCTION 22 31 | 1210 DATA DLY,143 32 | 1220 ! POINTER MOVE INSTRUCTIONS 23-25 33 | 1230 DATA XPAL,48,XPAH,52,XPPC,60 34 | 1240 ! EXTENSION REGISTER INSTRUCTIONS 26-33 35 | 1250 DATA LDE,64,XAE,1,ANE,80,ORE,88,XRE,96,DAE,104,ADE,112,CAE,120 36 | 1260 ! SERIAL I/O, SHIFT & ROTATE INSTRUCTIONS 34-38 37 | 1270 DATA SIO,25,SR,28,SRL,29,RR,30,RRL,31 38 | 1280 ! MISCELLANEOUS INSTRUCTIONS 39-46 39 | 1290 DATA HALT,0,CCL,2,SCL,3,IEN,5,DINT,4,CSA,6,CAS,7,NOP,8 40 | 1300 MAT READ C$ 41 | 1310 ! ASCII CHARACTERS 0 TO 32 42 | 1320 DATA NUL,SOH,STX,EXT,EOT,ENQ,ACK,BEL,BS,HT,LF,VT,FF,CR,SO,SI 43 | 1330 DATA DEL,DC1,DC2,DC3,DC4,NAK,SYN,ETB,CAN,EM,SUB,ESC,FS,GS,RS,US 44 | 1340 OPEN "KB:" AS FILE 1% 45 | 1350 Z%=1% ! OUTPUT CHANNEL NUMBER 46 | 1360 PRINT #1% & 47 | \ PRINT #1%,"SC/MP DIS-ASSEMBLER" & 48 | \ PRINT #1% 49 | 1370 PRINT #1%,"#"; & 50 | \ INPUT LINE #1%,F$ & 51 | \ F$=CVT$$(F$,4%) 52 | 1380 I%=INSTR(1%,F$,"<") OR INSTR(1%,F$,"=") 53 | 1390 IF I% THEN X$=LEFT(F$,I%-1%) & 54 | \ OPEN X$ FOR OUTPUT AS FILE 3% & 55 | \ PRINT #1%," OUTPUT TO ";X$ & 56 | \ Z%=3% & 57 | \ F$=RIGHT(F$,I%+1%) & 58 | \ PRINT #1% 59 | 1400 OPEN F$ FOR INPUT AS FILE 2% & 60 | \ PRINT #1% 61 | 1410 PRINT #1%," STARTING ADDRESS (HEX) ?"; & 62 | \ INPUT #1%,A$ & 63 | \ N1=FND(A$) & 64 | \ PRINT #1% 65 | 1420 ! PASS 1 66 | 1430 PRINT #1%," PASS 1" 67 | 1440 GOSUB 2240% 68 | 1450 ! GET SINGLE BYTE PORTIONS AND DECODE 69 | 1460 FOR J%=2% TO L% STEP 2% 70 | 1470 B$=MID(L$,J%-1%,2%) & 71 | \ GOTO 1530% IF D% & 72 | \ GOTO 1630% IF B$="XX" 73 | 1480 B%=FND(B$) & 74 | \ N0%=N0%+1% 75 | 1490 GOTO 1610% IF B%<128% 76 | 1500 ! TWO BYTE INSTRUCTIONS 77 | 1510 IF J%=L% THEN D%=-1% & 78 | \ GOTO 1610% 79 | 1520 J%=J%+2% & 80 | \ B$=MID(L$,J%-1%,2%) 81 | 1530 IF B$="XX" THEN PRINT #1%, & 82 | "MISSING ARGUMENT AT LINE ";FNH$(N1+N0%);" (HEX)" & 83 | \ GOTO 1630% 84 | 1540 D%=0% ! RESET CONTINUATION BYTE 85 | 1550 N0%=N0%+1% 86 | 1560 ! TEST FOR A TRANSFER INSTRUCTION 87 | 1570 IF B%<144% OR B%>159% THEN B%=FND(B$) & 88 | \ GOTO 1610% 89 | 1580 B%=FND(B$) 90 | 1590 ! ENTER LINE NUMBER REFERENCED IN TABLE T() 91 | 1600 B%=B%-256% IF B%>127% & 92 | \ GOTO 1610% IF L(I%)=N1+N0%+B%+1% FOR I%=0% TO T% & 93 | \ T%=T%+1% & 94 | \ L(T%)=N1+N0%+B%+1% 95 | 1610 NEXT J% ! PROCESS NEXT CHARACTER 96 | 1620 GOTO 1440% 97 | 1630 ! END PASS 1 98 | 1640 CLOSE 2% 99 | 1650 D%,F%=0% 100 | 1660 ! PASS 2 101 | 1670 OPEN F$ FOR INPUT AS FILE 2% & 102 | \ PRINT #1%," PASS 2" & 103 | \ PRINT #1% 104 | 1680 PRINT #Z%," ADDR B1 B2 LABEL OPCODE ARGUMENT "; & 105 | "[DECIMAL] " & 106 | \ PRINT #Z% 107 | 1690 PRINT #Z% 108 | 1700 P%=2% & 109 | \ N0%=0% 110 | 1710 GOSUB 2240% 111 | 1720 FOR J%=2% TO L% STEP 2% 112 | 1730 B$=MID(L$,J%-1%,2%) & 113 | \ GOTO 1950% IF D% & 114 | \ B1$=B$ & 115 | \ GOTO 2210% IF B$="XX" 116 | 1740 B%=FND(B$) & 117 | \ N0%=N0%+1% 118 | 1750 S$,O$,A$="" 119 | 1760 ! CHECK TO SEE WHETHER STATEMENT IS LABELED 120 | 1770 S$="L"+CVT$$(NUM$(I%),2%)+":" IF L(I%)=N1+N0% FOR I%=0% TO T% 121 | 1780 O%=B% & 122 | \ GOTO 2060% IF B%<128% 123 | 1790 ! TWO BYTE INSTRUCTIONS 124 | 1800 N1%=2% ! NUMBER OF BYTES 125 | 1810 ! POINTER REFERENCE CHECK FOR TRANSFER, MEMORY INC/DEC 126 | 1820 FOR I%=1% TO 3% & 127 | \ FOR K%=9% TO 14% 128 | 1830 IF O%(K%)+I%=O% THEN A$=A$+"("+CVT$$(NUM$(I%),2%)+")" & 129 | \ O%=O%-I% & 130 | \ GOTO 1910% 131 | 1840 NEXT K% & 132 | \ NEXT I% 133 | 1850 ! AUTO INDEX AND POINTER CHECK FOR MEMORY REFERENCE 134 | 1860 FOR K%=1% TO 8% & 135 | \ FOR I%=1% TO 3% 136 | 1870 IF O%(K%)+4%+I%=O% THEN A$="@("+CVT$$(NUM$(I%),2%)+")" & 137 | \ O%=O%-4%-I% & 138 | \ GOTO 1910% 139 | 1880 IF O%(K%)+I%=O% THEN A$="("+CVT$$(NUM$(I%),2%)+")" & 140 | \ O%=O%-I% & 141 | \ GOTO 1910% 142 | 1890 NEXT I% & 143 | \ NEXT K% 144 | 1900 ! FIND OPCODE FOR DOUBLE BYTE INSTRUCTION 145 | 1910 O$=O$(I%) IF O%(I%)=O% FOR I%=1% TO 22% 146 | 1920 ! GET SECOND BYTE 147 | 1930 IF J%=L% THEN D%=-1% & 148 | \ GOTO 2180% ! SECOND BYTE ON NEXT PHYSICAL LINE IN FILE F$ 149 | 1940 J%=J%+2% & 150 | \ B$=MID(L$,J%-1%,2%) 151 | 1950 GOTO 2210% IF B$="XX" 152 | 1960 D%=0% 153 | 1970 B2$=B$ 154 | 1980 N0%=N0%+1% 155 | 1990 ! CHECK FOR TRANSFER INSTRUCTION 156 | 2000 GOTO 2030% IF B%<144% OR B%>159% 157 | 2010 ! ADD LABEL REFERENCED TO ARGUMENT 158 | 2020 B%=FND(B$) & 159 | \ B%=B%-256% IF B%>127% & 160 | \ A$=A$+"L"+CVT$$(NUM$(I%),2%) IF L(I%)=N1+N0%+B%+1% FOR I%=0% TO T% & 161 | \ GOTO 2050% 162 | 2030 A$=A$+"X'"+B2$ 163 | 2040 ! OUTPUT TO CHANNEL 1 164 | 2050 GOSUB 2300% & 165 | \ GOTO 2180% 166 | 2060 ! SINGLE BYTE INSTRUCTIONS 167 | 2070 N1%=1% ! NUMBER OF BYTES 168 | 2080 ! CHECK POINTER MOVE 169 | 2090 FOR K%=23% TO 25% & 170 | \ FOR I%=0% TO 3% 171 | 2100 IF O%(K%)+I%=O% THEN A$=CVT$$(NUM$(I%),2%) & 172 | \ O%=O%-I% & 173 | \ GOTO 2130% 174 | 2110 NEXT I% & 175 | \ NEXT K% 176 | 2120 ! SET OPCODE FOR SINGLE BYTE INSTRUCTION 177 | 2130 O$=O$(I%) IF O%(I%)=O% FOR I%=23% TO 46% 178 | 2140 IF O$="" THEN O$=".BYTE" \ A$="X'"+B1$ 179 | 2150 B2$="" 180 | 2160 ! OUTPUT TO CHANNEL 1 181 | 2170 GOSUB 2300% 182 | 2180 NEXT J% 183 | 2190 ! GET NEXT LINE FROM FILE F$ 184 | 2200 GOTO 1710% 185 | 2210 ! EXIT 186 | 2220 CLOSE 2% & 187 | \ PRINT #Z% FOR I%=1% TO 3% & 188 | \ CLOSE 1%,3% 189 | 2230 GOTO 32767% 190 | 2240 ! SUBROUTINE TO GET A LINE FROM FILE F$ 191 | 2250 INPUT LINE #2%,L$ & 192 | \ L$=CVT$$(L$,6%) & 193 | \ L%=LEN(L$) & 194 | \ GOTO 2250% IF L%=0% 195 | 2260 ! F% IS THE NUMBER OF THE LINE READ FROM FILE F$ 196 | 2270 F%=F%+1% 197 | 2280 IF (L%/2%)*2%<>L% THEN PRINT #1%, & 198 | "INCOMPLETE BYTE READ FROM ";F$;", LINE";F% & 199 | \ L$=L$+" " 200 | 2290 RETURN 201 | 2300 ! OUTPUT ROUTINE TO CHANNEL Z% 202 | 2310 PRINT #Z% USING U$,N0%-N1%,FNH$(N1+N0%-N1%),B1$,B2$,S$,O$,A$; 203 | 2320 ! LINE NUMBER, ADDR B1 B2 LABEL: OPCODE ARGUMENT 204 | 2330 IF B2$="" THEN B$=B1$ ELSE B$=B2$ & 205 | \ B%=FND(B$) 206 | 2340 IF B%<32% THEN C$=C$(B%+1%) ELSE IF B%<96% THEN C$=CHR$(B%) 207 | 2350 B%=B%-256% IF B%>127% 208 | 2360 PRINT #Z% USING "[ #### ]",B%; 209 | 2370 IF C$<>"" THEN PRINT #Z% USING " < \ \ >",C$ ELSE PRINT #Z% 210 | 2380 C$="" 211 | 2390 RETURN 212 | 2400 DEF* FNH$(X) ! HEXADECIMAL CONVERSION 213 | 2410 X0=X & 214 | \ X0=X0+65536 IF X0<0% & 215 | \ X0=INT(X0+0.1) & 216 | \ GOTO 2440% IF X0>65536 & 217 | \ X$="" 218 | 2420 FOR X%=3% TO 1% STEP -1% & 219 | \ X1=X(X%) & 220 | \ X2=INT(X0/X1) & 221 | \ X0=X0-X1*X2 & 222 | \ X2=X2+1% & 223 | \ X$=X$+MID(H$,X2,1%) 224 | 2430 NEXT X% & 225 | \ FNH$=X$+MID(H$,X0+1%,1%) & 226 | \ GOTO 2450% 227 | 2440 PRINT #1%,"OVERFLOW IN HEX CONVERSION" & 228 | \ E%=E%+1% & 229 | \ FNH$=" " 230 | 2450 FNEND 231 | 2460 DEF* FND(X$) ! HEX TO DECIMAL CONVERSION 232 | 2470 X=LEN(X$) & 233 | \ X0=0% & 234 | \ GOTO 2500% IF X>4% 235 | 2480 FOR X%=0% TO X-1% & 236 | \ X1$=MID(X$,X-X%,1%) & 237 | \ GOTO 2490% IF X1$=MID(H$,X1,1%) FOR X1=1% TO 16% & 238 | \ PRINT #1%,"ILLEGAL CHARACTER IN HEX NUMBER :";X$ & 239 | \ GOTO 2510% 240 | 2490 X0=X0+(X1-1%)*X(X%) & 241 | \ NEXT X% & 242 | \ FND=X0 & 243 | \ GOTO 2520% 244 | 2500 PRINT #1%,"OVERFLOW IN DECIMAL CONVERSION :" 245 | 2510 E%=E%+1% & 246 | \ FND=0% 247 | 2520 FNEND 248 | 32767 END 249 | -------------------------------------------------------------------------------- /micros/DISASM.TSK: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/micros/DISASM.TSK -------------------------------------------------------------------------------- /micros/INTEL.B2S: -------------------------------------------------------------------------------- 1 | 10 ON ERROR GOTO 220 2 | 15 PRINT "Hex dump to INTEL absolute load format" 3 | 16 PRINT 4 | 20 PRINT "Filename "; 5 | 30 INPUT LINE F$ 6 | 40 OPEN F$ FOR INPUT AS FILE 1% 7 | 50 PRINT "Output to "; 8 | 60 INPUT LINE O$ 9 | 70 OPEN O$ FOR OUTPUT AS FILE 2% 10 | 80 INPUT "Start address (hex) ";S$ 11 | 90 WHILE -1% 12 | 100 INPUT #1%,L$ 13 | 111 N$=RIGHT(FNH$(LEN(L$)/2%),3%) 14 | 112 N%=FND%(N$) 15 | 113 C%=N%+FND%(LEFT(S$,2%))+FND%(RIGHT(S$,3%)) 16 | 120 PRINT #2%,":"+N$+S$+"00"; 17 | 150 FOR I%=1% TO 31% STEP 2% 18 | 151 D$=MID(L$,I%,2%) 19 | 152 D%=FND%(D$) 20 | 153 C%=C%+D% 21 | 160 PRINT #2%,D$; 22 | 170 NEXT I% 23 | 180 PRINT #2%,RIGHT(FNH$(-C%),3%) 24 | 200 S$=FNH$(FND%(S$)+16%) 25 | 210 NEXT 26 | 220 PRINT #2% 27 | 230 CLOSE 1%,2% 28 | 240 PRINT 29 | 250 PRINT "Done" 30 | 260 GOTO 32767 31 | 1000 DEF* FND%(X$) 32 | 1010 X0%=0% 33 | 1020 FOR X1%=1% TO LEN(X$) 34 | 1030 X2%=ASCII(MID(X$,X1%,1%)) 35 | 1040 IF X2%<48% OR (X2%>57% AND X2%<65%) OR X2%>70% THEN & 36 | PRINT "Illegal hex character in "+X$ \ STOP 37 | 1050 X2%=X2%-48% 38 | 1060 X2%=X2%-7% IF X2%>9% 39 | 1070 X0%=X2%+X0%*16% 40 | 1080 NEXT X1% 41 | 1090 FND%=X0% 42 | 1100 FNEND 43 | 2000 DEF* FNH$(X%) 44 | 2010 X$="" 45 | 2020 FOR X1%=0% TO 3% 46 | 2030 X0%=(X% AND (16%^(X1%+1%)-1%*(16%^X1%)))/(16%^X1%) 47 | 2040 X0%=X0%+16% IF X0%<0% 48 | 2050 X$=CHR$(48%+X0%)+X$ IF X0%<10% 49 | 2060 X$=CHR$(55%+X0%)+X$ IF X0%>9% 50 | 2070 NEXT X1% 51 | 2080 FNH$=X$ 52 | 2090 FNEND 53 | 32767 END 54 | -------------------------------------------------------------------------------- /micros/INTEL.TSK: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/micros/INTEL.TSK -------------------------------------------------------------------------------- /micros/INTELB.COM: -------------------------------------------------------------------------------- 1 | $! Command file to build INTEL.B2S (with Basic-Plus-2) 2 | $! 3 | $ set noOn 4 | $ run $bp2ic2 5 | SCALE 0 6 | OLD INTEL.B2S 7 | COMPILE INTEL/OBJECT/CHAIN/NODEBUG/NOCROSS/NOLIST/NOWARN 8 | BUILD INTEL 9 | SCRATCH 10 | EXIT 11 | $ tkb @INTEL 12 | $ del intel.odl, intel.obj, intel.cmd 13 | $ exit 14 | -------------------------------------------------------------------------------- /micros/SCMBLD.COM: -------------------------------------------------------------------------------- 1 | $! Command file to build SCMPCA.B2S (with Basic-Plus-2) 2 | $! 3 | $ set noOn 4 | $ run $bp2ic2 5 | SCALE 0 6 | OLD SCMPCA.B2S 7 | COMPILE SCMPCA/OBJECT/CHAIN/NODEBUG/NOCROSS/NOLIST/NOWARN 8 | BUILD SCMPCA 9 | SCRATCH 10 | EXIT 11 | $ tkb @SCMPCA 12 | $ del scmpca.odl, scmpca.obj, scmpca.cmd 13 | $ exit 14 | -------------------------------------------------------------------------------- /micros/SCMPCA.B2S: -------------------------------------------------------------------------------- 1 | 1010 REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! & 2 | REM !! !! & 3 | REM !! SC/MP CROSS ASSEMBLER !! & 4 | REM !! !! 5 | 1020 REM !! A.G. NICHOLSON, NEWCASTLE UNI. !! & 6 | REM !! !! & 7 | REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 8 | 1021 REM & 9 | REM ! Last edited: 30-Jan-79 & 10 | 11 | 1025 C9%=0% 12 | 1030 DIM O$(51), O%(51), T$(255), T%(255), D%(3) 13 | 1040 ! -- Set up error trap routine -- 14 | 1050 ON ERROR GOTO 31020 & 15 | \ X$=SYS(CHR$(6%)+CHR$(-7%)) 16 | 1060 ! -- Initialise -- 17 | 1070 N%=51% & 18 | \ T%(0%)=255% & 19 | \ T0%=TIME(1%) & 20 | \ F1$="KB:" & 21 | \ READ O$(I%), O%(I%) FOR I%=0% TO N% 22 | 1080 ! -- Print header -- 23 | 1090 OPEN F1$ AS FILE 1% & 24 | \ GOTO 1130 IF C9% & 25 | \ PRINT #1%,"SC/MP Cross assembler" & 26 | \ PRINT #1%,"#"; 27 | 1100 ! -- Get listing, source filenames -- 28 | 1110 INPUT LINE #1%, F2$ & 29 | \ F2$=CVT$$(F2$,-1%) 30 | 1120 ! -- Check for errors only switch -- 31 | 1130 F0%=-1% & 32 | \ L%=INSTR(1%,F2$,"/E") & 33 | \ IF L% THEN F2$=LEFT(F2$,L%-1%)+RIGHT(F2$,L%+2%) & 34 | \ F0%=0% 35 | 1140 ! -- Check for object module output switch -- 36 | 1150 F4%=0% & 37 | \ L%=INSTR(1%,F2$,"/O") & 38 | \ IF L% THEN F2$=LEFT(F2$,L%-1%)+RIGHT(F2$,L%+2%) & 39 | \ F4%=-1% 40 | 1160 ! -- Check for listing file and add default extensions -- 41 | 1170 F5%=INSTR(1%,F2$,"=") & 42 | \ IF F5% THEN F1$=LEFT(F2$,F5%-1%) & 43 | \ F1$=F1$+".LST" UNLESS INSTR(1%,F1$,".") & 44 | \ F2$=RIGHT(F2$,F5%+1%) 45 | 1180 F2$=F2$+".SRC" UNLESS INSTR(1%,F2$,".") 46 | 1190 PRINT #1%,"Listing sent to ";F1$ IF F5% 47 | 1200 IF F4% THEN F4$=LEFT(F2$,INSTR(1%,F2$,"."))+"BIN" & 48 | \ PRINT #1%,"Object module to ";F4$ 49 | 1210 ! -- Get a unique workfile name -- 50 | 1220 W$="SCMP"+MID(NUM$(100%+ASCII(SYS(CHR$(6%)+CHR$(9%)))/2%),3%,2%)+".TMP" 51 | 1230 ! -- Commence assembly -- 52 | 1240 GOSUB 1310 & 53 | \ GOSUB 1860 & 54 | \ X%=1% & 55 | \ GOSUB 2460 56 | 1250 ! -- Print symbol table -- 57 | 1260 GOSUB 2480 IF T% AND F0% & 58 | \ PRINT #1% 59 | 1270 ! -- Finish up and exit -- 60 | 1280 CLOSE 1 & 61 | \ IF F5% THEN X%=0% & 62 | \ GOSUB 2460 63 | 1290 PRINT "Runtime was";(TIME(1%)-T0%)/10;"sec" & 64 | \ GOTO 32767 65 | 1300 ! -- Pass 1 Driver routine -- 66 | 1310 E%,T%,N0%,N1%,F1%,O%=0% \ P0%=1% & 67 | \ OPEN F2$ FOR INPUT AS FILE 2% & 68 | \ PRINT #1% & 69 | \ OPEN W$ FOR OUTPUT AS FILE 3% & 70 | \ PRINT #1%,"Pass 1" 71 | 1320 FOR L%=1% STEP 1% UNTIL O%=N% & 72 | \ INPUT LINE #2%, L$ & 73 | \ L$=CVT$$(L$,165%) & 74 | \ L1%=LEN(L$) 75 | 1330 IF L1%=0% THEN O%=0% & 76 | \ GOTO 1450 77 | 1340 ! -- Scan source line -- 78 | 1350 GOSUB 1470 & 79 | \ GOSUB 1520 80 | 1360 ! -- Comment line ? -- 81 | 1370 IF D3%=1% THEN O%=0% & 82 | \ GOTO 1450 83 | 1380 ! -- Get argument field -- 84 | 1390 IF D3% THEN A$=CVT$$(MID(L$,D2%+1%,D3%-D2%-1%),136%) & 85 | ELSE A$=CVT$$(RIGHT(L$,D2%+1%),8%) 86 | 1400 ! -- Label ? -- 87 | 1410 IF D1% THEN S$=CVT$$(LEFT(L$,D1%-1%),128%) & 88 | \ S1%=N1% & 89 | \ GOSUB 1600 90 | 1420 ! -- Assignment ? -- 91 | 1430 IF D4% THEN GOSUB 1650 & 92 | ELSE GOSUB 1690 93 | 1440 ! -- Write to workfile -- 94 | 1450 GOSUB 1710 & 95 | \ NEXT L% & 96 | \ CLOSE 2,3 & 97 | \ RETURN 98 | 1460 ! -- Scan for strings in L$, D%() is the delimiter table -- 99 | 1470 D%=-1% & 100 | \ S2%=0% 101 | 1480 S1%=INSTR(S2%+1%,L$,"'") & 102 | \ RETURN UNLESS S1% & 103 | \ IF MID(L$,S1%-1%,1%)="X" THEN S2%=S1% & 104 | \ GOTO 1480 105 | 1490 S2%=INSTR(S1%+1%,L$,"'") & 106 | \ IF S2% THEN D%=D%+1% & 107 | \ IF D%<4% THEN D%(D%)=SWAP%(S1% AND 255%) OR (S2% AND 255%) & 108 | \ GOTO 1480 109 | 1500 RETURN 110 | 1510 & 111 | ! -- Search for token delimiters -- & 112 | ! D1% Label & 113 | ! D2% Opcode & 114 | ! D3% Comment & 115 | ! D4% Assignment 116 | 1520 D1%=INSTR(1%,L$,":") & 117 | \ D1%=0% IF FNS%(D1%) & 118 | \ D3%=0% 119 | 1530 D3%=INSTR(D3%+1%,L$,";") & 120 | \ GOTO 1530 IF FNS%(D3%) & 121 | \ D1%=0% IF (D1%>D3% AND D3%<>0%) & 122 | \ D2%=D1% 123 | 1540 D2%=D2%+1% & 124 | \ IF D2%>=L1% THEN 1560 & 125 | ELSE X%=ASCII(RIGHT(L$,D2%)) & 126 | \ IF X%=9% OR X%=32% THEN 1540 127 | 1550 D2%=D2%+1% & 128 | \ IF D2%9% AND X%<>32% THEN 1550 & 130 | ELSE D2%=D2%-1% 131 | 1560 D4%=INSTR(1%,L$,"=") & 132 | \ D4%=0% IF FNS%(D4%) OR (D4%>D3% AND D3%<>0%) & 133 | \ D2%=D4% IF D4% 134 | 1570 D2%=D3%-1% IF (D2%>=D3% AND D3%<>0%) & 135 | \ RETURN 136 | 1590 & 137 | ! Enter symbol S$ and its value S1% into T$() and T%() & 138 | 139 | 1600 X%=ASCII(S$) & 140 | \ IF X%<65% OR X%>90% OR LEN(S$)>6% THEN & 141 | X%=FNE%("Inv sym "+S$) & 142 | \ RETURN 143 | 1610 FOR I%=1% TO T% & 144 | \ IF S$=T$(I%) THEN S1%=FNE%("Redef sym "+S$) & 145 | \ RETURN 146 | 1620 NEXT I% & 147 | \ IF T%=T%(0%) THEN PRINT #1%,"Sym ovf" & 148 | \ RETURN 149 | 1630 T%=T%+1% & 150 | \ T$(T%)=S$ & 151 | \ T%(T%)=S1% & 152 | \ RETURN 153 | 1640 ! -- Enter assignment -- 154 | 1650 S$=CVT$$(MID(L$,D1%+1%,D4%-D1%-1%),136%) & 155 | \ S1%=FNA%(A$) 156 | 1660 IF S$="." THEN N1%=S1% & 157 | ELSE IF S$<>"" THEN GOSUB 1600 & 158 | ELSE S1%=FNE%("Missing symbol") 159 | 1670 O%=0% & 160 | \ RETURN 161 | 1680 ! -- Get opcode subscript -- 162 | 1690 X1$=CVT$$(MID(L$,D1%+1%,D2%-D1%),8%) & 163 | \ RETURN IF X1$=O$(O%) FOR O%=0% TO N% & 164 | \ O%=FNE%("Inv opc "+X1$) & 165 | \ RETURN 166 | 1700 ! -- Get byte count and output to workfile -- 167 | 1710 IF O%>46% THEN GOSUB 1770 & 168 | ELSE IF O%>22% THEN N2%=1% & 169 | ELSE IF O%>0% THEN N2%=2% & 170 | ELSE N2%=0% 171 | 1720 PRINT #3%,N1%;",";N2%;",";O%;",";F1% & 172 | \ PRINT #3%,A$ & 173 | \ N0%=N0%+N2% & 174 | \ N1%=N1%+N2% & 175 | \ F1%=0% & 176 | \ RETURN 177 | 1760 ! -- Get byte count for pseudo-op -- 178 | 1770 ON O%-46% GOTO 1790, 1790, 1810, 1840, 1840 179 | 1780 ! -- .BYTE, .DBYTE -- 180 | 1790 S1%=0% \ S2%=-1% & 181 | \ FOR N2%=0% WHILE S2% & 182 | \ S1%, S2%=INSTR(S1%+1%,A$,",") & 183 | \ NEXT N2% & 184 | \ N2%=N2%*2% IF O%=48% & 185 | \ RETURN 186 | 1800 ! -- .ASCII -- 187 | 1810 S1%=INSTR(2%,A$,LEFT(A$,1%)) & 188 | \ IF S1% THEN N2%=S1%-2% & 189 | \ RETURN 190 | 1820 O%=FNE%("Missing delim") & 191 | \ RETURN 192 | 1830 ! -- .LIST, END -- 193 | 1840 N2%=0% & 194 | \ RETURN 195 | 1850 ! -- Pass 2 Driver routine -- 196 | 1860 L%,C%,F2%=0% & 197 | \ P0%=2% & 198 | \ F3%=-1% & 199 | \ PRINT #1%,"Pass 2" & 200 | \ CLOSE 1 & 201 | \ OPEN F1$ FOR OUTPUT AS FILE 1% & 202 | \ OPEN F2$ FOR INPUT AS FILE 2% & 203 | \ OPEN W$ FOR INPUT AS FILE 3% 204 | 1870 ! -- If object out then output leader and and byte count -- 205 | 1880 IF F4% THEN OPEN F4$ FOR OUTPUT AS FILE 4% & 206 | \ GOSUB 2350 & 207 | \ B%=2% & 208 | \ GOSUB 2440 & 209 | \ B%=SWAP%(N0%) AND 255% & 210 | \ GOSUB 2440 & 211 | \ B%=N0% AND 255% & 212 | \ GOSUB 2440 213 | 1890 IF F0% THEN PRINT #1% & 214 | \ PRINT #1%," Line Addr B1 B2" & 215 | \ PRINT #1% 216 | 1900 INPUT #3%,N1%,N2%,O%,F1% & 217 | \ INPUT LINE #3%, A$ & 218 | \ A$=CVT$$(A$,4%) & 219 | \ INPUT LINE #2%, L$ & 220 | \ L$=CVT$$(L$,4%) & 221 | \ L%=L%+1% 222 | 1910 ! -- Form object code and output to listing file -- 223 | 1920 IF O%=N% THEN GOSUB 1980 & 224 | \ RETURN 225 | 1930 IF O%=0% THEN GOSUB 2370 & 226 | \ GOTO 1900 227 | 1940 O1$=FNH$(N1%,0%) & 228 | \ V%=O%(O%) 229 | 1950 IF O%>46% THEN GOSUB 2140 & 230 | ELSE IF O%>25% THEN GOSUB 2120 & 231 | ELSE IF O%>22% THEN GOSUB 2100 & 232 | ELSE IF O%>14% THEN GOSUB 2080 & 233 | ELSE IF O%>8% THEN GOSUB 2030 & 234 | ELSE GOSUB 2010 235 | 1960 GOTO 1900 236 | 1970 ! -- End of assembly, tidy up -- 237 | 1980 GOSUB 2370 & 238 | \ IF F4% THEN B%=2% & 239 | \ GOSUB 2440 & 240 | \ B%=C% AND 255% & 241 | \ GOSUB 2440 & 242 | \ GOSUB 2350 243 | 1990 CLOSE 2,3,4 & 244 | \ KILL W$ & 245 | \ RETURN 246 | 2000 ! -- Memory reference -- 247 | 2010 S1%=INSTR(1%,A$,"@") & 248 | \ IF S1% THEN V%=V%+4% & 249 | \ A$=LEFT(A$,S1%-1%)+RIGHT(A$,S1%+1%) 250 | 2020 ! -- Memory reference, inc, dec and transfer -- 251 | 2030 GOSUB 2290 & 252 | \ V%=V%+P% & 253 | \ GOSUB 2250 254 | 2040 V%=FNA%(A$) & 255 | \ IF P%=0% THEN V%=V%-N1%-1% & 256 | \ IF O%>8% AND O%<13% THEN V%=V%-1% 257 | 2041 ! Quirk for wrap around within 4K page - fixed 09-Oct-2018 258 | 2042 IF V%>(4096%-127%) THEN V%=V%-4096% 259 | 2050 IF V%<-128% OR V%>127% THEN V%=FNE%("Inv disp ="+NUM$(V%)) 260 | 2060 GOSUB 2270 & 261 | \ GOSUB 2370 & 262 | \ RETURN 263 | 2070 ! -- Immediate and Delay -- 264 | 2080 GOSUB 2250 & 265 | \ V%=FNA%(A$) & 266 | \ GOSUB 2270 & 267 | \ GOSUB 2370 & 268 | \ RETURN 269 | 2090 ! -- Pointer exchange -- 270 | 2100 GOSUB 2290 & 271 | \ P%=FNA%(A$) UNLESS P% & 272 | \ V%=V%+P% 273 | 2110 ! -- Single byte -- 274 | 2120 GOSUB 2250 & 275 | \ GOSUB 2370 & 276 | \ RETURN 277 | 2130 ! -- Pseudo-ops. -- 278 | 2140 ON O%-46% GOTO 2160, 2160, 2210, 2230 279 | 2150 ! -- .BYTE, .DBYTE -- 280 | 2160 A$=A$+"," & 281 | \ FOR I%=1% TO N2% STEP O%-46% & 282 | \ O1$=FNH$(N1%+I%-1%,0%) & 283 | \ S1%=INSTR(1%,A$,",") 284 | 2170 S2%=FNA%(LEFT(A$,S1%-1%)) & 285 | \ IF O%=48% THEN V%=SWAP%(S2%) & 286 | \ GOSUB 2250 & 287 | \ V%=S2% & 288 | \ GOSUB 2270 289 | 2180 IF O%=47% THEN V%=S2% & 290 | \ GOSUB 2250 291 | 2190 GOSUB 2370 & 292 | \ A$=RIGHT(A$,S1%+1%) & 293 | \ NEXT I% & 294 | \ RETURN 295 | 2200 ! -- .ASCII -- 296 | 2210 A$=MID(A$,2%,N2%) & 297 | \ FOR I%=1% TO N2% & 298 | \ O1$=FNH$(N1%+I%-1%,0%) & 299 | \ V%=ASCII(RIGHT(A$,I%)) & 300 | \ GOSUB 2250 & 301 | \ GOSUB 2370 & 302 | \ NEXT I% & 303 | \ RETURN 304 | 2220 ! -- .LIST -- 305 | 2230 F3%=FNA%(A$) & 306 | \ RETURN 307 | 2240 ! -- Form B1 and update checksum -- 308 | 2250 O2$=FNH$(V%,3%) & 309 | \ B%=V% AND 255% & 310 | \ GOSUB 2440 IF F4% & 311 | \ C%=C%+B% & 312 | \ RETURN 313 | 2260 ! -- Form B2 and update checksum -- 314 | 2270 O3$=FNH$(V%,3%) & 315 | \ B%=V% AND 255% & 316 | \ GOSUB 2440 IF F4% & 317 | \ C%=C%+B% & 318 | \ RETURN 319 | 2280 ! -- Extract pointer from argument -- 320 | 2290 P%, S1%=0% 321 | 2300 S1%=INSTR(S1%+1%,A$,"(") & 322 | \ RETURN UNLESS S1% & 323 | \ X$=LEFT(A$,S1%-1%) & 324 | \ GOTO 2300 IF X$="H" OR X$="L" 325 | 2310 S2%=INSTR(S1%+1%,A$,")") & 326 | \ P%=FNA%(MID(A$,S1%+1%,S2%-S1%-1%)) & 327 | \ A$=LEFT(A$,S1%-1%)+RIGHT(A$,S2%+1%) 328 | 2320 IF P%<0% OR P%>3% THEN P%=FNE%("Inv ptr ="+NUM$(P%)) 329 | 2330 RETURN 330 | 2340 ! -- Output a leader to object file -- 331 | 2350 PRINT #4%,STRING$(80%,0%); & 332 | \ RETURN 333 | 2360 ! -- Output assembled code to listing file -- 334 | 2370 GOTO 2420 UNLESS F0% OR F1% 335 | 2380 IF F1% THEN PRINT #1%,"?"; ELSE PRINT #1%," "; 336 | 2390 IF F2%"" THEN PRINT #1%,CHR$(9%);L$ & 339 | ELSE PRINT #1% 340 | 2410 ! -- Set a flag, clear output strings -- 341 | 2420 F2%=L% & 342 | \ O1$,O2$,O3$,L$="" & 343 | \ RETURN 344 | 2430 ! -- Output binary byte to object file -- 345 | 2440 PRINT #4%,CHR$(B%); & 346 | \ RETURN 347 | 2450 ! -- Print error count, checksum -- 348 | 2460 PRINT #X% & 349 | \ PRINT #X%,"Errors detected";E% & 350 | \ PRINT #X%,"Source checksum ";FNH$(C%,0%) & 351 | \ PRINT #X%,"Total bytes ";N0% & 352 | \ PRINT #X% & 353 | \ RETURN 354 | 2470 ! -- Print sorted symbol table -- 355 | 2480 PRINT #1%," Symbol Table" & 356 | \ PRINT #1% 357 | 2490 ! -- Bubble sort symbol table -- 358 | 2500 S2%=-1% & 359 | \ FOR S1%=T%-1% STEP -1% WHILE S2% & 360 | \ S2%=0% & 361 | \ FOR I%=1% TO S1% 362 | 2510 IF T$(I%+1%)63% & 375 | \ NEXT I% 376 | 2550 PRINT #1% IF CCPOS(1%) & 377 | \ RETURN 378 | 2560 & 379 | ! -- Check position of char X% in L$ using -- & 380 | ! -- tables D%(). FNS%=-1% means in string -- 381 | 2570 DEF* FNS%(X%) 382 | 2580 GOTO 2600 IF D%=-1% OR X%=0% & 383 | \ FOR X0%=0% TO D% & 384 | \ GOTO 2600 IF X%<(SWAP%(D%(X0%)) AND 255%) & 385 | \ IF X%<(D%(X0%) AND 255%) THEN FNS%=-1% & 386 | \ GOTO 2610 387 | 2590 NEXT X0% 388 | 2600 FNS%=0% 389 | 2610 FNEND 390 | 2620 ! -- Evaluate the argument expression -- 391 | 2630 DEF* FNA%(X$) 392 | 2640 ! -- Main driver routine -- 393 | 2650 X3$=CVT$$(X$,136%) & 394 | \ GOSUB 2680 & 395 | \ GOSUB 2710 & 396 | \ X3%=X0% 397 | 2660 GOTO 2890 UNLESS X5% & 398 | \ X7%=X5% & 399 | \ GOSUB 2680 & 400 | \ GOSUB 2710 & 401 | \ GOSUB 2840 & 402 | \ GOTO 2660 403 | 2670 REM ! -- Scan for the next operator { ! & % + * - / } -- 404 | 2680 IF X3$="" THEN X5%,X4%=0% & 405 | \ RETURN 406 | 2690 X9%=-1% & 407 | \ FOR X4%=1% TO LEN(X3$) & 408 | \ X5%=ASCII(RIGHT(X3$,X4%)) & 409 | \ X9%= NOT X9% IF X5%=39% & 410 | \ RETURN IF X9% AND ( X5%=33% OR X5%=37% OR X5%=38% & 411 | OR X5%=42% OR X5%=43% OR X5%=45% OR X5%=47%) & 412 | \ NEXT X4% & 413 | \ X5%=0% & 414 | \ X4%=X4%+1% & 415 | \ RETURN 416 | 2700 ! -- Get value of term -- 417 | 2710 X2$=CVT$$(LEFT(X3$,X4%-1%),136%) & 418 | \ X3$=RIGHT(X3$,X4%+1%) 419 | 2720 IF X2$="" THEN X0%=0% & 420 | \ RETURN 421 | 2730 ! -- H() or L() ? -- 422 | 2740 X1$=LEFT(X2$,2%) & 423 | \ IF X1$="H(" THEN X9%=1% & 424 | ELSE IF X1$="L(" THEN X9%=2% & 425 | ELSE X9%=0% 426 | 2750 IF X9% THEN IF RIGHT(X2$,LEN(X2$))=")" THEN X2$=MID(X2$,3%,LEN(X2$)-3%) & 427 | ELSE 2820 428 | 2760 ! -- Hex or Dec number ? -- & 429 | ! -- Ascii character ? -- & 430 | ! -- Current LC (".") ? -- & 431 | ! -- or Symbol ? -- & 432 | 433 | 2770 IF X1$="X'" THEN X0%=FND%(RIGHT(X2$,3%)) & 434 | \ GOTO 2800 435 | 2780 X1$=LEFT(X2$,1%) 436 | 2790 IF X1$="0" THEN X0%=FND%(RIGHT(X2$,2%)) & 437 | ELSE IF X1$>="1" AND X1$<="9" THEN X0%=VAL(X2$) & 438 | ELSE IF X1$>="A" AND X1$<="Z" THEN X0%=FNV%(X2$) & 439 | ELSE IF X1$="'" THEN X0%=ASCII(RIGHT(X2$,2%)) & 440 | ELSE IF X2$="." THEN X0%=N1% & 441 | ELSE 2820 442 | 2800 IF X9%=1% THEN X0%=SWAP%(X0%) AND 255% & 443 | ELSE IF X9%=2% THEN X0%=X0% AND 255% 444 | 2810 RETURN 445 | 2820 X0%=FNE%("Inv term = "+X2$) & 446 | \ RETURN 447 | 2830 ! -- Carry out the arithmetic or logical operation -- 448 | 2840 IF X7%>38% THEN 2860 & 449 | ELSE IF X7%=33% THEN X3%=X3% OR X0% & 450 | ELSE IF X7%=37% THEN X3%=X3%+(NOT X0%) & 451 | ELSE IF X7%=38% THEN X3%=X3% AND X0% 452 | 2850 RETURN 453 | 2860 IF X7%=42% THEN X3%=X3%*X0% & 454 | ELSE IF X7%=43% THEN X3%=X3%+X0% & 455 | ELSE IF X7%=45% THEN X3%=X3%-X0% & 456 | ELSE IF X7%=47% THEN X3%=X3%/X0% 457 | 2870 RETURN 458 | 2880 ! -- Exit with value of expression -- 459 | 2890 FNA%=X3% 460 | 2900 FNEND 461 | 2905 ! -- Print the given error message to the listing file 462 | 2906 DEF* FNE%(X$) & 463 | \ PRINT #1%,X$; & 464 | \ IF P0%=1% THEN PRINT #1%," at line";L% ELSE PRINT #1% 465 | 2907 E%=E%+1% & 466 | \ F1%=-1% & 467 | \ FNE%=0% & 468 | \ FNEND 469 | 2910 ! -- Look up value of symbol -- 470 | 2920 DEF* FNV%(X$) 471 | 2930 GOTO 2940 IF X$=T$(X%) FOR X%=1% TO T% & 472 | \ FNV%=FNE%("Undef sym = "+X$) & 473 | \ GOTO 2950 474 | 2940 FNV%=T%(X%) 475 | 2950 FNEND 476 | 2960 ! -- Dec to Hex conversion -- 477 | 2970 DEF* FNH$(X%,D%) 478 | 2980 X$="" & 479 | \ FOR X1%=0% TO 3% & 480 | \ X0%=(X% AND (16%^(X1%+1%)-1%*(16%^X1%)))/(16%^X1%) & 481 | \ X0%=X0%+16% IF X0%<0% & 482 | \ X$=CHR$(48%+X0%)+X$ IF X0%<10% & 483 | \ X$=CHR$(55%+X0%)+X$ IF X0%>9% & 484 | \ NEXT X1% & 485 | \ IF D% THEN X$=MID(X$,D%,2%) 486 | 2990 FNH$=X$ 487 | 3000 FNEND 488 | 3010 ! -- Hex to Dec conversion -- 489 | 3020 DEF* FND%(X$) & 490 | \ X0%=0% & 491 | \ FOR X1%=1% TO LEN(X$) & 492 | \ X2%=ASCII(MID(X$,X1%,1%)) & 493 | \ IF X2%<48% OR (X2%>57% AND X2%<65%) OR X2%>70% THEN & 494 | FND%=FNE%("Inv Hex const = "+X$) & 495 | \ GOTO 3040 496 | 3030 X2%=X2%-48% & 497 | \ X2%=X2%-7% IF X2%>9% & 498 | \ X0%=X2%+X0%*16% & 499 | \ NEXT X1% & 500 | \ FND%=X0% 501 | 3040 FNEND 502 | 30000 ! CCL Entry point 503 | 30010 F2$=CVT$$(SYS(CHR$(7%)),188%) & 504 | \ I%=INSTR(1%,F2$,"SCMPCA") & 505 | \ IF I% THEN F2$=RIGHT(F2$,7%) & 506 | ELSE PRINT "?SCMPCA - Illegal entry" & 507 | \ GOTO 32767 508 | 30020 C9%=-1% & 509 | \ GOTO 1050 510 | 31000 ! -- Error routine -- 511 | 31010 ! -- No "END" -- 512 | 31020 IF ERR=11% AND ERL=1320% THEN O%=N%+FNE%("Missing END") & 513 | \ RESUME 1450 514 | 31030 IF ERR=11% AND ERL=1900% THEN L$="" & 515 | \ RESUME 1920 516 | 31040 ! -- ^Z at filename request -- 517 | 31050 RESUME 32767 IF ERL=1110% 518 | 31060 ! -- Illegal number in FNA%() -- 519 | 31070 IF ERR=51% AND ERL=2790% THEN X0%=VAL(X2$)-65536 & 520 | \ RESUME 2800 521 | 31080 RESUME 2820 IF ERR=52% AND ERL=2790% 522 | 31090 CLOSE 1,2,3 & 523 | \ KILL W$ IF LINE>=1310% & 524 | \ RESUME 32767 IF ERR=28% 525 | 31100 ! -- Print any unanticipated error -- 526 | 31110 ON ERROR GOTO 0 527 | 32000 ! -- Opcode data -- 528 | 32010 DATA "",0 529 | 32020 ! Memory reference 1-8 530 | 32030 DATA LD,192,ST,200,AND,208,OR,216,XOR,224,DAD,232,ADD,240,CAD,248 531 | 32040 ! Transfer 9-12 532 | 32050 DATA JMP,144,JP,148,JZ,152,JNZ,156 533 | 32060 ! Memory inc,dec 13-14 534 | 32070 DATA ILD,168,DLD,184 535 | 32080 ! Immediate 15-21 536 | 32090 DATA LDI,196,ANI,212,ORI,220,XRI,228,DAI,236,ADI,244,CAI,252 537 | 32100 ! Delay 22 538 | 32110 DATA DLY,143 539 | 32120 ! Pointer 23-25 540 | 32130 DATA XPAL,48,XPAH,52,XPPC,60 541 | 32140 ! Extension 26-33 542 | 32150 DATA LDE,64,XAE,1,ANE,80,ORE,88,XRE,96,DAE,104,ADE,112,CAE,120 543 | 32160 ! SIO, Shift, Rotate 34-38 544 | 32170 DATA SIO,25,SR,28,SRL,29,RR,30,RRL,31 545 | 32180 ! Miscellaneous 39-46 546 | 32190 DATA HALT,0,CCL,2,SCL,3,IEN,5,DINT,4,CSA,6,CAS,7,NOP,8 547 | 32200 ! Assembler pseudo-ops 47-51 548 | 32210 DATA .BYTE,0,.DBYTE,0,.ASCII,0,.LIST,0,END,0 549 | 32767 END 550 | -------------------------------------------------------------------------------- /micros/SCMPCA.TSK: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/micros/SCMPCA.TSK -------------------------------------------------------------------------------- /micros/X65.B2S: -------------------------------------------------------------------------------- 1 | 1000 REM & 2 | REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! & 3 | REM !! !! & 4 | REM !! 6502 Cross Assembler !! & 5 | REM !! !! 6 | 1010 REM !! A.G. Nicholson, Newcastle Uni . !! & 7 | REM !! !! & 8 | REM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! & 9 | 10 | 1020 REM & 11 | REM ! Version of 26-Nov-79 & 12 | 13 | 1030 EXTEND 14 | 1040 DIM SYMBOLS$(767%), & 15 | VALUES%(767%), & 16 | FLAGS%(767%), & 17 | SYMBOL.CHARS%(6%), & 18 | DELIMITER.TABLE%(3%) 19 | 1050 ! -- Set up error trap routine -- 20 | 1060 ON ERROR GOTO 31020 & 21 | \ X$=SYS(CHR$(6%)+CHR$(-7%)) 22 | 1070 ! -- Initialise -- 23 | 1080 NUMBER.OF.SYMBOLS%=0% & 24 | \ SYMBOL.TABLE.SIZE%=768% & 25 | \ START.CPU.TIME%=TIME(1%) & 26 | \ LISTING.FILE$="KB:" 27 | 1090 FOR I%=1% TO 65% & 28 | \ READ SYMBOL$,VALUE%,FLAG.WORD% & 29 | \ GOSUB 2490 & 30 | \ NEXT I% & 31 | ! Read in opcodes 32 | 1100 ! -- Print header -- 33 | 1110 OPEN LISTING.FILE$ AS FILE 1% & 34 | \ PRINT #1%,"6502 Cross assembler" & 35 | \ PRINT #1%,"#"; 36 | 1120 ! & 37 | 38 | 1130 ! -- Get listing, source filenames -- 39 | 1140 INPUT LINE #1%, SOURCE.FILE$ & 40 | \ SOURCE.FILE$=CVT$$(SOURCE.FILE$,-1%) 41 | 1150 ! -- Check for errors only switch -- 42 | 1160 ERRORS.ONLY.SWITCH%=-1% & 43 | \ I%=INSTR(1%,SOURCE.FILE$,"/E") & 44 | \ IF I% THEN SOURCE.FILE$=LEFT(SOURCE.FILE$,I%-1%)+ & 45 | RIGHT(SOURCE.FILE$,I%+2%) & 46 | \ ERRORS.ONLY.SWITCH%=0% 47 | 1170 ! -- Check for symbol table listing switch -- 48 | 1180 SYMBOL.TABLE.LIST.FLAG%=INSTR(1%,SOURCE.FILE$,"/S") & 49 | \ IF SYMBOL.TABLE.LIST.FLAG% THEN SOURCE.FILE$= & 50 | LEFT(SOURCE.FILE$,SYMBOL.TABLE.LIST.FLAG%-1%)+ & 51 | RIGHT(SOURCE.FILE$,SYMBOL.TABLE.LIST.FLAG%+2%) 52 | 1190 ! -- Check for object module output switch -- 53 | 1200 OBJECT.OUT.FLAG%=0% & 54 | \ I%=INSTR(1%,SOURCE.FILE$,"/O") & 55 | \ IF I% THEN SOURCE.FILE$=LEFT(SOURCE.FILE$,I%-1%)+ & 56 | RIGHT(SOURCE.FILE$,I%+2%) & 57 | \ OBJECT.OUT.FLAG%=-1% 58 | 1210 ! -- Check for listing file and add default extensions -- 59 | 1220 LISTING.TO.FILE.FLAG%=INSTR(1%,SOURCE.FILE$,"=") & 60 | \ IF LISTING.TO.FILE.FLAG% THEN LISTING.FILE$= & 61 | LEFT(SOURCE.FILE$,LISTING.TO.FILE.FLAG%-1%) & 62 | \ LISTING.FILE$=LISTING.FILE$+".LST" UNLESS & 63 | INSTR(1%,LISTING.FILE$,".") & 64 | \ SOURCE.FILE$=RIGHT(SOURCE.FILE$, & 65 | LISTING.TO.FILE.FLAG%+1%) 66 | 1230 SOURCE.FILE$=SOURCE.FILE$+".SRC" UNLESS & 67 | INSTR(1%,SOURCE.FILE$,".") 68 | 1240 PRINT #1%,"Listing output to "+ & 69 | LISTING.FILE$ IF LISTING.TO.FILE.FLAG% 70 | 1250 IF OBJECT.OUT.FLAG% THEN OBJECT.FILE$= & 71 | LEFT(SOURCE.FILE$,INSTR(1%,SOURCE.FILE$,"."))+"HEX" & 72 | \ PRINT #1%,"Object module to ";OBJECT.FILE$ 73 | 1260 ! -- Get a unique workfile name -- 74 | 1270 WORK.FILE$="X65X"+MID(NUM$(100%+ASCII(SYS(CHR$(6%)+ & 75 | CHR$(9%)))/2%),3%,2%)+".TMP" 76 | 1280 ! -- Commence assembly -- 77 | 1290 GOSUB 2010 & 78 | \ GOSUB 3010 & 79 | \ X%=1% & 80 | \ GOSUB 3630 81 | 1300 ! -- Print symbol table -- 82 | 1310 GOSUB 3660 IF SYMBOL.TABLE.LIST.FLAG% & 83 | \ PRINT #1% 84 | 1320 ! -- Finish up and exit -- 85 | 1330 CLOSE 1% & 86 | \ IF LISTING.TO.FILE.FLAG% THEN X%=0% & 87 | \ GOSUB 3630 88 | 1340 PRINT "Runtime was";(TIME(1%)-START.CPU.TIME%)/10;"sec" & 89 | \ GOTO 32767 90 | 1350 ! & 91 | 92 | 2000 & 93 | ! -- Pass 1 Driver routine -- & 94 | 95 | 2010 ERROR.COUNT%, & 96 | TOTAL.BYTES%, & 97 | LOCATION.COUNTER%, & 98 | ERROR.LINE.FLAG%, & 99 | OPCODE.TABLE.SUBSCRIPT%=0% & 100 | \ PASS.NUMBER%=1% & 101 | \ OPEN SOURCE.FILE$ FOR INPUT AS FILE 2% & 102 | \ OPEN WORK.FILE$ FOR OUTPUT AS FILE 3% & 103 | \ PRINT #1%,"Pass 1" 104 | 2020 INPUT LINE #2%,SOURCE.LINE$ & 105 | \ SOURCE.LINE$=CVT$$(SOURCE.LINE$,421%) & 106 | \ LINE.LENGTH%=LEN(SOURCE.LINE$) & 107 | \ LINE.NUMBER%=LINE.NUMBER%+1% 108 | 2030 IF LINE.LENGTH%=0% OR LEFT(SOURCE.LINE$,1%)="$" THEN & 109 | OPCODE.TABLE.SUBSCRIPT%=-1% & 110 | \ GOTO 2150 111 | 2040 ! -- Scan source line -- 112 | 2050 GOSUB 2360 & 113 | \ GOSUB 2410 114 | 2060 ! -- Comment line ? -- 115 | 2070 IF COMMENT.DELIMITER%=1% THEN & 116 | OPCODE.TABLE.SUBSCRIPT%=-1% & 117 | \ GOTO 2150 118 | 2080 ! -- Get argument field -- 119 | 2090 IF COMMENT.DELIMITER% THEN ARGUMENT$= & 120 | CVT$$(MID(SOURCE.LINE$,OPCODE.DELIMITER%+1%, & 121 | COMMENT.DELIMITER%-OPCODE.DELIMITER%-1%),258%) & 122 | ELSE ARGUMENT$=CVT$$(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%+1%),258%) 123 | 2100 ! -- Label ? -- 124 | 2110 IF LABEL.DELIMITER% THEN SYMBOL$= & 125 | CVT$$(LEFT(SOURCE.LINE$,LABEL.DELIMITER%-1%),128%) & 126 | \ VALUE%=LOCATION.COUNTER% & 127 | \ FLAG.WORD%=-2% & 128 | \ GOSUB 2490 129 | 2120 ! -- Assignment ? -- 130 | 2130 IF EQU.DELIMITER% THEN GOSUB 2560 & 131 | ELSE GOSUB 2610 132 | 2140 ! -- Write to workfile -- 133 | 2150 GOSUB 2770 & 134 | \ GOTO 2020 IF OPCODE.TABLE.SUBSCRIPT%=-1% & 135 | \ GOTO 2020 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)<>1% 136 | 2160 CLOSE 2%,3% & 137 | \ RETURN & 138 | ! -- End of Pass 1 139 | 2170 ! & 140 | 141 | 2180 & 142 | ! -- Determine the addressing mode & 143 | ! -- and the number of bytes for this opcode & 144 | 145 | 2190 OP.TYPE%=SWAP%(VALUES%(OPCODE.TABLE.SUBSCRIPT%)) AND 255% 146 | 2200 IF OP.TYPE%=0% THEN BYTE.COUNT%=1% & 147 | \ TEMP1%=FNERROR.PRINT%("No argument required") & 148 | IF ARGUMENT$<>"" & 149 | \ RETURN 150 | 2210 IF OP.TYPE%=1% THEN BYTE.COUNT%=2% & 151 | \ RETURN & 152 | ! relative branch 153 | 2220 IF OP.TYPE%=2% THEN BYTE.COUNT%=3% & 154 | \ RETURN & 155 | ! transfer 156 | 2230 ARG.LENGTH%=LEN(ARGUMENT$) & 157 | \ IF ARG.LENGTH%=0% THEN BYTE.COUNT%=FNERROR.PRINT%( & 158 | "Missing argument") & 159 | \ OPCODE.TABLE.SUBSCRIPT%=-1% & 160 | \ RETURN 161 | 2240 TEMP2$=MID(ARGUMENT$,ARG.LENGTH%-2%,3%) & 162 | \ TEMP3$=LEFT(ARGUMENT$,1%) & 163 | \ IF TEMP2$=",X)" AND TEMP3$="(" THEN ADDR.MODE%=0% & 164 | \ ARGUMENT$=MID(ARGUMENT$,2%,ARG.LENGTH%-4%) & 165 | \ BYTE.COUNT%=2% & 166 | \ RETURN & 167 | ! (ind ,X) 168 | 2250 IF TEMP2$="),Y" AND TEMP3$="(" THEN ADDR.MODE%=16% & 169 | \ ARGUMENT$=MID(ARGUMENT$,2%,ARG.LENGTH%-4%) & 170 | \ BYTE.COUNT%=2% & 171 | \ RETURN & 172 | ! (ind),Y 173 | 2260 IF TEMP3$="#" THEN ADDR.MODE%=8% & 174 | \ ARGUMENT$=RIGHT(ARGUMENT$,2%) & 175 | \ BYTE.COUNT%=2% & 176 | \ RETURN & 177 | ! # 178 | 2270 IF ARGUMENT$="A" THEN ADDR.MODE%=8% & 179 | \ BYTE.COUNT%=1% & 180 | \ RETURN & 181 | ! A 182 | 2280 TEMP2$=RIGHT(TEMP2$,2%) & 183 | \ IF OP.TYPE%>7% AND TEMP2$=",Y" THEN TEMP2$=",X" & 184 | \ GOTO 2300 & 185 | ! Convert ',Y' to ',X' for idx store and load 186 | 2290 IF TEMP2$=",Y" THEN ADDR.MODE%=24% & 187 | \ ARGUMENT$=LEFT(ARGUMENT$,ARG.LENGTH%-2%) & 188 | \ BYTE.COUNT%=3% & 189 | \ RETURN & 190 | ! abs,Y 191 | 2300 IF TEMP2$<>",X" THEN 2320 & 192 | ELSE ARGUMENT$=LEFT(ARGUMENT$,ARG.LENGTH%-2%) & 193 | \ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) & 194 | \ IF UNDEFINED.SYMBOL% OR ( VALUE% AND -256% ) THEN & 195 | ADDR.MODE%=28% & 196 | \ BYTE.COUNT%=3% & 197 | \ RETURN & 198 | ! abs,X 199 | 2310 ADDR.MODE%=20% & 200 | \ BYTE.COUNT%=2% & 201 | \ RETURN & 202 | ! z page,X 203 | 2320 VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) & 204 | \ IF UNDEFINED.SYMBOL% OR ( VALUE% AND -256% ) THEN & 205 | ADDR.MODE%=12% & 206 | \ BYTE.COUNT%=3% & 207 | \ RETURN & 208 | ! abs 209 | 2330 ADDR.MODE%=4% & 210 | \ BYTE.COUNT%=2% & 211 | \ RETURN & 212 | ! zero page 213 | 2340 ! & 214 | 215 | 2350 & 216 | ! -- Scan for strings in SOURCE.LINE$ -- & 217 | 218 | 2360 DELIMITER%=-1% & 219 | \ TEMP2%=0% 220 | 2370 TEMP1%=INSTR(TEMP2%+1%,SOURCE.LINE$,"'") & 221 | \ RETURN UNLESS TEMP1% 222 | 2380 TEMP2%=INSTR(TEMP1%+1%,SOURCE.LINE$,"'") & 223 | \ IF TEMP2% THEN DELIMITER%=DELIMITER%+1% & 224 | \ IF DELIMITER%<4% THEN DELIMITER.TABLE%(DELIMITER%)= & 225 | SWAP%(TEMP1% AND 255%) OR (TEMP2% AND 255%) & 226 | \ GOTO 2370 227 | 2390 RETURN 228 | 2400 & 229 | ! -- Search for token delimiters -- & 230 | ! LABEL.DELIMITER% Label & 231 | ! OPCODE.DELIMITER% Opcode & 232 | ! COMMENT.DELIMITER% Comment & 233 | ! EQU.DELIMITER% Assignment & 234 | 235 | 2410 LABEL.DELIMITER%=INSTR(1%,SOURCE.LINE$,":") & 236 | \ LABEL.DELIMITER%=0% IF FNCHECK.SYNTAX%(LABEL.DELIMITER%) & 237 | \ COMMENT.DELIMITER%=0% 238 | 2420 COMMENT.DELIMITER%=INSTR(COMMENT.DELIMITER%+1%,SOURCE.LINE$,";") & 239 | \ GOTO 2420 IF FNCHECK.SYNTAX%(COMMENT.DELIMITER%) & 240 | \ LABEL.DELIMITER%=0% IF (LABEL.DELIMITER%> & 241 | COMMENT.DELIMITER% AND COMMENT.DELIMITER%<>0%) & 242 | \ OPCODE.DELIMITER%=LABEL.DELIMITER% 243 | 2430 OPCODE.DELIMITER%=OPCODE.DELIMITER%+1% & 244 | \ IF OPCODE.DELIMITER%>=LINE.LENGTH% THEN 2450 & 245 | ELSE X%=ASCII(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%)) & 246 | \ IF X%=9% OR X%=32% THEN 2430 247 | 2440 OPCODE.DELIMITER%=OPCODE.DELIMITER%+1% & 248 | \ IF OPCODE.DELIMITER%9% AND X%<>32% THEN 2440 & 251 | ELSE OPCODE.DELIMITER%=OPCODE.DELIMITER%-1% 252 | 2450 EQU.DELIMITER%=INSTR(1%,SOURCE.LINE$,"=") & 253 | \ EQU.DELIMITER%=0% IF FNCHECK.SYNTAX%(EQU.DELIMITER%) OR & 254 | (EQU.DELIMITER%>COMMENT.DELIMITER% AND & 255 | COMMENT.DELIMITER%<>0%) & 256 | \ OPCODE.DELIMITER%=EQU.DELIMITER% IF EQU.DELIMITER% 257 | 2460 OPCODE.DELIMITER%=COMMENT.DELIMITER%-1% IF & 258 | (OPCODE.DELIMITER%>=COMMENT.DELIMITER% AND & 259 | COMMENT.DELIMITER%<>0%) & 260 | \ RETURN 261 | 2470 ! & 262 | 263 | 2480 & 264 | ! Enter symbol SYMBOL$ into symbol table & 265 | ! and its value VALUE% & 266 | 267 | 2490 IF NUMBER.OF.SYMBOLS%=SYMBOL.TABLE.SIZE% THEN & 268 | VALUE%=FNERROR.PRINT%("?X65 - FATAL: Symbol table overflow") & 269 | \ STOP & 270 | ! Symbol table full 271 | 2500 X%=ASCII(SYMBOL$) & 272 | \ IF X%<>46% AND ( X%<65% OR X%>90% ) THEN & 273 | VALUE%=FNERROR.PRINT%("Invalid symbol = "+SYMBOL$) & 274 | \ RETURN & 275 | ! Invalid symbol 276 | 2510 TEMP2%=FNHASH.SYMBOL%(SYMBOL$,SYMBOL.TABLE.SIZE%) & 277 | ! Hash symbol 278 | 2520 IF SYMBOLS$(TEMP2%)="" THEN SYMBOLS$(TEMP2%)=SYMBOL$ & 279 | \ VALUES%(TEMP2%)=VALUE% & 280 | \ FLAGS%(TEMP2%)=FLAG.WORD% & 281 | \ NUMBER.OF.SYMBOLS%=NUMBER.OF.SYMBOLS%+1% & 282 | \ RETURN & 283 | ! If slot empty, enter symbol, value and flagword 284 | 2530 IF SYMBOLS$(TEMP2%)=SYMBOL$ AND FLAGS%(TEMP2%)<0% THEN & 285 | VALUE%=FNERROR.PRINT%("Redefined symbol = "+SYMBOL$) & 286 | \ RETURN & 287 | ! Multiple definition not allowed 288 | 2540 TEMP2%=FNREHASH.SYMBOL%(TEMP2%,SYMBOL.TABLE.SIZE%) & 289 | \ GOTO 2520 290 | 2550 & 291 | ! -- Enter assignment -- & 292 | 293 | 2560 SYMBOL$=CVT$$(MID(SOURCE.LINE$,LABEL.DELIMITER%+1%, & 294 | EQU.DELIMITER%-LABEL.DELIMITER%-1%),136%) & 295 | \ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) & 296 | \ IF UNDEFINED.SYMBOL% THEN VALUE%= & 297 | FNERROR.PRINT%("Undefined value") 298 | 2570 IF SYMBOL$="." THEN LOCATION.COUNTER%=VALUE% & 299 | ELSE IF SYMBOL$="" THEN VALUE%= & 300 | FNERROR.PRINT%("Missing symbol") & 301 | ELSE FLAG.WORD%=-1% & 302 | \ GOSUB 2490 303 | 2580 OPCODE.TABLE.SUBSCRIPT%=-1% & 304 | \ RETURN 305 | 2590 ! & 306 | 307 | 2600 & 308 | ! -- Get opcode subscript -- & 309 | 310 | 2610 OPCODE$=CVT$$(MID(SOURCE.LINE$,LABEL.DELIMITER%+1%, & 311 | OPCODE.DELIMITER%-LABEL.DELIMITER%),8%) & 312 | \ IF OPCODE$<>"" THEN OPCODE.TABLE.SUBSCRIPT%= & 313 | FNHASH.SYMBOL%(OPCODE$,SYMBOL.TABLE.SIZE%) & 314 | ELSE OPCODE.TABLE.SUBSCRIPT%=-1% \ RETURN 315 | 2620 IF SYMBOLS$(OPCODE.TABLE.SUBSCRIPT%)=OPCODE$ THEN RETURN & 316 | ELSE IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)<0% OR & 317 | SYMBOLS$(OPCODE.TABLE.SUBSCRIPT%)="" THEN & 318 | OPCODE.TABLE.SUBSCRIPT%= & 319 | FNERROR.PRINT%("Invalid opcode = "+OPCODE$)-1% & 320 | ELSE OPCODE.TABLE.SUBSCRIPT%= & 321 | FNREHASH.SYMBOL%(OPCODE.TABLE.SUBSCRIPT%, & 322 | SYMBOL.TABLE.SIZE%) & 323 | \ GOTO 2620 & 324 | ! Check for opcode match in the symbol table & 325 | ! If flagword < 0 then report an error else rehash 326 | 2630 RETURN 327 | 2640 & 328 | ! -- Get address mode and check for validity & 329 | 330 | 2650 GOSUB 2190 & 331 | \ RETURN IF OP.TYPE%<3% & 332 | ! O.K. if single byte, branch or transfer 333 | 2660 ON OP.TYPE%-2% GOTO & 334 | 2670, 2680, 2690, 2700, & 335 | 2710, 2720, 2730 & 336 | ! shift accum bit idx cmp & 337 | ! inc/dec load idx store idx 338 | 2670 RETURN IF ( ADDR.MODE%=8% AND ARGUMENT$="A" ) & 339 | OR ADDR.MODE%=4% OR ADDR.MODE%=20% & 340 | OR ADDR.MODE%=12% OR ADDR.MODE%=28% & 341 | \ GOTO 2740 342 | 2680 RETURN 343 | 2690 RETURN IF ADDR.MODE%=4% OR ADDR.MODE%=12% & 344 | \ GOTO 2740 345 | 2700 RETURN IF ADDR.MODE%>0% AND ADDR.MODE%<16% & 346 | \ GOTO 2740 347 | 2710 RETURN IF ADDR.MODE%=4% OR ADDR.MODE%=20% & 348 | OR ADDR.MODE%=12% OR ADDR.MODE%=28% & 349 | \ GOTO 2740 350 | 2720 RETURN UNLESS ADDR.MODE%=0% OR ADDR.MODE%=16% & 351 | OR ADDR.MODE%=24% & 352 | \ GOTO 2740 353 | 2730 RETURN IF ADDR.MODE%=4% OR ADDR.MODE%=12% & 354 | OR ADDR.MODE%=20% 355 | 2740 OPCODE.TABLE.SUBSCRIPT%=FNERROR.PRINT%( & 356 | "Illegal addressing mode")-1% & 357 | \ RETURN 358 | 2750 ! & 359 | 360 | 2760 & 361 | ! -- Get byte count and output to workfile -- & 362 | 363 | 2770 IF OPCODE.TABLE.SUBSCRIPT%=-1% THEN BYTE.COUNT%=0% & 364 | ELSE IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)>0% THEN & 365 | GOSUB 2800 & 366 | ELSE GOSUB 2650 & 367 | ! Get byte count into BYTE.COUNT% 368 | 2780 PRINT #3%,LOCATION.COUNTER%;","; & 369 | BYTE.COUNT%;","; & 370 | OPCODE.TABLE.SUBSCRIPT%;","; & 371 | ADDR.MODE%;","; & 372 | ERROR.LINE.FLAG% & 373 | \ PRINT #3%,ARGUMENT$ & 374 | \ TOTAL.BYTES%=TOTAL.BYTES%+BYTE.COUNT% & 375 | \ LOCATION.COUNTER%=LOCATION.COUNTER%+BYTE.COUNT% & 376 | \ ERROR.LINE.FLAG%=0% & 377 | \ RETURN 378 | 2790 & 379 | ! -- Get byte count for pseudo-op -- & 380 | 381 | 2800 ON FLAGS%(OPCODE.TABLE.SUBSCRIPT%) & 382 | GOTO 2890, 2820, 2820, 2820, & 383 | 2840, 2840, 2840, 2870, & 384 | 2890 & 385 | ! .END .BYTE .DBYTE .WORD & 386 | ! .ASCII .ASCIP .ASCIZ .BLKB & 387 | ! .LIST 388 | 2810 ! -- .BYTE, .DBYTE, .WORD -- 389 | 2820 TEMP1%=0% & 390 | \ TEMP2%=-1% & 391 | \ FOR BYTE.COUNT%=0% WHILE TEMP2% & 392 | \ TEMP1%,TEMP2%=INSTR(TEMP1%+1%,ARGUMENT$,",") & 393 | \ NEXT BYTE.COUNT% & 394 | \ BYTE.COUNT%=BYTE.COUNT%*2% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=3% & 395 | OR FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=4% & 396 | \ RETURN 397 | 2830 ! -- .ASCII, .ASCIP, .ASCIZ -- 398 | 2840 TEMP1%=INSTR(2%,ARGUMENT$,LEFT(ARGUMENT$,1%)) & 399 | \ IF TEMP1%=0% THEN OPCODE.TABLE.SUBSCRIPT%= & 400 | FNERROR.PRINT%("Missing delimiter")-1% & 401 | ELSE BYTE.COUNT%=TEMP1%-2% 402 | 2850 BYTE.COUNT%=BYTE.COUNT%+1% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=7% & 403 | \ RETURN 404 | 2860 ! -- .BLKB 405 | 2870 BYTE.COUNT%=FNEVALUATE.EXPR%(ARGUMENT$) & 406 | \ RETURN 407 | 2880 ! -- .LIST, .END -- 408 | 2890 BYTE.COUNT%=0% & 409 | \ RETURN 410 | 2900 ! & 411 | 412 | 3000 & 413 | ! -- Pass 2 Driver routine -- & 414 | 415 | 3010 LINE.NUMBER%, & 416 | CHECKSUM%, & 417 | NEW.LINE.FLAG%=0% & 418 | \ PASS.NUMBER%=2% & 419 | \ LIST.FLAG%=-1% & 420 | \ PRINT #1%,"Pass 2" & 421 | \ CLOSE 1% & 422 | \ OPEN LISTING.FILE$ FOR OUTPUT AS FILE 1% & 423 | \ OPEN SOURCE.FILE$ FOR INPUT AS FILE 2% & 424 | \ OPEN WORK.FILE$ FOR INPUT AS FILE 3% & 425 | \ KILL WORK.FILE$ 426 | 3020 IF OBJECT.OUT.FLAG% THEN & 427 | OPEN OBJECT.FILE$ FOR OUTPUT AS FILE 4% & 428 | \ NEW.OBJ.LINE%=0% 429 | 3030 IF ERRORS.ONLY.SWITCH% THEN PRINT #1%," Line Addr B1 B2 B3" & 430 | \ PRINT #1% 431 | 3040 INPUT #3%,LOCATION.COUNTER%, & 432 | BYTE.COUNT%, & 433 | OPCODE.TABLE.SUBSCRIPT%, & 434 | ADDR.MODE%, & 435 | ERROR.LINE.FLAG% & 436 | \ INPUT LINE #3%, ARGUMENT$ & 437 | \ ARGUMENT$=CVT$$(ARGUMENT$,4%) & 438 | \ INPUT LINE #2%, SOURCE.LINE$ & 439 | \ SOURCE.LINE$=CVT$$(SOURCE.LINE$,4%) & 440 | \ LINE.NUMBER%=LINE.NUMBER%+1% 441 | 3050 ! -- Form object code and output to listing file -- 442 | 3060 IF LEFT(SOURCE.LINE$,1%)="$" THEN & 443 | SOURCE.LINE$=RIGHT(SOURCE.LINE$,2%) 444 | 3070 IF OPCODE.TABLE.SUBSCRIPT%=-1% THEN GOSUB 3540 & 445 | \ GOTO 3040 446 | 3080 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=1% THEN & 447 | GOSUB 3130 & 448 | \ RETURN 449 | 3090 ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%,0%) & 450 | \ VALUE%=VALUES%(OPCODE.TABLE.SUBSCRIPT%) & 451 | \ FLAG.WORD%=SWAP%(VALUE%) AND 255% & 452 | \ VALUE%=VALUE% AND 255% 453 | 3100 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)>0% THEN GOSUB 3260 & 454 | ELSE IF FLAG.WORD% THEN GOSUB 3170 & 455 | ELSE GOSUB 3450 & 456 | \ GOSUB 3540 457 | 3110 GOTO 3040 458 | 3120 & 459 | ! -- End of assembly, tidy up -- & 460 | 461 | 3130 GOSUB 3540 & 462 | \ PRINT #4% IF OBJECT.OUT.FLAG% 463 | 3140 CLOSE 2%,3%,4% & 464 | \ RETURN 465 | 3150 ! & 466 | 467 | 3160 & 468 | ! -- Process operands -- & 469 | 470 | 3170 IF FLAG.WORD%=1% THEN GOSUB 3450 & 471 | \ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$)-LOCATION.COUNTER%-2% & 472 | \ VALUE%=FNERROR.PRINT%("Invalid displacement ="+NUM$(VALUE%)) & 473 | IF VALUE%<-128% OR VALUE%>127% & 474 | \ GOSUB 3470 & 475 | \ GOTO 3540 & 476 | ! relative branch 477 | 3180 IF FLAG.WORD%<>2% THEN 3200 & 478 | ELSE ARG.LENGTH%=LEN(ARGUMENT$) & 479 | \ IF LEFT(ARGUMENT$,1%)="(" AND & 480 | RIGHT(ARGUMENT$,ARG.LENGTH%)=")" AND & 481 | VALUE%=76% THEN VALUE%=VALUE%+32% & 482 | \ ARGUMENT$=MID(ARGUMENT$,2%,ARG.LENGTH%-2%) & 483 | ! JMP ( ) 484 | 3190 GOSUB 3450 & 485 | \ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) & 486 | \ GOSUB 3470 & 487 | \ GOTO 3230 & 488 | ! transfer 489 | 3200 IF FLAG.WORD%=6% THEN & 490 | ADDR.MODE%=0% IF ADDR.MODE%=8% & 491 | ! kludge for compare idx 492 | 3210 IF FLAG.WORD%=8% THEN & 493 | ADDR.MODE%=ADDR.MODE%+4% & 494 | \ ADDR.MODE%=4% IF ADDR.MODE%=12% & 495 | ! kludge for load idx 496 | 3220 VALUE%=VALUE%+ADDR.MODE% & 497 | \ GOSUB 3450 & 498 | \ GOTO 3540 IF BYTE.COUNT%=1% & 499 | \ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) & 500 | \ GOSUB 3470 & 501 | \ GOTO 3540 IF BYTE.COUNT%=2% 502 | 3230 VALUE%=SWAP%(VALUE%) & 503 | \ GOSUB 3490 & 504 | \ GOTO 3540 & 505 | ! multi mode 506 | 3240 ! & 507 | 508 | 3250 & 509 | ! -- Pseudo-ops. -- & 510 | 511 | 3260 ON FLAGS%(OPCODE.TABLE.SUBSCRIPT%) & 512 | GOTO 3430, 3280, 3280, 3280, & 513 | 3340, 3340, 3340, 3410, & 514 | 3390 & 515 | ! .END .BYTE .DBYTE .WORD & 516 | ! .ASCII .ASCIP .ASCIZ .BLKB & 517 | ! .LIST 518 | 3270 ! -- .BYTE, .DBYTE, .WORD -- 519 | 3280 ARGUMENT$=ARGUMENT$+"," & 520 | \ TEMP3%=1% & 521 | \ TEMP3%=2% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=3% & 522 | OR FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=4% & 523 | \ FOR I%=1% TO BYTE.COUNT% STEP TEMP3% & 524 | \ ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%+I%-1%,0%) & 525 | \ TEMP1%=INSTR(1%,ARGUMENT$,",") 526 | 3290 TEMP2%=FNEVALUATE.EXPR%(LEFT(ARGUMENT$,TEMP1%-1%)) & 527 | \ IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=3% THEN & 528 | VALUE%=SWAP%(TEMP2%) & 529 | \ GOSUB 3450 & 530 | \ VALUE%=TEMP2% & 531 | \ GOSUB 3470 532 | 3300 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=4% THEN & 533 | VALUE%=SWAP%(TEMP2%) & 534 | \ GOSUB 3470 & 535 | \ VALUE%=TEMP2% & 536 | \ GOSUB 3450 537 | 3310 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=2% THEN & 538 | VALUE%=TEMP2% & 539 | \ GOSUB 3450 540 | 3320 GOSUB 3540 & 541 | \ ARGUMENT$=RIGHT(ARGUMENT$,TEMP1%+1%) & 542 | \ NEXT I% & 543 | \ RETURN 544 | 3330 ! -- .ASCII, .ASCIP, .ASCIZ -- 545 | 3340 ARGUMENT$=MID(ARGUMENT$,2%,BYTE.COUNT%) & 546 | \ ARGUMENT$=LEFT(ARGUMENT$,BYTE.COUNT%-1%)+CHR$(0%) & 547 | IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=7% & 548 | \ FOR I%=1% TO BYTE.COUNT% STEP 3% & 549 | \ ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%+I%-1%,0%) & 550 | \ VALUE%=FNCHAR%(I%) & 551 | \ GOSUB 3450 & 552 | \ VALUE%=FNCHAR%(I%+1%) & 553 | \ GOSUB 3470 IF I%+1%<=BYTE.COUNT% & 554 | \ VALUE%=FNCHAR%(I%+2%) & 555 | \ GOSUB 3490 IF I%+2%<=BYTE.COUNT% & 556 | \ GOSUB 3540 & 557 | \ NEXT I% & 558 | \ RETURN 559 | 3350 ! & 560 | 561 | 3360 ! -- Get character J% from ARGUMENT$ 562 | 3370 DEF* FNCHAR%(J%) & 563 | \ CHAR%=ASCII(MID(ARGUMENT$,J%,1%)) & 564 | \ CHAR%=CHAR% OR 128% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=6% & 565 | AND J%=BYTE.COUNT% & 566 | \ FNCHAR%=CHAR% & 567 | \ FNEND & 568 | 569 | 3380 ! -- .LIST -- 570 | 3390 LIST.FLAG%=FNEVALUATE.EXPR%(ARGUMENT$) & 571 | \ ADDRESS$="" & 572 | \ RETURN 573 | 3400 ! -- .BLKB 574 | 3410 TEMP1%=FNEVALUATE.EXPR%(ARGUMENT$) & 575 | \ IF OBJECT.OUT.FLAG% THEN VALUE%=0% & 576 | \ FOR X%=1% TO TEMP1% & 577 | \ GOSUB 3520 & 578 | \ NEXT X% 579 | 3420 GOSUB 3540 580 | 3430 RETURN 581 | 3440 & 582 | ! -- Form B1 -- & 583 | 584 | 3450 BYTE1$=FNDEC.TO.HEX$(VALUE%,3%) & 585 | \ GOSUB 3520 & 586 | \ RETURN 587 | 3460 & 588 | ! -- Form B2 -- & 589 | 590 | 3470 BYTE2$=FNDEC.TO.HEX$(VALUE%,3%) & 591 | \ GOSUB 3520 & 592 | \ RETURN 593 | 3480 & 594 | ! -- Form B3 -- & 595 | 596 | 3490 BYTE3$=FNDEC.TO.HEX$(VALUE%,3%) & 597 | \ GOSUB 3520 & 598 | \ RETURN 599 | 3500 ! & 600 | 601 | 3510 & 602 | ! -- Output object and update checksum -- & 603 | 604 | 3520 OBJECT.BYTE%=VALUE% AND 255% & 605 | \ OBJECT.BYTE%=FNOBJECT.OUTPUT%(VALUE%) IF OBJECT.OUT.FLAG% & 606 | \ CHECKSUM%=CHECKSUM%+OBJECT.BYTE% & 607 | \ RETURN 608 | 3530 & 609 | ! -- Output assembled code to listing file -- & 610 | 611 | 3540 GOTO 3590 UNLESS ERRORS.ONLY.SWITCH% OR ERROR.LINE.FLAG% 612 | 3550 IF ERROR.LINE.FLAG% THEN PRINT #1%,"?"; ELSE PRINT #1%," "; 613 | 3560 IF NEW.LINE.FLAG%"" THEN & 618 | PRINT #1%,CHR$(9%);SOURCE.LINE$ & 619 | ELSE PRINT #1% 620 | 3580 ! -- Set a flag, clear output strings -- 621 | 3590 NEW.LINE.FLAG%=LINE.NUMBER% & 622 | \ ADDRESS$,BYTE1$,BYTE2$,BYTE3$,SOURCE.LINE$="" & 623 | \ RETURN 624 | 3600 & 625 | ! -- Output binary byte to object file -- & 626 | 627 | 3610 DEF* FNOBJECT.OUTPUT%(X%) & 628 | \ OBJECT.BYTE%=X% AND 255% & 629 | \ PRINT #4%,FNDEC.TO.HEX$(OBJECT.BYTE%,3%); & 630 | \ NEW.OBJ.LINE%=NEW.OBJ.LINE%+1% & 631 | \ PRINT #4% IF (NEW.OBJ.LINE% AND 15%)=0% & 632 | \ FNOBJECT.OUTPUT%=OBJECT.BYTE% & 633 | \ FNEND 634 | 3620 & 635 | ! -- Print error count, checksum -- & 636 | 637 | 3630 PRINT #X% & 638 | \ PRINT #X%,"Errors detected ";FNDEC.TO.HEX$(ERROR.COUNT%,0%) & 639 | \ PRINT #X%,"Source checksum ";FNDEC.TO.HEX$(CHECKSUM%,0%) & 640 | \ PRINT #X%,"Total hex bytes ";FNDEC.TO.HEX$(TOTAL.BYTES%,0%) & 641 | \ PRINT #X% & 642 | \ RETURN 643 | 3640 ! & 644 | 645 | 3650 & 646 | ! -- Print sorted symbol table -- & 647 | 648 | 3660 TEMP1%,TEMP2%=0% & 649 | \ NUMBER.OF.SYMBOLS%=NUMBER.OF.SYMBOLS%-66% & 650 | \ RETURN IF NUMBER.OF.SYMBOLS%<0% 651 | 3670 PRINT #1%," Symbol Table" & 652 | \ PRINT #1% 653 | 3680 TEMP1%=TEMP1%+1% WHILE FLAGS%(TEMP1%)>=0% & 654 | \ SYMBOLS$(TEMP2%)=SYMBOLS$(TEMP1%) & 655 | \ VALUES%(TEMP2%)=VALUES%(TEMP1%) & 656 | \ FLAGS%(TEMP2%)=FLAGS%(TEMP1%) & 657 | \ TEMP2%=TEMP2%+1% & 658 | \ TEMP1%=TEMP1%+1% & 659 | \ GOTO 3680 UNLESS TEMP2%=NUMBER.OF.SYMBOLS% 660 | 3690 ! -- Quick sort the symbol table 661 | 3700 TEMP1%=FNQUICKSORT%(0%,NUMBER.OF.SYMBOLS%,0%,NUMBER.OF.SYMBOLS%) 662 | 3710 ! -- Output to listing file -- 663 | 3720 FOR I%=0% TO NUMBER.OF.SYMBOLS% & 664 | \ IF FLAGS%(I%)=-1% THEN S$="#" ELSE S$=" " 665 | 3730 PRINT #1% USING " \ \ \ \ ", & 666 | SYMBOLS$(I%),FNDEC.TO.HEX$(VALUES%(I%),0%)+S$; & 667 | \ PRINT #1% IF CCPOS(1%)>63% & 668 | \ NEXT I% 669 | 3740 PRINT #1% IF CCPOS(1%) & 670 | \ RETURN 671 | 3750 & 672 | ! -- Check position of char X% in SOURCE.LINE$ using tables & 673 | ! -- DELIMITER%(). FNCHECK.SYNTAX%=-1% means in string & 674 | 675 | 3760 DEF* FNCHECK.SYNTAX%(X%) 676 | 3770 GOTO 3790 IF DELIMITER%=-1% OR X%=0% & 677 | \ FOR X0%=0% TO DELIMITER% & 678 | \ GOTO 3790 IF X%<(SWAP%(DELIMITER.TABLE%(X0%)) AND 255%) & 679 | \ IF X%<(DELIMITER.TABLE%(X0%) AND 255%) THEN & 680 | FNCHECK.SYNTAX%=-1% & 681 | \ GOTO 3800 682 | 3780 NEXT X0% 683 | 3790 FNCHECK.SYNTAX%=0% 684 | 3800 FNEND 685 | 3810 ! & 686 | 687 | 4000 & 688 | ! -- Evaluate the argument expression -- & 689 | 690 | 4010 DEF* FNEVALUATE.EXPR%(X$) & 691 | \ UNDEFINED.SYMBOL%=0% 692 | 4020 & 693 | ! -- Main driver routine -- & 694 | 695 | 4030 EXPR$=X$ & 696 | \ GOSUB 4060 & 697 | \ GOSUB 4080 & 698 | \ EXP.VAL%=TERM% 699 | 4040 GOTO 4290 UNLESS OP% & 700 | \ LAST.OP%=OP% & 701 | \ GOSUB 4060 & 702 | \ GOSUB 4080 & 703 | \ GOSUB 4190 & 704 | \ GOTO 4040 705 | 4050 & 706 | REM ! -- Scan for the next operator { ! & % + * - / } -- & 707 | 708 | 4060 EXP.FLAG%=-1% & 709 | \ FOR TOK.PTR%=1% TO LEN(EXPR$) & 710 | \ TOK.CHR$=MID(EXPR$,TOK.PTR%,1%) & 711 | \ EXP.FLAG%= NOT EXP.FLAG% IF TOK.CHR$="'" & 712 | \ OP%=INSTR(1%,"!%&*+-/",TOK.CHR$) & 713 | \ RETURN IF OP% AND EXP.FLAG% & 714 | \ NEXT TOK.PTR% & 715 | \ OP%=0% & 716 | \ TOK.PTR%=TOK.PTR%+1% & 717 | \ RETURN 718 | 4070 & 719 | ! -- Get value of term -- & 720 | 721 | 4080 TERM$=LEFT(EXPR$,TOK.PTR%-1%) & 722 | \ EXPR$=RIGHT(EXPR$,TOK.PTR%+1%) 723 | 4090 IF TERM$="" THEN TERM%=0% & 724 | \ RETURN 725 | 4100 ! -- H() or L() ? -- 726 | 4110 TEMP1$=LEFT(TERM$,2%) & 727 | \ IF TEMP1$="H(" THEN EXP.FLAG%=1% & 728 | ELSE IF TEMP1$="L(" THEN EXP.FLAG%=2% & 729 | ELSE EXP.FLAG%=0% 730 | 4120 IF EXP.FLAG% THEN IF RIGHT(TERM$,LEN(TERM$))=")" THEN & 731 | TERM$=MID(TERM$,3%,LEN(TERM$)-3%) & 732 | ELSE 4170 733 | 4130 TEMP1$=LEFT(TERM$,1%) 734 | 4140 IF TEMP1$>="A" AND TEMP1$<="Z" THEN TERM%=FNSYMBOL.LOOKUP%(TERM$) & 735 | ELSE IF TEMP1$="0" OR TEMP1$="$" THEN & 736 | TERM%=FNHEX.TO.DEC%(RIGHT(TERM$,2%)) & 737 | ELSE IF TEMP1$>="1" AND TEMP1$<="9" THEN TERM%=VAL(TERM$) & 738 | ELSE IF TEMP1$="'" THEN TERM%=ASCII(RIGHT(TERM$,2%)) & 739 | ELSE IF TEMP1$="^" THEN TERM%=FNOCT.TO.DEC%(RIGHT(TERM$,2%)) & 740 | ELSE IF TERM$="." THEN TERM%=LOCATION.COUNTER% & 741 | ELSE 4170 742 | 4150 IF EXP.FLAG%=1% THEN TERM%=SWAP%(TERM%) AND 255% & 743 | ELSE IF EXP.FLAG%=2% THEN TERM%=TERM% AND 255% 744 | 4160 RETURN 745 | 4170 TERM%=FNERROR.PRINT%("Invalid term = "+TERM$) & 746 | \ RETURN 747 | 4180 & 748 | ! -- Carry out the arithmetic or logical operation -- & 749 | 750 | 4190 ON LAST.OP%+1% & 751 | GOTO 4270, 4200, 4210, 4220, & 752 | 4230, 4240, 4250, 4260 & 753 | ! or not and & 754 | ! mult add sub div 755 | 4200 EXP.VAL%=EXP.VAL% OR TERM% & 756 | \ RETURN & 757 | ! or 758 | 4210 EXP.VAL%=EXP.VAL%+(NOT TERM%) & 759 | \ RETURN & 760 | ! not 761 | 4220 EXP.VAL%=EXP.VAL% AND TERM% & 762 | \ RETURN & 763 | ! and 764 | 4230 EXP.VAL%=EXP.VAL%*TERM% & 765 | \ RETURN & 766 | ! multiply 767 | 4240 EXP.VAL%=EXP.VAL%+TERM% & 768 | \ RETURN & 769 | ! add 770 | 4250 EXP.VAL%=EXP.VAL%-TERM% & 771 | \ RETURN & 772 | ! subtract 773 | 4260 IF TERM%=0% THEN EXP.VAL%=FNERROR.PRINT%("Division by zero") & 774 | ELSE EXP.VAL%=EXP.VAL%/TERM% 775 | 4270 RETURN 776 | 4280 & 777 | ! -- Exit with value of expression -- 778 | 4290 FNEVALUATE.EXPR%=EXP.VAL% 779 | 4300 FNEND 780 | 4310 ! & 781 | 782 | 4320 & 783 | ! -- Print the given error message to the listing file & 784 | 785 | 4330 DEF* FNERROR.PRINT%(X$) & 786 | \ PRINT #1%,"********";X$; & 787 | \ IF PASS.NUMBER%=1% THEN PRINT #1%," at line";LINE.NUMBER% & 788 | ELSE PRINT #1% 789 | 4340 ERROR.COUNT%=ERROR.COUNT%+1% & 790 | \ ERROR.LINE.FLAG%=-1% & 791 | \ FNERROR.PRINT%=0% & 792 | \ FNEND 793 | 4350 & 794 | ! -- Look up value of symbol -- & 795 | 796 | 4360 DEF* FNSYMBOL.LOOKUP%(SYMBOL$) & 797 | \ X%=FNHASH.SYMBOL%(SYMBOL$,SYMBOL.TABLE.SIZE%) 798 | 4370 IF SYMBOLS$(X%)=SYMBOL$ AND FLAGS%(X%)<=0% THEN & 799 | FNSYMBOL.LOOKUP%=VALUES%(X%) & 800 | ELSE IF SYMBOLS$(X%)="" THEN GOSUB 4390 & 801 | ELSE X%=FNREHASH.SYMBOL%(X%,SYMBOL.TABLE.SIZE%) & 802 | \ GOTO 4370 803 | 4380 FNEND 804 | 4390 UNDEFINED.SYMBOL%=-1% & 805 | \ IF PASS.NUMBER%=2% THEN & 806 | FNSYMBOL.LOOKUP%=FNERROR.PRINT%( & 807 | "Undefined symbol "+SYMBOL$) 808 | 4400 RETURN 809 | 4410 & 810 | ! -- Dec to Hex conversion -- & 811 | 812 | 4420 DEF* FNDEC.TO.HEX$(X%,D%) 813 | 4430 X$="" & 814 | \ FOR X1%=0% TO 3% & 815 | \ X0%=(X% AND (16%^(X1%+1%)-1%*(16%^X1%)))/(16%^X1%) & 816 | \ X0%=X0%+16% IF X0%<0% & 817 | \ X$=CHR$(48%+X0%)+X$ IF X0%<10% & 818 | \ X$=CHR$(55%+X0%)+X$ IF X0%>9% & 819 | \ NEXT X1% & 820 | \ IF D% THEN X$=MID(X$,D%,2%) 821 | 4440 FNDEC.TO.HEX$=X$ 822 | 4450 FNEND 823 | 4460 & 824 | ! -- Hex to Dec conversion -- & 825 | 826 | 4470 DEF* FNHEX.TO.DEC%(X$) & 827 | \ X0%=0% & 828 | \ FOR X1%=1% TO LEN(X$) & 829 | \ X2%=ASCII(MID(X$,X1%,1%)) & 830 | \ IF X2%<48% OR (X2%>57% AND X2%<65%) OR X2%>70% THEN & 831 | FNHEX.TO.DEC%=FNERROR.PRINT%("Invalid HEX constant = "+X$) & 832 | \ GOTO 4490 833 | 4480 X2%=X2%-48% & 834 | \ X2%=X2%-7% IF X2%>9% & 835 | \ X0%=X2%+X0%*16% & 836 | \ NEXT X1% & 837 | \ FNHEX.TO.DEC%=X0% 838 | 4490 FNEND 839 | 4500 & 840 | ! -- Octal to Dec conversion -- & 841 | 842 | 4510 DEF* FNOCT.TO.DEC%(X$) & 843 | \ X0%=0% & 844 | \ FOR X1%=1% TO LEN(X$) & 845 | \ X2%=ASCII(MID(X$,X1%,1%))-48% & 846 | \ IF X2%<0% OR X2%>7% THEN & 847 | FNOCT.TO.DEC%=FNERROR.PRINT%("Invalid OCTAL constant = "+X$) & 848 | \ GOTO 4530 849 | 4520 X0%=X0%*8% + X2% & 850 | \ NEXT X1% & 851 | \ FNOCT.TO.DEC%=X0% 852 | 4530 FNEND 853 | 4540 & 854 | ! -- Calculate X1% modulo X2% -- & 855 | 856 | 4550 DEF* FNMOD%(X1%,X2%) & 857 | \ X1%=X1%-(X1%/X2%)*X2% & 858 | \ X1%=X1%+X2% IF X1%<0% & 859 | \ FNMOD%=X1% & 860 | \ FNEND 861 | 4560 & 862 | ! -- Hash symbol X$, modulo SYMBOL.TABLE.SIZE% -- & 863 | 864 | 4570 DEF* FNHASH.SYMBOL%(SYMBOL$,M%) & 865 | \ SYMBOL$=LEFT(SYMBOL$+" ",6%) & 866 | \ CHANGE SYMBOL$ TO SYMBOL.CHARS% & 867 | \ SYMBOL.CHARS%(X%)=SYMBOL.CHARS%(X%)-48% FOR X%=1% TO 6% & 868 | \ FNHASH.SYMBOL%=FNMOD%(SYMBOL.CHARS%(1%)*23%+ & 869 | SYMBOL.CHARS%(2%)*19%+SYMBOL.CHARS%(3%)*17%+ & 870 | SYMBOL.CHARS%(4%)*13%+SYMBOL.CHARS%(5%)*11%+ & 871 | SYMBOL.CHARS%(6%)*7%,M%) & 872 | \ FNEND 873 | 4580 & 874 | ! -- Rehash function, modulo X2% & 875 | 876 | 4590 DEF* FNREHASH.SYMBOL%(X1%,X2%)=FNMOD%(X1%+23%,X2%) 877 | 4600 & 878 | ! -- Quick sort symbol table & 879 | 880 | 4610 ! & 881 | 882 | 4620 DEF* FNQUICKSORT%(LOW%,HIGH%,I%,J%) & 883 | \ I%=LOW% & 884 | \ J%=HIGH% & 885 | \ X$=SYMBOLS$((HIGH%+LOW%)/2%) 886 | 4630 I%=I%+1% WHILE SYMBOLS$(I%)J% THEN 4670 & 889 | ELSE IF I%<>J% THEN VALUE%=VALUES%(I%) & 890 | \ FLAG.WORD%=FLAGS%(I%) & 891 | \ SYMBOL$=SYMBOLS$(I%) & 892 | \ VALUES%(I%)=VALUES%(J%) & 893 | \ FLAGS%(I%)=FLAGS%(J%) & 894 | \ SYMBOLS$(I%)=SYMBOLS$(J%) & 895 | \ VALUES%(J%)=VALUE% & 896 | \ FLAGS%(J%)=FLAG.WORD% & 897 | \ SYMBOLS$(J%)=SYMBOL$ 898 | 4660 I%=I%+1% & 899 | \ J%=J%-1% & 900 | \ IF I%<=J% THEN 4630 901 | 4670 IF LOW%10% 143 | 2160 CLOSE 2%,3% & 144 | \ RETURN & 145 | ! -- End of Pass 1 146 | 2170 ! & 147 | 148 | 2180 & 149 | ! -- Scan for strings in SOURCE.LINE$ -- & 150 | 151 | 2190 DELIMITER%=-1% & 152 | \ TEMP2%=0% 153 | 2200 TEMP1%=INSTR(TEMP2%+1%,SOURCE.LINE$,"'") & 154 | \ RETURN UNLESS TEMP1% 155 | 2210 TEMP2%=INSTR(TEMP1%+1%,SOURCE.LINE$,"'") & 156 | \ IF TEMP2% THEN DELIMITER%=DELIMITER%+1% & 157 | \ IF DELIMITER%<4% THEN DELIMITER.TABLE%(DELIMITER%)= & 158 | SWAP%(TEMP1% AND 255%) OR (TEMP2% AND 255%) & 159 | \ GOTO 2200 160 | 2220 RETURN 161 | 2230 & 162 | ! -- Search for token delimiters -- & 163 | ! LABEL.DELIMITER% Label & 164 | ! OPCODE.DELIMITER% Opcode & 165 | ! COMMENT.DELIMITER% Comment & 166 | ! EQU.DELIMITER% Assignment & 167 | 168 | 2240 LABEL.DELIMITER%=INSTR(1%,SOURCE.LINE$,":") & 169 | \ LABEL.DELIMITER%=0% IF FNCHECK.SYNTAX%(LABEL.DELIMITER%) & 170 | \ COMMENT.DELIMITER%=0% 171 | 2250 COMMENT.DELIMITER%=INSTR(COMMENT.DELIMITER%+1%,SOURCE.LINE$,";") & 172 | \ GOTO 2250 IF FNCHECK.SYNTAX%(COMMENT.DELIMITER%) & 173 | \ LABEL.DELIMITER%=0% IF (LABEL.DELIMITER%> & 174 | COMMENT.DELIMITER% AND COMMENT.DELIMITER%<>0%) & 175 | \ OPCODE.DELIMITER%=LABEL.DELIMITER% 176 | 2260 OPCODE.DELIMITER%=OPCODE.DELIMITER%+1% & 177 | \ IF OPCODE.DELIMITER%>=LINE.LENGTH% THEN 2280 & 178 | ELSE X%=ASCII(RIGHT(SOURCE.LINE$,OPCODE.DELIMITER%)) & 179 | \ IF X%=9% OR X%=32% THEN 2260 180 | 2270 OPCODE.DELIMITER%=OPCODE.DELIMITER%+1% & 181 | \ IF OPCODE.DELIMITER%9% AND X%<>32% THEN 2270 & 184 | ELSE OPCODE.DELIMITER%=OPCODE.DELIMITER%-1% 185 | 2280 EQU.DELIMITER%=INSTR(1%,SOURCE.LINE$,"=") & 186 | \ EQU.DELIMITER%=0% IF FNCHECK.SYNTAX%(EQU.DELIMITER%) OR & 187 | (EQU.DELIMITER%>COMMENT.DELIMITER% AND & 188 | COMMENT.DELIMITER%<>0%) & 189 | \ OPCODE.DELIMITER%=EQU.DELIMITER% IF EQU.DELIMITER% 190 | 2290 OPCODE.DELIMITER%=COMMENT.DELIMITER%-1% IF & 191 | (OPCODE.DELIMITER%>=COMMENT.DELIMITER% AND & 192 | COMMENT.DELIMITER%<>0%) & 193 | \ RETURN 194 | 2300 & 195 | ! Enter symbol SYMBOL$ into symbol table & 196 | ! and its value VALUE% & 197 | 198 | 2310 IF NUMBER.OF.SYMBOLS%=SYMBOL.TABLE.SIZE% THEN & 199 | VALUE%=FNERROR.PRINT%("?X80 - FATAL: Symbol table overflow") & 200 | \ STOP & 201 | ! Symbol table full 202 | 2320 X%=ASCII(SYMBOL$) & 203 | \ IF X%<>46% AND ( X%<65% OR X%>90% ) THEN & 204 | VALUE%=FNERROR.PRINT%("Invalid symbol = "+SYMBOL$) & 205 | \ RETURN & 206 | ! Invalid symbol 207 | 2330 TEMP2%=FNHASH.SYMBOL%(SYMBOL$,SYMBOL.TABLE.SIZE%) & 208 | ! Hash symbol 209 | 2340 IF SYMBOLS$(TEMP2%)="" THEN SYMBOLS$(TEMP2%)=SYMBOL$ & 210 | \ VALUES%(TEMP2%)=VALUE% & 211 | \ FLAGS%(TEMP2%)=FLAG.WORD% & 212 | \ NUMBER.OF.SYMBOLS%=NUMBER.OF.SYMBOLS%+1% & 213 | \ RETURN & 214 | ! If slot empty, enter symbol, value and flagword 215 | 2350 IF SYMBOLS$(TEMP2%)=SYMBOL$ AND FLAGS%(TEMP2%)<0% THEN & 216 | VALUE%=FNERROR.PRINT%("Redefined symbol = "+SYMBOL$) & 217 | \ RETURN & 218 | ! Multiple definition not allowed 219 | 2360 TEMP2%=FNREHASH.SYMBOL%(TEMP2%,SYMBOL.TABLE.SIZE%) & 220 | \ GOTO 2340 221 | 2370 & 222 | ! -- Enter assignment -- & 223 | 224 | 2380 SYMBOL$=CVT$$(MID(SOURCE.LINE$,LABEL.DELIMITER%+1%, & 225 | EQU.DELIMITER%-LABEL.DELIMITER%-1%),136%) & 226 | \ VALUE%=FNEVALUATE.EXPR%(ARGUMENT$) 227 | 2390 IF SYMBOL$="." THEN LOCATION.COUNTER%=VALUE% & 228 | ELSE IF SYMBOL$="" THEN VALUE%= & 229 | FNERROR.PRINT%("Missing symbol") & 230 | ELSE FLAG.WORD%=-1% & 231 | \ GOSUB 2310 232 | 2400 OPCODE.TABLE.SUBSCRIPT%=-1% & 233 | \ RETURN 234 | 2410 & 235 | ! -- Get opcode subscript -- & 236 | 237 | 2420 OPCODE$=CVT$$(MID(SOURCE.LINE$,LABEL.DELIMITER%+1%, & 238 | OPCODE.DELIMITER%-LABEL.DELIMITER%),8%) & 239 | \ IF OPCODE$<>"" THEN OPCODE.TABLE.SUBSCRIPT%= & 240 | FNHASH.SYMBOL%(OPCODE$,SYMBOL.TABLE.SIZE%) & 241 | ELSE OPCODE.TABLE.SUBSCRIPT%=-1% \ RETURN 242 | 2430 IF SYMBOLS$(OPCODE.TABLE.SUBSCRIPT%)=OPCODE$ THEN RETURN & 243 | ELSE IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)<0% OR & 244 | SYMBOLS$(OPCODE.TABLE.SUBSCRIPT%)="" THEN & 245 | OPCODE.TABLE.SUBSCRIPT%= & 246 | FNERROR.PRINT%("Invalid opcode = "+OPCODE$)-1% & 247 | ELSE OPCODE.TABLE.SUBSCRIPT%= & 248 | FNREHASH.SYMBOL%(OPCODE.TABLE.SUBSCRIPT%, & 249 | SYMBOL.TABLE.SIZE%) & 250 | \ GOTO 2430 & 251 | ! Check for opcode match in the symbol table & 252 | ! If flagword < 0 then report an error else rehash 253 | 2440 RETURN 254 | 2450 & 255 | ! -- Get byte count and output to workfile -- & 256 | 257 | 2460 IF OPCODE.TABLE.SUBSCRIPT%=-1% THEN BYTE.COUNT%=0% & 258 | ELSE IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)>3% THEN & 259 | GOSUB 2500 & 260 | ELSE BYTE.COUNT%=FLAGS%(OPCODE.TABLE.SUBSCRIPT%) & 261 | ! Get byte count into BYTE.COUNT% 262 | 2470 PRINT #3%,LOCATION.COUNTER%;","; & 263 | BYTE.COUNT%;","; & 264 | OPCODE.TABLE.SUBSCRIPT%;","; & 265 | ERROR.LINE.FLAG% & 266 | \ PRINT #3%,ARGUMENT$ & 267 | \ TOTAL.BYTES%=TOTAL.BYTES%+BYTE.COUNT% & 268 | \ LOCATION.COUNTER%=LOCATION.COUNTER%+BYTE.COUNT% & 269 | \ ERROR.LINE.FLAG%=0% & 270 | \ RETURN 271 | 2480 ! & 272 | 273 | 2490 & 274 | ! -- Get byte count for pseudo-op -- & 275 | 276 | 2500 ON FLAGS%(OPCODE.TABLE.SUBSCRIPT%)-9% & 277 | GOTO 2590, 2520, 2520, 2520, & 278 | 2540, 2540, 2540, 2590, & 279 | 2570 & 280 | ! .END .BYTE .DBYTE .WORD & 281 | ! .ASCII .ASCIP .ASCIZ .LIST & 282 | ! .BLKB 283 | 2510 ! -- .BYTE, .DBYTE, .WORD -- 284 | 2520 TEMP1%=0% & 285 | \ TEMP2%=-1% & 286 | \ FOR BYTE.COUNT%=0% WHILE TEMP2% & 287 | \ TEMP1%,TEMP2%=INSTR(TEMP1%+1%,ARGUMENT$,",") & 288 | \ NEXT BYTE.COUNT% & 289 | \ BYTE.COUNT%=BYTE.COUNT%*2% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=12% & 290 | OR FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=13% & 291 | \ RETURN 292 | 2530 ! -- .ASCII, .ASCIP, .ASCIZ -- 293 | 2540 TEMP1%=INSTR(2%,ARGUMENT$,LEFT(ARGUMENT$,1%)) & 294 | \ IF TEMP1%=0% THEN OPCODE.TABLE.SUBSCRIPT%= & 295 | FNERROR.PRINT%("Missing delimiter")-1% & 296 | ELSE BYTE.COUNT%=TEMP1%-2% 297 | 2550 BYTE.COUNT%=BYTE.COUNT%+1% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=16% & 298 | \ RETURN 299 | 2560 ! -- .BLKB 300 | 2570 BYTE.COUNT%=FNEVALUATE.EXPR%(ARGUMENT$) & 301 | \ RETURN 302 | 2580 ! -- .LIST, END -- 303 | 2590 BYTE.COUNT%=0% & 304 | \ RETURN 305 | 2600 ! & 306 | 307 | 3000 & 308 | ! -- Pass 2 Driver routine -- & 309 | 310 | 3010 LINE.NUMBER%, & 311 | CHECKSUM%, & 312 | NEW.LINE.FLAG%=0% & 313 | \ PASS.NUMBER%=2% & 314 | \ LIST.FLAG%=-1% & 315 | \ PRINT #1%,"Pass 2" & 316 | \ CLOSE 1% & 317 | \ OPEN LISTING.FILE$ FOR OUTPUT AS FILE 1% & 318 | \ OPEN SOURCE.FILE$ FOR INPUT AS FILE 2% & 319 | \ OPEN WORK.FILE$ FOR INPUT AS FILE 3% & 320 | \ KILL WORK.FILE$ 321 | 3020 IF OBJECT.OUT.FLAG% THEN & 322 | OPEN OBJECT.FILE$ FOR OUTPUT AS FILE 4% & 323 | \ NEW.OBJ.LINE%=0% 324 | 3030 IF ERRORS.ONLY.SWITCH% THEN PRINT #1%," Line Addr B1 B2 B3" & 325 | \ PRINT #1% 326 | 3040 INPUT #3%,LOCATION.COUNTER%, & 327 | BYTE.COUNT%, & 328 | OPCODE.TABLE.SUBSCRIPT%, & 329 | ERROR.LINE.FLAG% & 330 | \ INPUT LINE #3%, ARGUMENT$ & 331 | \ ARGUMENT$=CVT$$(ARGUMENT$,4%) & 332 | \ INPUT LINE #2%, SOURCE.LINE$ & 333 | \ SOURCE.LINE$=CVT$$(SOURCE.LINE$,4%) & 334 | \ LINE.NUMBER%=LINE.NUMBER%+1% 335 | 3050 ! -- Form object code and output to listing file -- 336 | 3060 IF LEFT(SOURCE.LINE$,1%)="$" THEN & 337 | SOURCE.LINE$=RIGHT(SOURCE.LINE$,2%) 338 | 3070 IF OPCODE.TABLE.SUBSCRIPT%=-1% THEN GOSUB 3630 & 339 | \ GOTO 3040 340 | 3080 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=10% THEN & 341 | GOSUB 3130 & 342 | \ RETURN 343 | 3090 ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%,0%) & 344 | \ VALUE%=VALUES%(OPCODE.TABLE.SUBSCRIPT%) & 345 | \ FLAG.WORD%=SWAP%(VALUE%) AND 255% & 346 | \ VALUE%=VALUE% AND 255% 347 | 3100 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)>3% THEN GOSUB 3370 & 348 | ELSE IF FLAG.WORD% THEN GOSUB 3170 & 349 | ELSE GOSUB 3540 & 350 | \ GOSUB 3630 351 | 3110 GOTO 3040 352 | 3120 & 353 | ! -- End of assembly, tidy up -- & 354 | 355 | 3130 GOSUB 3630 & 356 | \ PRINT #4% IF OBJECT.OUT.FLAG% 357 | 3140 CLOSE 2%,3%,4% & 358 | \ RETURN 359 | 3150 ! & 360 | 361 | 3160 & 362 | ! -- Process operands -- & 363 | 364 | 3170 FIRST.ARG.TYPE%=FLAG.WORD% AND 7% & 365 | \ SECOND.ARG.TYPE%=(FLAG.WORD% AND 56%)/8% & 366 | \ SHIFT.ARG.FLAG%=(FLAG.WORD% AND 192%)/64% & 367 | \ SHIFT.ARG.FLAG%=4% IF SHIFT.ARG.FLAG%=2% 368 | 3180 ! -- If two operands evaluate the second into ARG2.VALUE% 369 | 3190 IF SECOND.ARG.TYPE%=0% THEN ARG2.VALUE%=0% & 370 | ELSE TEMP2%=INSTR(1%,ARGUMENT$,",") & 371 | \ IF TEMP2%=0% THEN ARG2.VALUE%= & 372 | FNERROR.PRINT%("Missing operand") & 373 | ELSE ARG2.VALUE%=FNEVALUATE.ARGUMENT%( & 374 | RIGHT(ARGUMENT$,TEMP2%+1%),SECOND.ARG.TYPE%) & 375 | \ ARGUMENT$=LEFT(ARGUMENT$,TEMP2%-1%) 376 | 3200 ! -- Evaluate the first (only) operand 377 | 3210 ARG1.VALUE%=FNEVALUATE.ARGUMENT%(ARGUMENT$,FIRST.ARG.TYPE%) 378 | 3220 ! -- If register , do appropriate shift and OR into opcode base 379 | 3230 IF FIRST.ARG.TYPE%<4% OR FIRST.ARG.TYPE%=7% THEN & 380 | ARG1.VALUE%=ARG1.VALUE%*(2%^SHIFT.ARG.FLAG%) & 381 | \ VALUE%=VALUE% OR ARG1.VALUE% 382 | 3240 IF SECOND.ARG.TYPE%<4% THEN VALUE%=VALUE% OR ARG2.VALUE% & 383 | ! -- Assemble the bytes for this instruction 384 | 3250 GOSUB 3540 385 | 3260 IF SHIFT.ARG.FLAG%=1% THEN GOSUB 3330 & 386 | \ GOSUB 3560 & 387 | \ GOSUB 3630 & 388 | \ RETURN 389 | 3270 IF SECOND.ARG.TYPE%=4% THEN FIRST.ARG.TYPE%=4% & 390 | \ ARG1.VALUE%=ARG2.VALUE% 391 | 3280 IF FIRST.ARG.TYPE%=4% THEN VALUE%=ARG1.VALUE% & 392 | \ GOSUB 3560 & 393 | \ GOSUB 3630 & 394 | \ RETURN 395 | 3290 IF SECOND.ARG.TYPE%=5% THEN FIRST.ARG.TYPE%=6% & 396 | \ ARG1.VALUE%=ARG2.VALUE% 397 | 3300 IF FIRST.ARG.TYPE%=6% THEN VALUE%=ARG1.VALUE% & 398 | \ GOSUB 3560 & 399 | \ VALUE%=SWAP%(ARG1.VALUE%) & 400 | \ GOSUB 3580 401 | 3310 GOSUB 3630 & 402 | \ RETURN 403 | 3320 ! -- Z80 relative branches 404 | 3330 VALUE%=ARG1.VALUE%-LOCATION.COUNTER%-2% & 405 | \ IF VALUE%<-128% OR VALUE%>127% THEN & 406 | VALUE%=FNERROR.PRINT%("Invalid displacement ="+NUM$(VALUE%)) 407 | 3340 RETURN 408 | 3350 ! & 409 | 410 | 3360 & 411 | ! -- Pseudo-ops. -- & 412 | 413 | 3370 ON FLAGS%(OPCODE.TABLE.SUBSCRIPT%)-9% & 414 | GOTO 3490, 3390, 3390, 3390, & 415 | 3450, 3450, 3450, 3490, & 416 | 3510 & 417 | ! .END .BYTE .DBYTE .WORD & 418 | ! .ASCII .ASCIP .ASCIZ .LIST & 419 | ! .BLKB 420 | 3380 ! -- .BYTE, .DBYTE, .WORD -- 421 | 3390 ARGUMENT$=ARGUMENT$+"," & 422 | \ TEMP3%=1% & 423 | \ TEMP3%=2% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=12% & 424 | OR FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=13% & 425 | \ FOR I%=1% TO BYTE.COUNT% STEP TEMP3% & 426 | \ ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%+I%-1%,0%) & 427 | \ TEMP1%=INSTR(1%,ARGUMENT$,",") 428 | 3400 TEMP2%=FNEVALUATE.EXPR%(LEFT(ARGUMENT$,TEMP1%-1%)) & 429 | \ IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=12% THEN & 430 | VALUE%=SWAP%(TEMP2%) & 431 | \ GOSUB 3540 & 432 | \ VALUE%=TEMP2% & 433 | \ GOSUB 3560 434 | 3410 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=13% THEN & 435 | VALUE%=TEMP2% & 436 | \ GOSUB 3540 & 437 | \ VALUE%=SWAP%(TEMP2%) & 438 | \ GOSUB 3560 439 | 3420 IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=11% THEN & 440 | VALUE%=TEMP2% & 441 | \ GOSUB 3540 442 | 3430 GOSUB 3630 & 443 | \ ARGUMENT$=RIGHT(ARGUMENT$,TEMP1%+1%) & 444 | \ NEXT I% & 445 | \ RETURN 446 | 3440 ! -- .ASCII, .ASCIP, .ASCIZ -- 447 | 3450 ARGUMENT$=MID(ARGUMENT$,2%,BYTE.COUNT%) & 448 | \ ARGUMENT$=LEFT(ARGUMENT$,BYTE.COUNT%-1%)+CHR$(0%) & 449 | IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=16% & 450 | \ FOR I%=1% TO BYTE.COUNT% STEP 3% & 451 | \ ADDRESS$=FNDEC.TO.HEX$(LOCATION.COUNTER%+I%-1%,0%) & 452 | \ VALUE%=FNCHAR%(I%) & 453 | \ GOSUB 3540 & 454 | \ VALUE%=FNCHAR%(I%+1%) & 455 | \ GOSUB 3560 IF I%+1%<=BYTE.COUNT% & 456 | \ VALUE%=FNCHAR%(I%+2%) & 457 | \ GOSUB 3580 IF I%+2%<=BYTE.COUNT% & 458 | \ GOSUB 3630 & 459 | \ NEXT I% & 460 | \ RETURN 461 | 3460 ! -- Get character J% from ARGUMENT$ 462 | 3470 DEF* FNCHAR%(J%) & 463 | \ CHAR%=ASCII(MID(ARGUMENT$,J%,1%)) & 464 | \ CHAR%=CHAR% OR 128% IF FLAGS%(OPCODE.TABLE.SUBSCRIPT%)=15% & 465 | AND J%=BYTE.COUNT% & 466 | \ FNCHAR%=CHAR% & 467 | \ FNEND & 468 | 469 | 3480 ! -- .LIST -- 470 | 3490 LIST.FLAG%=FNEVALUATE.EXPR%(ARGUMENT$) & 471 | \ ADDRESS$="" & 472 | \ RETURN 473 | 3500 ! -- .BLKB 474 | 3510 TEMP1%=FNEVALUATE.EXPR%(ARGUMENT$) & 475 | \ IF OBJECT.OUT.FLAG% THEN VALUE%=0% & 476 | \ FOR X%=1% TO TEMP1% & 477 | \ GOSUB 3610 & 478 | \ NEXT X% 479 | 3520 GOSUB 3630 & 480 | \ RETURN 481 | 3530 & 482 | ! -- Form B1 -- & 483 | 484 | 3540 BYTE1$=FNDEC.TO.HEX$(VALUE%,3%) & 485 | \ GOSUB 3610 & 486 | \ RETURN 487 | 3550 & 488 | ! -- Form B2 -- & 489 | 490 | 3560 BYTE2$=FNDEC.TO.HEX$(VALUE%,3%) & 491 | \ GOSUB 3610 & 492 | \ RETURN 493 | 3570 & 494 | ! -- Form B3 -- & 495 | 496 | 3580 BYTE3$=FNDEC.TO.HEX$(VALUE%,3%) & 497 | \ GOSUB 3610 & 498 | \ RETURN 499 | 3590 ! & 500 | 501 | 3600 & 502 | ! -- Output object and update checksum -- & 503 | 504 | 3610 OBJECT.BYTE%=VALUE% AND 255% & 505 | \ OBJECT.BYTE%=FNOBJECT.OUTPUT%(VALUE%) IF OBJECT.OUT.FLAG% & 506 | \ CHECKSUM%=CHECKSUM%+OBJECT.BYTE% & 507 | \ RETURN 508 | 3620 & 509 | ! -- Output assembled code to listing file -- & 510 | 511 | 3630 GOTO 3680 UNLESS ERRORS.ONLY.SWITCH% OR ERROR.LINE.FLAG% 512 | 3640 IF ERROR.LINE.FLAG% THEN PRINT #1%,"?"; ELSE PRINT #1%," "; 513 | 3650 IF NEW.LINE.FLAG%"" THEN & 518 | PRINT #1%,CHR$(9%);SOURCE.LINE$ & 519 | ELSE PRINT #1% 520 | 3670 ! -- Set a flag, clear output strings -- 521 | 3680 NEW.LINE.FLAG%=LINE.NUMBER% & 522 | \ ADDRESS$,BYTE1$,BYTE2$,BYTE3$,SOURCE.LINE$="" & 523 | \ RETURN 524 | 3690 & 525 | ! -- Output binary byte to object file -- & 526 | 527 | 3700 DEF* FNOBJECT.OUTPUT%(X%) & 528 | \ OBJECT.BYTE%=X% AND 255% & 529 | \ PRINT #4%,FNDEC.TO.HEX$(OBJECT.BYTE%,3%); & 530 | \ NEW.OBJ.LINE%=NEW.OBJ.LINE%+1% & 531 | \ PRINT #4% IF (NEW.OBJ.LINE% AND 15%)=0% & 532 | \ FNOBJECT.OUTPUT%=OBJECT.BYTE% & 533 | \ FNEND 534 | 3710 & 535 | ! -- Print error count, checksum -- & 536 | 537 | 3720 PRINT #X% & 538 | \ PRINT #X%,"Errors detected ";FNDEC.TO.HEX$(ERROR.COUNT%,0%) & 539 | \ PRINT #X%,"Source checksum ";FNDEC.TO.HEX$(CHECKSUM%,0%) & 540 | \ PRINT #X%,"Total hex bytes ";FNDEC.TO.HEX$(TOTAL.BYTES%,0%) & 541 | \ PRINT #X% & 542 | \ RETURN 543 | 3730 ! & 544 | 545 | 3740 & 546 | ! -- Print sorted symbol table -- & 547 | 548 | 3750 TEMP1%,TEMP2%=0% & 549 | \ NUMBER.OF.SYMBOLS%=NUMBER.OF.SYMBOLS%-111% & 550 | \ RETURN IF NUMBER.OF.SYMBOLS%<0% 551 | 3760 PRINT #1%," Symbol Table" & 552 | \ PRINT #1% 553 | 3770 TEMP1%=TEMP1%+1% WHILE FLAGS%(TEMP1%)>=0% & 554 | \ SYMBOLS$(TEMP2%)=SYMBOLS$(TEMP1%) & 555 | \ VALUES%(TEMP2%)=VALUES%(TEMP1%) & 556 | \ FLAGS%(TEMP2%)=FLAGS%(TEMP1%) & 557 | \ TEMP2%=TEMP2%+1% & 558 | \ TEMP1%=TEMP1%+1% & 559 | \ GOTO 3770 UNLESS TEMP2%=NUMBER.OF.SYMBOLS%+1% 560 | 3780 ! -- Quick sort the symbol table 561 | 3790 TEMP1%=FNQUICKSORT%(0%,NUMBER.OF.SYMBOLS%,0%,NUMBER.OF.SYMBOLS%) 562 | 3800 ! -- Output to listing file -- 563 | 3810 FOR I%=0% TO NUMBER.OF.SYMBOLS% & 564 | \ IF FLAGS%(I%)=-1% THEN S$="#" ELSE S$=" " 565 | 3820 PRINT #1% USING " \ \ \ \ ", & 566 | SYMBOLS$(I%),FNDEC.TO.HEX$(VALUES%(I%),0%)+S$; & 567 | \ PRINT #1% IF CCPOS(1%)>63% & 568 | \ NEXT I% 569 | 3830 PRINT #1% IF CCPOS(1%) & 570 | \ RETURN 571 | 3840 & 572 | ! -- Check position of char X% in SOURCE.LINE$ using tables & 573 | ! -- DELIMITER%(). FNCHECK.SYNTAX%=-1% means in string & 574 | 575 | 3850 DEF* FNCHECK.SYNTAX%(X%) 576 | 3860 GOTO 3880 IF DELIMITER%=-1% OR X%=0% & 577 | \ FOR X0%=0% TO DELIMITER% & 578 | \ GOTO 3880 IF X%<(SWAP%(DELIMITER.TABLE%(X0%)) AND 255%) & 579 | \ IF X%<(DELIMITER.TABLE%(X0%) AND 255%) THEN & 580 | FNCHECK.SYNTAX%=-1% & 581 | \ GOTO 3890 582 | 3870 NEXT X0% 583 | 3880 FNCHECK.SYNTAX%=0% 584 | 3890 FNEND 585 | 3900 ! & 586 | 587 | 4000 & 588 | ! -- Evaluate the argument expression -- & 589 | 590 | 4010 DEF* FNEVALUATE.EXPR%(X$) 591 | 4020 & 592 | ! -- Main driver routine -- & 593 | 594 | 4030 EXPR$=X$ & 595 | \ GOSUB 4060 & 596 | \ GOSUB 4080 & 597 | \ EXP.VAL%=TERM% 598 | 4040 GOTO 4290 UNLESS OP% & 599 | \ LAST.OP%=OP% & 600 | \ GOSUB 4060 & 601 | \ GOSUB 4080 & 602 | \ GOSUB 4190 & 603 | \ GOTO 4040 604 | 4050 & 605 | REM ! -- Scan for the next operator { ! & % + * - / } -- & 606 | 607 | 4060 EXP.FLAG%=-1% & 608 | \ FOR TOK.PTR%=1% TO LEN(EXPR$) & 609 | \ TOK.CHR$=MID(EXPR$,TOK.PTR%,1%) & 610 | \ EXP.FLAG%= NOT EXP.FLAG% IF TOK.CHR$="'" & 611 | \ OP%=INSTR(1%,"!%&*+-/",TOK.CHR$) & 612 | \ RETURN IF OP% AND EXP.FLAG% & 613 | \ NEXT TOK.PTR% & 614 | \ OP%=0% & 615 | \ TOK.PTR%=TOK.PTR%+1% & 616 | \ RETURN 617 | 4070 & 618 | ! -- Get value of term -- & 619 | 620 | 4080 TERM$=LEFT(EXPR$,TOK.PTR%-1%) & 621 | \ EXPR$=RIGHT(EXPR$,TOK.PTR%+1%) 622 | 4090 IF TERM$="" THEN TERM%=0% & 623 | \ RETURN 624 | 4100 ! -- H() or L() ? -- 625 | 4110 TEMP1$=LEFT(TERM$,2%) & 626 | \ IF TEMP1$="H(" THEN EXP.FLAG%=1% & 627 | ELSE IF TEMP1$="L(" THEN EXP.FLAG%=2% & 628 | ELSE EXP.FLAG%=0% 629 | 4120 IF EXP.FLAG% THEN IF RIGHT(TERM$,LEN(TERM$))=")" THEN & 630 | TERM$=MID(TERM$,3%,LEN(TERM$)-3%) & 631 | ELSE 4170 632 | 4130 TEMP1$=LEFT(TERM$,1%) 633 | 4140 IF TEMP1$>="A" AND TEMP1$<="Z" THEN TERM%=FNSYMBOL.LOOKUP%(TERM$) & 634 | ELSE IF TEMP1$="0" THEN TERM%=FNHEX.TO.DEC%(RIGHT(TERM$,2%)) & 635 | ELSE IF TEMP1$>="1" AND TEMP1$<="9" THEN TERM%=VAL(TERM$) & 636 | ELSE IF TEMP1$="'" THEN TERM%=ASCII(RIGHT(TERM$,2%)) & 637 | ELSE IF TEMP1$="^" THEN TERM%=FNOCT.TO.DEC%(RIGHT(TERM$,2%)) & 638 | ELSE IF TERM$="." THEN TERM%=LOCATION.COUNTER% & 639 | ELSE 4170 640 | 4150 IF EXP.FLAG%=1% THEN TERM%=SWAP%(TERM%) AND 255% & 641 | ELSE IF EXP.FLAG%=2% THEN TERM%=TERM% AND 255% 642 | 4160 RETURN 643 | 4170 TERM%=FNERROR.PRINT%("Invalid term = "+TERM$) & 644 | \ RETURN 645 | 4180 & 646 | ! -- Carry out the arithmetic or logical operation -- & 647 | 648 | 4190 ON LAST.OP%+1% & 649 | GOTO 4270, 4200, 4210, 4220, & 650 | 4230, 4240, 4250, 4260 & 651 | ! or not and & 652 | ! mult add sub div 653 | 4200 EXP.VAL%=EXP.VAL% OR TERM% & 654 | \ RETURN & 655 | ! or 656 | 4210 EXP.VAL%=EXP.VAL%+(NOT TERM%) & 657 | \ RETURN & 658 | ! not 659 | 4220 EXP.VAL%=EXP.VAL% AND TERM% & 660 | \ RETURN & 661 | ! and 662 | 4230 EXP.VAL%=EXP.VAL%*TERM% & 663 | \ RETURN & 664 | ! multiply 665 | 4240 EXP.VAL%=EXP.VAL%+TERM% & 666 | \ RETURN & 667 | ! add 668 | 4250 EXP.VAL%=EXP.VAL%-TERM% & 669 | \ RETURN & 670 | ! subtract 671 | 4260 IF TERM%=0% THEN EXP.VAL%=FNERROR.PRINT%("Division by zero") & 672 | ELSE EXP.VAL%=EXP.VAL%/TERM% 673 | 4270 RETURN 674 | 4280 & 675 | ! -- Exit with value of expression -- & 676 | 677 | 4290 FNEVALUATE.EXPR%=EXP.VAL% 678 | 4300 FNEND 679 | 4310 & 680 | ! -- Find value of argument of the type TYPE% & 681 | 682 | 4320 DEF* FNEVALUATE.ARGUMENT%(X$,TYPE%) & 683 | \ EXP.VAL%=FNEVALUATE.EXPR%(X$) 684 | 4330 IF TYPE%=1% AND (EXP.VAL%<0% OR EXP.VAL%>7%) THEN & 685 | EXP.VAL%=FNERROR.PRINT%("Invalid register id") & 686 | ELSE IF (TYPE%=2% AND EXP.VAL% AND 4%) OR & 687 | (TYPE%=3% AND EXP.VAL%>1%) THEN & 688 | EXP.VAL%=FNERROR.PRINT%("Invalid register pair") & 689 | ELSE IF TYPE%=7% AND (EXP.VAL%<0% OR EXP.VAL%>7%) & 690 | THEN EXP.VAL%=FNERROR.PRINT%("Invalid RST vector") 691 | 4340 FNEVALUATE.ARGUMENT%=EXP.VAL% & 692 | \ FNEND 693 | 4350 ! & 694 | 695 | 4360 & 696 | ! -- Print the given error message to the listing file & 697 | 698 | 4370 DEF* FNERROR.PRINT%(X$) & 699 | \ PRINT #1%,"********";X$; & 700 | \ IF PASS.NUMBER%=1% THEN PRINT #1%," at line";LINE.NUMBER% & 701 | ELSE PRINT #1% 702 | 4380 ERROR.COUNT%=ERROR.COUNT%+1% & 703 | \ ERROR.LINE.FLAG%=-1% & 704 | \ FNERROR.PRINT%=0% & 705 | \ FNEND 706 | 4390 & 707 | ! -- Look up value of symbol -- & 708 | 709 | 4400 DEF* FNSYMBOL.LOOKUP%(SYMBOL$) & 710 | \ X%=FNHASH.SYMBOL%(SYMBOL$,SYMBOL.TABLE.SIZE%) 711 | 4410 IF SYMBOLS$(X%)=SYMBOL$ AND FLAGS%(X%)<=0% THEN & 712 | FNSYMBOL.LOOKUP%=VALUES%(X%) & 713 | ELSE IF SYMBOLS$(X%)="" THEN FNSYMBOL.LOOKUP%= & 714 | FNERROR.PRINT%("Undefined symbol = "+SYMBOL$) & 715 | ELSE X%=FNREHASH.SYMBOL%(X%,SYMBOL.TABLE.SIZE%) & 716 | \ GOTO 4410 717 | 4420 FNEND 718 | 4430 & 719 | ! -- Dec to Hex conversion -- & 720 | 721 | 4440 DEF* FNDEC.TO.HEX$(X%,D%) 722 | 4450 X$="" & 723 | \ FOR X1%=0% TO 3% & 724 | \ X0%=(X% AND (16%^(X1%+1%)-1%*(16%^X1%)))/(16%^X1%) & 725 | \ X0%=X0%+16% IF X0%<0% & 726 | \ X$=CHR$(48%+X0%)+X$ IF X0%<10% & 727 | \ X$=CHR$(55%+X0%)+X$ IF X0%>9% & 728 | \ NEXT X1% & 729 | \ IF D% THEN X$=MID(X$,D%,2%) 730 | 4460 FNDEC.TO.HEX$=X$ 731 | 4470 FNEND 732 | 4480 & 733 | ! -- Hex to Dec conversion -- & 734 | 735 | 4490 DEF* FNHEX.TO.DEC%(X$) & 736 | \ X0%=0% & 737 | \ FOR X1%=1% TO LEN(X$) & 738 | \ X2%=ASCII(MID(X$,X1%,1%)) & 739 | \ IF X2%<48% OR (X2%>57% AND X2%<65%) OR X2%>70% THEN & 740 | FNHEX.TO.DEC%=FNERROR.PRINT%("Invalid HEX constant = "+X$) & 741 | \ GOTO 4510 742 | 4500 X2%=X2%-48% & 743 | \ X2%=X2%-7% IF X2%>9% & 744 | \ X0%=X2%+X0%*16% & 745 | \ NEXT X1% & 746 | \ FNHEX.TO.DEC%=X0% 747 | 4510 FNEND 748 | 4520 & 749 | ! -- Octal to Dec conversion -- & 750 | 751 | 4530 DEF* FNOCT.TO.DEC%(X$) & 752 | \ X0%=0% & 753 | \ FOR X1%=1% TO LEN(X$) & 754 | \ X2%=ASCII(MID(X$,X1%,1%))-48% & 755 | \ IF X2%<0% OR X2%>7% THEN & 756 | FNOCT.TO.DEC%=FNERROR.PRINT%("Invalid OCTAL constant = "+X$) & 757 | \ GOTO 4550 758 | 4540 X0%=X0%*8% + X2% & 759 | \ NEXT X1% & 760 | \ FNOCT.TO.DEC%=X0% 761 | 4550 FNEND 762 | 4560 & 763 | ! -- Calculate X1% modulo X2% -- & 764 | 765 | 4570 DEF* FNMOD%(X1%,X2%) & 766 | \ X1%=X1%-(X1%/X2%)*X2% & 767 | \ X1%=X1%+X2% IF X1%<0% & 768 | \ FNMOD%=X1% & 769 | \ FNEND 770 | 4580 & 771 | ! -- Hash symbol X$, modulo SYMBOL.TABLE.SIZE% -- & 772 | 773 | 4590 DEF* FNHASH.SYMBOL%(SYMBOL$,M%) & 774 | \ SYMBOL$=LEFT(SYMBOL$+" ",6%) & 775 | \ CHANGE SYMBOL$ TO SYMBOL.CHARS% & 776 | \ SYMBOL.CHARS%(X%)=SYMBOL.CHARS%(X%)-48% FOR X%=1% TO 6% & 777 | \ FNHASH.SYMBOL%=FNMOD%(SYMBOL.CHARS%(1%)*23%+ & 778 | SYMBOL.CHARS%(2%)*19%+SYMBOL.CHARS%(3%)*17%+ & 779 | SYMBOL.CHARS%(4%)*13%+SYMBOL.CHARS%(5%)*11%+ & 780 | SYMBOL.CHARS%(6%)*7%,M%) & 781 | \ FNEND 782 | 4600 & 783 | ! -- Rehash function, modulo X2% & 784 | 785 | 4610 DEF* FNREHASH.SYMBOL%(X1%,X2%)=FNMOD%(X1%+23%,X2%) 786 | 4620 & 787 | ! -- Quick sort symbol table & 788 | 789 | 4630 DEF* FNQUICKSORT%(LOW%,HIGH%,I%,J%) & 790 | \ I%=LOW% & 791 | \ J%=HIGH% & 792 | \ X$=SYMBOLS$((HIGH%+LOW%)/2%) 793 | 4640 I%=I%+1% WHILE SYMBOLS$(I%)J% THEN 4680 & 796 | ELSE IF I%<>J% THEN VALUE%=VALUES%(I%) & 797 | \ FLAG.WORD%=FLAGS%(I%) & 798 | \ SYMBOL$=SYMBOLS$(I%) & 799 | \ VALUES%(I%)=VALUES%(J%) & 800 | \ FLAGS%(I%)=FLAGS%(J%) & 801 | \ SYMBOLS$(I%)=SYMBOLS$(J%) & 802 | \ VALUES%(J%)=VALUE% & 803 | \ FLAGS%(J%)=FLAG.WORD% & 804 | \ SYMBOLS$(J%)=SYMBOL$ 805 | 4670 I%=I%+1% & 806 | \ J%=J%-1% & 807 | \ IF I%<=J% THEN 4640 808 | 4680 IF LOW%"" THEN CCL.ENTRY%=-1% ELSE CCL.ENTRY%=0% 823 | 30030 GOTO 1070 824 | 30999 ! & 825 | 826 | 31000 & 827 | ! -- Error routine -- & 828 | 829 | 31010 ! -- No ".END" -- 830 | 31020 IF ERR=11% AND ERL=2020% THEN OPCODE.TABLE.SUBSCRIPT%= & 831 | FNERROR.PRINT%("Missing .END")+ & 832 | FNHASH.SYMBOL%(".END",SYMBOL.TABLE.SIZE%) & 833 | \ SOURCE.LINE$="" & 834 | \ RESUME 2150 835 | 31030 IF ERR=11% AND ERL=3040% THEN SOURCE.LINE$="" & 836 | \ OPCODE.TABLE.SUBSCRIPT%=FNHASH.SYMBOL%(".END", & 837 | SYMBOL.TABLE.SIZE%) & 838 | \ RESUME 3080 839 | 31040 ! -- ^Z at filename request -- 840 | 31050 RESUME 32767 IF ERL=1160% 841 | 31060 ! -- Illegal number in FNEVALUATE.EXPR%() -- 842 | 31070 IF ERR=51% AND ERL=4140% THEN X0%=VAL(TERM$)-65536 & 843 | \ RESUME 4150 844 | 31080 RESUME 4170 IF ERR=52% AND ERL=4140% 845 | 31090 CLOSE 1%,2%,3%,4% & 846 | \ RESUME 32767% IF ERR=28% 847 | 31100 ! -- Print any unanticipated error -- 848 | 31110 ON ERROR GOTO 0 849 | 31999 ! & 850 | 851 | 32000 & 852 | ! -- Opcode data & 853 | 854 | 32010 ! Table is of the form: & 855 | ! SYMBOL,value,byte count & 856 | ! where: the low byte of value is the opcode base & 857 | ! and the high byte a flag consisting of & 858 | ! bits 15,14 a shift flag 0=none,2=four,3=three & 859 | ! bits 13-11,10-8 are arg2, arg1 types & 860 | ! 0-none, 1-register, 2-register pair, & 861 | ! 3-limited register pair, 4-data byte, & 862 | ! 5-data word, 6-address and 7-for RST 863 | 32020 DATA .END, 0, 10, .BYTE, 0, 11, & 864 | .DBYTE, 0, 12, .WORD, 0, 13, & 865 | .ASCII, 0, 14, .ASCIP, 0, 15, & 866 | .ASCIZ, 0, 16, .LIST, 0, 17, & 867 | .BLKB, 0, 18 868 | 32030 DATA CALL, 1741, 3, CC, 1756, 3, & 869 | CM, 1788, 3, CNC, 1748, 3, & 870 | CNZ, 1732, 3, CP, 1780, 3, & 871 | CPE, 1772, 3, CPO, 1764, 3, & 872 | CZ, 1740, 3 873 | 32040 DATA JC, 1754, 3, JM, 1786, 3, & 874 | JMP, 1731, 3, JNC, 1746, 3, & 875 | JNZ, 1730, 3, JP, 1778, 3, & 876 | JPE, 1770, 3, JPO, 1762, 3, & 877 | JZ, 1738, 3 878 | 32050 DATA LDA, 1594, 3, LHLD, 1578, 3, & 879 | SHLD, 1570, 3, STA, 1586, 3, & 880 | LXI, -22015, 3 881 | 32060 DATA ACI, 1230, 2, ADI, 1222, 2, & 882 | ANI, 1254, 2, CPI, 1278, 2, & 883 | ORI, 1270, 2, SBI, 1246, 2, & 884 | SUI, 1238, 2, XRI, 1262, 2, & 885 | IN, 1243, 2, OUT, 1235, 2, & 886 | MVI, -7930, 2 887 | 32070 DATA DJNZ, 17936, 2, JR, 17944, 2, & 888 | JRNZ, 17952, 2, JRZ, 17960, 2, & 889 | JRNC, 17968, 2, JRC, 17976, 2 890 | 32080 DATA ADC, 392, 1, ADD, 384, 1, & 891 | ANA, 416, 1, CMP, 440, 1, & 892 | ORA, 432, 1, SBB, 408, 1, & 893 | SUB, 400, 1, XRA, 424, 1, & 894 | DAD, -32247, 1, DCX, -32245, 1, & 895 | INX, -32253, 1, POP, -32063, 1, & 896 | PUSH, -32059, 1 897 | 32090 DATA DCR, -16123, 1, INR, -16124, 1, & 898 | LDAX, -31990, 1, STAX, -31998, 1, & 899 | MOV, -14016, 1, RST, -14393, 1 900 | 32100 DATA CMA, 47, 1, CMC, 63, 1, & 901 | DAA, 39, 1, EI, 251, 1, & 902 | HLT, 118, 1, NOP, 0, 1, & 903 | DI, 243, 1, PCHL, 233, 1, & 904 | RAL, 23, 1, RAR, 31, 1, & 905 | RC, 216, 1, RET, 201, 1, & 906 | RLC, 7, 1, RM, 248, 1, & 907 | RNC, 208, 1, RNZ, 192, 1, & 908 | RP, 240, 1, RPE, 232, 1, & 909 | RPO, 224, 1, RRC, 15, 1, & 910 | RZ, 200, 1, SPHL, 249, 1, & 911 | STC, 55, 1, XCHG, 235, 1, & 912 | XTHL, 227, 1 913 | 32110 DATA RIM, 32, 1, SIM, 48, 1, & 914 | EXX, 217, 1, EXAF, 8, 1 915 | 32120 !--Register symbol definitions 916 | 32130 DATA B, 0, C, 1, D, 2, & 917 | E, 3, H, 4, L, 5, & 918 | M, 6, A, 7, BC, 0, & 919 | DE, 1, HL, 2, SP, 3, & 920 | PSW, 3 921 | 32767 END 922 | -------------------------------------------------------------------------------- /micros/X80.HLP: -------------------------------------------------------------------------------- 1 | 2 | Cross Assembler for 8080/8085 A.G. Nicholson 3 | ---------------------------------------------- 4 | To enable users of 8080 based systems to quickly develop 5 | their application programs - by eliminating the tedious task of 6 | hand assembling, I have written a cross assembler for the use of 7 | interested persons. 8 | The cross assembler is written in DEC's Basic-plus(I) and is 9 | available for use on a PDP-11 series processor using the RSTS/E 10 | ( V06B onwards ) operating system. 11 | The following describes some of its features and gives the 12 | operating procedure using RSTS/E. 13 | 14 | * General features :- 15 | Input to the assembler consists of lines of mnemonics which 16 | have the general form :- 17 | 18 | label: opcode argument(s) ; comments 19 | 20 | Each of these lines is formed according to the following 21 | syntax rules :- 22 | 23 | 1) The label (if any) consists of up to six alphanumeric 24 | characters, the first of which must be alphabetic, 25 | followed by a colon ":". (eg: "LOOP:") 26 | 2) The opcode (instruction or assembler mnemonic) must 27 | be followed by at least one space or tab character if 28 | an argument is to be present. Standard mnemonics are 29 | used. 30 | 31 | 3) The argument (if required) consists of a valid 32 | expression, the form of which is determined by the 33 | opcode. For 8080/8085 instructions, these are :- 34 | 35 | a/ Input/Output instructions 36 | (IN,OUT) 37 | dev 38 | (eg: "IN 0FB" ) 39 | 40 | b/ Primary memory reference 41 | (LDAX,STAX) 42 | rp 43 | (LDA,STA,LHLD,SHLD) 44 | addr 45 | (eg: "LHLD COUNT") 46 | 47 | c/ Immediate 48 | (LXI rp,data16 49 | MVI reg,data ) 50 | (eg: "LXI HL,0" ) 51 | 52 | d/ Jumps 53 | (JMP,JC,JNC,JZ,JNZ,JP,JM,JPE,JPO) 54 | addr 55 | ( eg: "JMP LOOP" ) 56 | (PCHL) 57 | 58 | e/ Calls and returns 59 | (CALL,CC,CNC,CZ,CNZ,CP,CM,CPE,CPO) 60 | addr 61 | (eg: "CNC SUBR" ) 62 | (RET,RC,RNC,RZ,RNZ,RP,RM,RPE,RPO) 63 | f/ Immediate operate 64 | (ADI,ACI,SUI,SBI,ANI,XRI,ORI,CPI) 65 | data 66 | ( eg: "CPI 1" ) 67 | 68 | g/ Move 69 | ( MOV reg,reg ) 70 | ( eg: "MOV B,A" ) 71 | 72 | h/ Accumulator 73 | (ADD,ADC,SUB,SBB,ANA,XRA,ORA,CMP) 74 | reg 75 | ( eg: "ADD M" ) 76 | (DAD rp) 77 | ( eg: "DAD HL" ) 78 | 79 | i/ Register operate 80 | (INR,DCR) 81 | reg 82 | ( eg: "DCR B" ) 83 | (INX,DCX) 84 | rp 85 | ( eg: "DCX DE" ) 86 | (CMA,DAA,RLC,RRC,RAL,RAR) 87 | 88 | j/ Stack 89 | (PUSH,POP) 90 | rp 91 | ( eg: "PUSH BC" ) 92 | 93 | k/ Interrupt 94 | ( RST n ) 95 | ( eg: "RST 7" ) 96 | (EI,DI) 97 | and l/ Miscellaneous 98 | 99 | Also included are the Z80 relative branches and exchange 100 | instructions. 101 | (JR,JRNZ,JRZ,JRNC,JRC) 102 | ( eg: "JRNZ LOOP6" ) 103 | (EXX,EXAF) 104 | 105 | Where :- 106 | data,addr,data16 are arithmetic or logical expressions 107 | consisting of numeric constants and / or 108 | the operators :- 109 | ! logical OR 110 | % logical NOT 111 | & logical AND 112 | * multiplication 113 | + addition 114 | - subtraction 115 | / integer division 116 | H( ) high order byte 117 | L( ) low order byte 118 | 119 | Expressions are evaluated from left to 120 | right, and may not contain parentheses. 121 | 122 | reg is one of the 8 bit registers (A,B,C,D,E,H,L,M) 123 | 124 | rp is one of the register pairs (BC,DE,HL,SP,PSW) 125 | 126 | n is a restart vector ( 0 to 7 ) 127 | 128 | Some argument examples are :- 129 | 130 | 03E the hexadecimal constant "3E" 131 | ^377 the octal constant "377" 132 | 'D' the ascii value of "D" 133 | -120 the decimal integer constant 134 | "-120". (the range allowed is 135 | -32768 to +32767) 136 | L(ADDR)-1 the low order byte of the symbol 137 | "ADDR", minus 1. 138 | 139 | The currently available assembler directives are :- 140 | 141 | i) .BYTE or assigns the byte or double byte 142 | .DBYTE or expressions given in the argu- 143 | .WORD ment to current sequential addr- 144 | esses. '.WORD' allocates two bytes 145 | in 8080 address format, low byte 146 | followed by the high byte. 147 | (eg: ".BYTE 0F,LABEL,'A'") 148 | 149 | ii) = assigns to the symbol on its 150 | left the value of the expression 151 | on its right. 152 | (eg: "VALUE=OFFSET-START+1") 153 | 154 | A period "." is a special symbol 155 | used to specify the location 156 | counter. 157 | (eg: " .=01C0 ; start addr") 158 | 159 | iii) .ASCII translates the character string 160 | .ASCIP argument to ascii ( with parity 161 | set on the last character in the 162 | case of .ASCIP ) and assigns 163 | these values to the current 164 | sequential address(es). 165 | (eg: ".ASCII 'TEXT STRING'" ) 166 | 167 | iv) .LIST to enable/disable the listing of 168 | the source program in assembler 169 | output. If the value of the expr 170 | given is zero, the listing is 171 | disabled, else it is enabled. 172 | (eg: ".LIST 0 ; no list") 173 | 174 | v) .BLKB reserves the number of bytes 175 | given in the argument expression 176 | (eg: ".BLKB 0100 ; buffer area") 177 | 178 | vi) .END to tell the assembler it has 179 | reached the end of your source 180 | program. This statement must 181 | be included as the last line of 182 | source. 183 | 184 | 4) The (optional) comments are proceeded by a semi-colon 185 | ";" and may contain any other character. The label, 186 | opcode and argument fields may be omitted for a 187 | comment line. A line with a dollar "$" sign as the 188 | first character is treated as a comment line and 189 | is printed to the listing file minus the "$" sign. 190 | 191 | * Use of assembler on RSTS/E :- 192 | 193 | After logging on to the system, perform the following steps :- 194 | 195 | (1) Enter the source program into a file on the system 196 | using the $PIP or $EDIT programs or the "CREATE" command 197 | 198 | (2) Run the cross assembler by typing "RUN !X80", 199 | responding to the "#" sign with a command string of the 200 | form: eg: LIST=PROG/switch(es) 201 | which directs the listing to the file "LIST.LST" from the 202 | source file "PROG. SRC". The switch(es) are optional but 203 | /E specifies an errors only listing 204 | /O specifies an object module output, in the format 205 | of a hexadecimal dump in ASCII, 16 bytes/line. 206 | (this is useful for later punching of paper tape) 207 | /S specifies that the sorted symbol table be printed. 208 | Only specifying the source file ( eg: PROG ) causes all 209 | output to the user's terminal. 210 | 211 | (3) If any errors are detected, it is neccessary to edit 212 | the source file using the $EDIT program or the "EDIT" 213 | command, and repeat step 2 above until no errors are 214 | detected. 215 | 216 | Any queries ? - don't hesitate to contact Tony Nicholson c/o 217 | Electrical Engineering Department, for advice or help with your 218 | problems regarding the cross assembler. You might also want to 219 | attend on the second and fourth Mondays of the month in Physics 220 | building room G12 at 7pm, when the Newcastle Microcomputer Club 221 | meets. 222 | -------------------------------------------------------------------------------- /micros/X80.TSK: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/micros/X80.TSK -------------------------------------------------------------------------------- /micros/X80BLD.COM: -------------------------------------------------------------------------------- 1 | $! Command file to build X80.B2S (with Basic-Plus-2) 2 | $! 3 | $ set noOn 4 | $ run $bp2ic2 5 | SCALE 0 6 | OLD X80.B2S 7 | COMPILE X80/OBJECT/CHAIN/NODEBUG/NOCROSS/NOLIST/NOWARN 8 | BUILD X80 9 | SCRATCH 10 | EXIT 11 | $ tkb @X80 12 | $ del x80.odl, x80.obj, x80.cmd 13 | $ exit 14 | -------------------------------------------------------------------------------- /photos/DECtape-RSTS-E-V06B.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/photos/DECtape-RSTS-E-V06B.jpeg -------------------------------------------------------------------------------- /software/ahl_basic_games.dta: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/software/ahl_basic_games.dta -------------------------------------------------------------------------------- /software/rk05-games-rsts0-0.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/software/rk05-games-rsts0-0.dsk -------------------------------------------------------------------------------- /software/rl01-games-rsts0-0.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/software/rl01-games-rsts0-0.dsk -------------------------------------------------------------------------------- /software/rl01-games.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/software/rl01-games.dsk -------------------------------------------------------------------------------- /software/rl02-ker363.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/software/rl02-ker363.dsk -------------------------------------------------------------------------------- /software/rl02-zemu25.dsk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/agn453/RSTS-E/273b5a0958bcc3ec89a5f49b943f2fcac1fe23e3/software/rl02-zemu25.dsk --------------------------------------------------------------------------------