ELECTRON SECOND PROCESSOR Speed up your Electrons and watch your memory expand with a 6502 second processor, designed by John Wike with Electron wners in mind. This article describes the addition of a second processor board to an Acorn Electron, making 30K bytes of RAM available to BASIC (60K to achine code), and giving an increase in processing speed of up three times. The hardware will be described this month and the software next month, together with a complete assembly listing. What about the others? Although the term 'second processor' is usually associated with Acorn and their 'Tube' system, multiprocessor designs are found in several microcomputers in the business and scientific markets. Even the Sinclair QL contains two microprocessors, one to handle input/output and the other to do the computing. So, although the circuit shown here is designed specifically for the Acorn machines, the concept is generally applicable. It is relatively straightforward to design a circuit board with a processor and some RAM on it, and to interface it with an existing computer system. The real problem is the software, machine code of course, to handle the new hardware. As the host machine probably has the screen RAM within its memory map, it must be assumed at it will retain the input/output handling functions. This means that the language (usually BASIC II) operates in the second processor. It is necessary to know how to intercept the input/output routines (PRINT, INPUT, SAVE, LOAD, etc.) so that the data will be transferred to or from the second processor's memory instead of the host's. Routines can then be written to reside in each processor's memory and allow them to communicate with each other transparently, so that the user will not be aware of any difference in operation from the basic machine. All this sounds involved, but given a machine that is well supported by reference material and ROM listings, or your own skill at disassembly, it is by no means impossible. So if you are interested have a go! 2P or not 2P? The owner of an Acorn machine does not need to worry about the foregoing because this article will cover all the ground. He or she will however have to decide whether it is worthwhile adding a second processor to the system. There are several advantages to balance against the effort involved: Speed The benchmark system has gained widespread acceptance as a qualitative assessment of the processing speed of a computer. For a full discussion of benchmarks the reader is referred to the February 1985 edition of Computing Today. Benchmark Mode 6 Mode 0 E2P (BBC) 1 0.93 2.11 0.68 0.8 2 4.01 9.35 2.99 3.1 3 11.54 26.97 8.43 8.3 4 12.27 28.86 8.95 8.7 5 12.85 30.15 9.37 9.1 6 19.51 45.72 14.35 13.7 7 30.09 69.88 22.24 21.3 Table 1 Benchmark timings for the Electron with and without E2P. Each test consists of 1000 iterations of specific instructions, the times for which are given in Table 1. Also included for interest are the timings for the BBC computer, taken from the Computing Today article. In Mode 6 the unexpanded Electron is approximately 50% slower than the BBC, and in Mode 0 it is 250% slower! With the E2P board fitted it is approximately the same as the BBC in all modes. Memory The display memory in the Electron can consume between 8K of RAM in Mode 6 and 20K of RAM in Modes 0, 1 and 2. Add to this the 3.5K used as operating system workspace, up to 1.5 K for user-defined characters and an extra 3.75K if the Plus 3 disc drive is fitted, and out of a total of 32K there might only be 3.25K available for programs. The E2P board contains 64K RAM, 30K of which can be used from BASIC whatever the configuration. Machine code programs can use a massive 60K. Processor The first requirement of the design was that the hardware and software should react with the Electron operating system in the same way as the official 'Tube'. 32 ETI JUNE 1985 PROJECT This is a ULA with eight bidirectional registers, addressed at FCE0h to FCE7h, of which seven are used by the support software and only one, at FCE5h, is accessed directly by the operating system for data transfer during, for example, LOAD and SAVE. So the circuit must detect accesses at FCE5h and interrupt the second processor to allow it to pass the required data. The other registers can be at any convenient address, since they have their own support software. The only storage device on the board is the RAM. The top 256 bytes of that are accessible to the Electron, so that several locations can be used as the bidirectional registers. Also, as this is the area where the 6502 goes at Reset, the Electron can control its reset and transfer sufficient code there beforehand to allow it to "boot up'. After that the rest of its operating system can be sent via the data byte at FCE5h. When deciding where in the Electron memory map to locate this 256 byte block, it was remembered that sideways ROMs are given the opportunity to initialise themselves at BREAK and to declare themselves during the *HELP command. The block is therefore addressed as a sideways ROM and the first eleven or so bytes are taken up with the necessary data for it to be recognised by the operating system. They also contain a jump instruction so that the 'ROM' software can be in the main program in the Electron RAM. In order to refresh the dynamic RAM the processor is interrupted every 1ms and a specific routine scans 128 bytes in 64us. On alternate interrupts it scans another 128 bytes to include all the rows in the RAM. This results in a time overhead of 6% which is considered acceptable by the author. Because the refresh is software controlled there is no facility for a hard reset of the processor. Instead, the 'sideways ROM' routine issues an initialisation request on BREAK. Interfacing The board is designed to slot into one of the cartridge sockets on the Plus One interface unit, which provides some of the address decoding. For those people without a Plus One, a circuit is shown allowing connection to the basic Electron. Current consumption of the board is about half an amp, which the author's machine was able to cope with. If a lot of other devices are drawing power, it may overload the supply. A link (LK1) is provided to disconnect the 5 volt line from the edge connector and an alternative supply can then be connected to the board. Construction Construction of this project is straightforward but you are recommended to use a fine tipped soldering iron, and to check the board closely to see that no stray bits of swarf or solder are shorting tracks. The author's prototype second processor board (some changes have been made in the final version). ETI JUNE 1985 33 As this is a double sided PCB and is not plated through, the first thing is to insert all the links and solder them on both sides of the board. Take special care not to miss the ones underneath ICs as these will be impossible to fit afterwards. Fig. 1 Block diagram of the second processor board. Fig. 2 PCB overlay for the second processor. 34 ETI JUNE 1985 PROJECT: Second Processor Next fit all the ICs except the RAMs and the processor, soldering their leads on the bottom, top or both, as necessary. Next fit the resistors, capacitors and diode. Some of these components need to be soldered on both sides of the board. Now fit the sockets for the RAMs and processor. Use insulating tape to protect the throueh-board links before inserting the sockets. If you intend to power the board from the Electron's 5 volt line fit the link LK1. Otherwise, connect the external supply wires to points A (0 volt) and B (5 volts). Finally, insert the RAMs and processor into their sockets. If you do not have the Plus One unit you will aow have to construct the interface circuit. This could be done on Veroboard and then connected, along with the second processor board, to the Electron with a short length of ribbon cable and a 25 pin double-edge connector. Fig. 3 Circuit diagram of the second processor Fig. 4 Plus One cartridge socket edge connector. ETI JUNE 1985 35 HOW IT WORKS The second processor is reset at switch on by latch IC8a with C4 and R12. Diode D1 ensures that C4 will be discharged quickly at switch off. IC8 is a quad S-R latch with Set overriding Reset. Sections c and d are used to provide extra AND functions. Decoding of the host processor address bus is performed by IC17, IC8d and IC1f. When either the sideways ROM or FCE5h are accessed, the output of IC17a will go low. This signal enables the data bus buffer, IC18. It also disables the second processor address multiplexers IC2 and IC3, after being inverted by IC1a, and it operates the control line multiplexer IC5. IC5 determines which processor's R/W and clock signals will be applied to the RAM - when Pin 1, select, is low the second processor clock and R/W times are effectively disabled. The second processor 2MHz clock is generated by IC4 dividing down the master system 16MHz oscillator. Further division takes place in IC4 and IC6 to give the 1ms NMI signal. Note that as the processor only responds to negative edges there is no need to provide short pulses. The output of IC17a is combined with the host processor clock in IC8c, which triggers the 15us IRQ monostable IC8b. The monostable is inhibited during ROM selection by the input at pin 11 so that it will only operate during an access at FCE5h. The monostable output is also fed to IC8a to clear the second processor reset. The output of IC8c goes via IC1b to set the second processor clock in phase with the host's during host access. Because the clocks are in phase, the control multiplexer IC5 can be guaranteed to switch when they are both low. Tri-state buffer IC7 with resistors R3-R10 performs the address multiplexing function for host processor addresses. It is enabled during the first part of a host access to give the row addresses for the RAMs, then it is disabled and the resistors provide the column addresses. If it is a ROM address, IC8d output will be high and page FFh will be accessed. For address FCE5h, IC8d will be low and page FEh will be accessed. The RAS signal to the RAMs is provided by IC1c and the CAS signal by IC1d and IC1e from the delay circuit R2-C3. PARTS LIST - INTERFACE RESISTOR R13 470R CAPACITOR C15 220p SEMICONDUCTORS IC20 74LS30 IC21 74LS27 IC22 74LS20 IC23 74LS139 IC24 74LS74 MISCELLANEOUS Veroboard, 22-way double sided socket to fit E2P edge connector, 25-way double sided socket to fit Electron edge connector. Setting up Before switching on, check the board very carefully for shorted tracks and the orientation of ICs, diodes and electrolytic and tantalum capacitors. To ensure that the Electron will will not be damaged check every contact on the edge connector with a meter for shorts to either the 0 volt or 5 volt supply lines. Connect the board and switch on. You should get the start-up message as usual. If not, then switch off and check again for shorts. If you can get hold of a double-beam oscilloscope, connect a probe to pin 9 of IC8 and enter and run the following program: 10 A%=?&FCE5:GOTO10 You should see on the 'scope a negative going pulse 15ms wide. If it is different width adjust the values of R11 and/or C5 to get it as close as possible. Now connect one input of the scope to IC1 pin 1 and the other input to ICI pin 6. The negative going edge of the signal on pin 6 should occur between 120 and 150ns after the positive going edge at pin 1. Adjust R2 and/or C3 as neccesary. Before trying the system in earnest you will have to switch off then on again in order to hard reset second processor. The necessary software will be included in next month's article, but in meantime a copy of the assembly code is available on tape from the author. Alternatively, if you send a Plus Three disc it can be stored on that together with the machine code as a !BOOT file so that pressing shift-break will automatically boot in the second processor. See Buylines for details. Fig. 4 Suggested interface circuit to link basic Electron and the second processor. Fig. 5 Electron edge connector 36 ETI JUNE 1985 PROJECT: Second Processor PARTS LIST - MAIN BOARD RESISTORS (all 1/4 watt) R1,2,3,4,5,6,7,8,9,10 470R R11 390R R12 4k7 CAPACITORS (all ceramics unless stated) C1 470p C2 33p C4 100u electrolytic C5 47n C6,7,8 47u 10V tantalum C9,10,11,12,13,14 100n SEMICONDUCTORS IC1 74LS14 IC2,3 74LS257 IC4,6 74LS393 IC5 74LS157 IC7,18 74LS245 IC8 74LS279 IC9,10,11,12,13,14,15,16 4164-15/4864P-2 IC17 74LS21 IC19 6502A (2MHz) D1 1N4148 MISCELLANEOUS 40 pin DIL socket, 8x16 pin OIL sockets, wire for links. BUYLINES All the components are available readily from advertisers in ETI. The PCB and software are available from the author, John Wike, at 9, Lon-y-Garwa, Caerphilly, Mid-Glamorgan. The price of the PCB is £12, software on tape is £3.50, and on your disc £2.00, inclusive of postage, if you send a disc please state whether you wish to have the !BOOT file put PROJECT ELECTRON SECOND PROCESSOR It doesn't take ESP to know that we're dealing with the software for John Wike's Electron add-on. Having described the hardware for this project last month, it is now time to consider the software. When RUN the program creates a 2K machine code file on tape or disc called E2PCODE. This latter is what must be *RUN to operate the second processor. Alternatively, if you have a disc it can be renamed as !BOOT and run using shift-break. The listing given in this article has been produced using a formatting program to line it up nicely. If you intend to enter it yourself you must leave out all the spaces (except those after the'.' labels) or it will not fit into memory. The beauty of the Acorn machines is that in order to intercept the input/output operations of any language it is only necessary to modify eleven well-documented operating system (OS) routines. Detailed descriptions of these can be found 'The Acorn Electron Advanced User Guide' by Holmes and Dickens, and 'The Advanced User Guide for the BBC Micro' by Bray, Dickens, Holmes. The operating system calls are the same for both machines and while one book also covers the special hardware in the Electron, the other is more readily in the shops. Memory Usage In this article the Electron processor will be referred to as the I/O processor because that is its function in the new environment. The second processor will be called 2P for short. The E2PCODE program loads into addresses 2800h to 2FFFh in the I/O memory, as shown in the map. This is below the highest resolution screen. It uses memory (again I/O) at 0 to 70h and 400h to 40Bh so it is important that no user programs corrupt these three areas of I/O memory. The main program is in three sections. Lines 190 to 4880 run where they are in I/O memory. Lines 5930 to 7250 are copied to the 256 byte sideways ROM area and exist at 8000h in I/O memory and FF00h in 2P memory. Finally, lines 7300 to 11100 are passed to 2P memory at F800h to FAFFh. Communication The processors communicate with each other by way of various locations in 2P RAM which are used as status and data registers. Their functions are listed in Table 1 and, together with the 28byte Oswrch buffer, they overwrite the 2P reset routine in lines 6020 to 6230. As there is no hard reset that routine is not needed again anyway. With all the registers, except the buffer pointers, a zero value indicates that the message data has been received and acted on. Address I/O (2P) Function Possible Values 800D(FF0D) h Pass Instruction to 2P 8 h Start memory read(0) 9 h Start memory write(1) C h Run program(4) 28 h Stop memory read/write 40 h Handle Event code 80 h Pass BRK error message C0 h Set/Reset Escape flag FF h Initialise 2P (Reset) 8013(FF13) h Pass OS call to I/O LSB Address of I/O OS routine 8014(FF14) h Flush Oswrch buffer flag Equal to 801 E(FF1E) h 8019(FF19) h Status for I/O to2P 40 h Data is text 80 h Data is not text C0 h End of data 801A(FF1A) h Data for I/O to 2P 801B(FF1B) h Status for 2P to I/O As for 8019(FF19) h 801C(FF1C) h Data for 2P to I/O 801D(FF1D) h Oswrch buffer remove pointer Pointers equal if buffer empty 801E(FF1E) h Oswrch buffer insert pointer " Table 1. Communication protocols. Facilities This implementation has the ability to reset into the I/O processor by pressing B-break, ie hold down the B key while pressing BREAK. Programs can then be developed in the I/O memory without switching off. In I/O HIMEM is set to 2800h to protect the program. In 2P HIMEM is 8000h and PAGE is 800h. If you execute *HELP while in 2P you will get the message "E2P 0.10". This does not appear if you are in the I/O. Just one word of warning. Do not use any EVENT handlers in 2P that call OS routines. If you do the system will most probably hang up. You will have to find out by trial and error which programs will work with a second processor. Anything that accesses screen memory or hardware directly will not work, since this can only be done by OS commands across the interface. ETI JULY 1985 43 HOW IT WORKS I/O OPERATION When the program is run the I/O processor enters the cold start routine at line 1250. At lines 1350 to 1630 it checks each ROM number from 7 down to 0 for a block of RAM of 256 bytes or less. If it finds one it assumes that it is the E2P card and stores the ROM number in location 'this ROM', if not it returns to the language ROM and returns the error 'No E2P'. If the ROM is not logged in already (1640-1670), it then cycles through the RAM (1690-1720), loads the RAM (1740-1770) and clears the 2P reset (1780). The RAM is then cycled to refresh it (1800-1820) until the 2P signals that it is ready (1830-1840). It then initiates a 2P memory write and transfers the 2P operating system routines over (1860-2040) before soft resetting itself (2050). During I/O reset the operating system calls the sideways ROM service routines at 8003h (line 5940) with the Tube reset code FEh in the accumulator. This is detected at line 2350 and the Osbyte vector is changed (2480-2570) to allow the new routine (3000-3140) to set HIMEM and inhibit the memory clear facility. Lines 2590-2670 check for the B key (64h in line 2630). If it is not pressed the Tube presence at Osbyte EAh and the IO/second processor flag at isec are set. The 2P is initialised (2700-2740). The vectors are changed, the soft character set is exploded, the filing system status is set and the sign on message is printed (2670-2920) before leaving the service routine. Before the I/O can communicate with the 2P it must select the correct sideways ROM location. This is done with the routine at 3230-3320. If the Tube presence flag is set during I/O reset the operating system will not start up a language but will jump instead to location 400h. This has been loaded at line 2690 (via lines 380-430) with the code in lines 210-240. So it will enter the warm start routines at line 4120. Pointers are set up to transfer the current language to 2P memory either at 8000h (4130-4180) or at a specified relocation address (4190-4300). If the language has been selected by a * command (4320), or if this is a cold start (4330-4340), or if it is a hard reset (4350-4370), and it is not Plus One control ROM at 0Ch (4380-4410), then the language will be transferred to 2P memory (4430-4550). The language will then be started up in 2P by issuing a Run Program command (4590-4680). The actual routines to give instructions to 2P start at line 3340. The operating system will enter these via the relocated line 230 at 406h, but they are called directly within this program. Lines 3340-3500 allow different filing systems to claim the 2P interface by entering with their Tube ID number plus C0h in the accumulator and waiting for the carry flag to be set. They release the interface using 80h plus the ID number. The read, write and run instructions (0, 1 and 4 respectively) enter with YX pointing to four consecutive locations which hold the action address for the 2P. This address is sent in lines 3550-3660 then the actual instruction number ORed with 8 so that it cannot be zero is sent (3690-3710). If the instruction is to run a program, the I/O processor will enter its main loop, otherwise it will return (3740-3820). The main loop routine (5540-5880) maintains the rotating Oswrch buffer remove pointer at 801D(FF1D)h. If the buffer is not empty its contents are printed. If it is empty the status register at 8013(FF13)h is examined and an OS call is executed if desired. I/O 2P +-------------------+ &FFFF +-------------------+ &FFFF | OS ROM | | OS | +-------------------+ &FF00 +-------------------+ &FF3B | | | | +-------------------+ +-------------------+ &FF00 | "TUBE" BYTE | | "TUBE" BYTE | +-------------------+ &FCE5 +-------------------+ &FEE5 | | | | +-------------------+ &FC00 +-------------------+ &FC00 | | | RAM REFRESH | | OS ROM | +-------------------+ &FB00 | | | | +-------------------+ &C000 | OS | | REPEATS OF | | | | &8000 - &80FF | +-------------------+ &F800 +-------------------+ &8100 | UNUSED WITH | | | | NORMAL LANGUAGES | +-------------------+ &803B +-------------------+ &C000 | OSWRCH BUFFER | | | +-------------------+ &801F | LANGUAGE | | STATUS/DATA | | BASIC/VIEW ETC | | REGISTERS | | | +-------------------+ &800D +-------------------+ &8000 | SIDEWAYS ROM | | | | RECOGNITION CODE | | | +-------------------+ &8006 | | | SIDEWAYS ROM | | | | ENTRIES | | | +-------------------+ &8000 | | | DISPLAY | | USER PROGRAM | +-------------------+ &6000 | AREA | | HIGH RES DISPLAYS | | | +-------------------+ &3000 | | | E2P SOFTWARE | | | +-------------------+ &2800 | | HIMEM | USER PROGRAM | | | | AREA | | | +-------------------+ &1D00 | | PAGE | | | | +-------------------+ &0E00 +-------------------+ | | | | | OS/LANGUAGE | | OS/LANGUAGE | | WORKSPACE | | WORKSPACE | | | | | +-------------------+ &0000 +-------------------+ &0000 Memory maps of Electron and second processor board. 2P OPERATION When the 2P reset is cleared it jumps via its reset vector at FFFCh (7240) to line 6020. Here it loads a 128 byte RAM refresh routine twice into FB00h to FBFFh. This consists of 'compare accumulator immediate' instructions (C9h), which are two bytes long and take two cycles to execute. Thus it will access 128 bytes in 128 cycles, or 64 microseconds. The last few bytes of the routine contain lines 6170-6230 which modify the calling routine to scan the other 128 bytes next time round (6170-6190) and check the status register at 800D(FFOD) h to see if any instructions need to be executed. Normally the NMI routine (6400-6420) will call the cycle routine (6350-6380) to perform the refresh. However while the I/O is writing or reading 2P memory via the data register at FCE5(FEE5)h the 2P must respond quickly to the IRQ line. So the NMI is disabled and the 2P goes into the loop (6680-6700) where it is continually cycling to do the refresh. The read/write function is performed by modifying the three locations at ivec (6270) in the irql routine (6250-6330) to read or write the specified start address (6470-6550). If it is a read the first location is read by a software interrupt (6610-6620). The other instructions are looked for in the test routines (7460-8310) and the appropriate action taken. The 2P OS routines (8330-9720) interact with their I/O counterparts (450-1230) via the register at 8013(FF13)h. Some routines need to pass over the processor A,X and Y registers. Some need to pass text and some need block data. These are handled by the routines at lines 4700-5360, 6730-6780, and 9740-10320. The Osword routines transfer different amounts of different size blocks. The tables at 10480-10910 are used to determine how much to send. The 2P Osbyte routine checks for the memory functions 82h to 84h (8420-8540). these give the machine high order address (FFFFh for I/O, 0000h for 2P), PAGE, HIMEM, and HIMEM in other Modes, in that order. It also checks (8560-8640) whether the Oswrch buffer is being flushed (Osbyte DAh,0,0) and sets the flag at 8014(FF14)h. 44 ETI JULY 1985 PROJECT: Processor Listing of Electron program to run second processor. Copyright John Wike, 1985. 50 REM AS SPACE IS SHORT WHEN 60 REM USING DISCS, THE CODE IS 70 REM ASSEMBLED INTO SCREEN 80 REM MEMORY BEFORE SAVING. 90 : 100 MODE6:VDU28,0,24,39,12 110 : 120 rgX=&F0:txt=&F2:rpl=&F4 130 blk=&96:num=&98:tmp=&99 140 cmd=&9A 150 : 160 U%=&2800:V%=&6500:HIMEM=V% 170 A%=U%:B%=U% 180 FOR I=4TO6STEP2 190 O%=V%:P%=U% 200 [OPT I 210 JMP cold 220 : 230 .cod400 240 JMP warm 250 JMP esc 260 JMP instr 270 .osjmp 280 JMP osrdch 290 : 300 .pload 310 LDA (0),Y 320 INC 0 330 BNE pload2 340 INC 1 350 : 360 .pload2 370 STA &FCE5 380 : 390 LDY #7 400 .delay 410 DEY 420 BNE delay 430 RTS 440 : 450 .codld 460 LDX #&C 470 .codld5 480 LDA cod400-1,X 490 STA &3FF,X 500 DEX 510 BNE codld5 520 RTS 530 : 540 .osrdch 550 JSR &FFE0 560 .osrd1 570 JSR regso2 580 .osret 590 LDA #0 600 STA &8013 610 .anrts 620 RTS 630 : 640 .oscli 650 JSR datin 660 JSR &FFF7 670 JMP osret 680 : 690 .osbyte 700 JSR regsin 710 JSR &FFF4 720 JSR regsout 730 JMP osret 740 : 750 .osword 760 LDA &8016 770 BNE oswd5 780 JSR datin 790 STX 0 800 STY 1 810 TXA 820 TAY 830 JSR &FFF1 840 JSR regso3 850 JSR osret 860 BCS anrts 870 JMP txtout 880 : 890 .oswd5 900 LDY #&20 910 JSR datin1 920 LDX #&20 930 LDY #0 940 LDA &8016 950 JSR &FFF1 960 JSR osret 970 JSR regsin 980 JMP blkout2 990 : 1000 .osargs 1010 JSR datin 1020 JSR regsi1 1030 JSR &FFDA 1040 JSR osrd1 1050 JMP blkout 1060 : 1070 .osbget 1080 JSR regsi1 1090 JSR &FFD7 1100 JMP osrd1 1110 : 1120 .osbput 1130 JSR regsi1 1140 JSR &FFD4 1150 JMP osret 1160 : 1170 .osfind 1180 JSR regsi1 1190 BEQ osf5 1200 PHA 1210 JSR datin 1220 PLA 1230 .osf5 1240 JSR &FFCE 1250 JMP osrd1 1260 : 1270 .osfile 1280 JSR datin 1290 JSR datin 1300 STX 0 1310 STY 1 1320 LDY #0 1330 LDA &8016 1340 JSR &FFDD 1350 JSR osrd1 1360 LDX #&12 1370 LDY #2 1380 JMP blkout2 1390 : 1400 .osgbpb 1410 JSR datin 1420 LDY #0 1430 LDA &8016 1440 JSR &FFD1 1450 JSR osrd1 1460 LDX #&D 1470 JMP blkout1 1480 : 1490 .cold 1500 SEI 1510 LDA #&40 1520 STA &D00 1530 LDA #&AA 1540 LDX #0 1550 LDY #&FF 1560 JSR &FFF4 1570 STX &F6 1580 STY &F7 1590 : 1600 LDX &F4 1610 LDY #7 1620 .cold1 1630 TYA 1640 JSR sidesel 1650 LDA &8000 1660 CMP &8100 1670 BNE cold5 1680 EOR #&FF 1690 STA &8000 1700 CMP &8100 1710 PHP 1720 EOR #&FF 1730 STA &8000 1740 PLP 1750 BEQ cold7 1760 : 1770 .cold5 1780 DEY 1790 BPL cold1 1800 TXA 1810 JSR sidesel 1820 BRK 1830 BRK 1840 EQUS "No E2P" 1850 BRK 1860 : 1870 .coldvec 1880 EQUW tclear 1890 : 1900 .cold7 1910 STY thisROM 1920 LDA (&F6),Y 1930 BEQ cold10 1940 CMP &8006 1950 BEQ cold16 1960 : 1970 .cold10 1980 LDX #0 1990 .cold11 2000 LDA &8000,X 2010 INX 2020 BNE cold11 2030 : 2040 .cold12 2050 LDA B%,X 2060 STA &8000,X 2070 INX 2080 BNE cold12 2090 LDA &FCE5 2100 : 2110 .cold15 2120 LDA &8000,X 2130 INX 2140 BNE cold15 2150 LDA &800D 2160 BNE cold15 2170 : 2180 .cold16 2190 LDX #coldvec MOD 256 2200 LDY #coldvec DIV 256 2210 LDA #1 2220 JSR instr 2230 : 2240 LDA #C% MOD 256:STA 0 2250 LDA #C% DIV 256:STA 1 2260 LDY #0 2270 STY langflg 2280 : 2290 .cold17 2300 JSR pload 2310 LDA 0 2320 CMP #D% MOD 256 2330 BNE cold17 2340 LDA 1 2350 CMP #D% DIV 256 2360 BNE cold17 2370 JMP (&FFFC) 2380 : 2390 .message1 2400 EQUB &D 2410 EQUS "E2P 0.10" 2420 EQUB &D 2430 EQUB 0 2440 : 2450 .message2 2460 EQUS "SECOND PROCESSOR" 2470 EQUB &D 2480 EQUB &D 2490 EQUB 0 2500 : 2510 .prnmes 2520 LDX #0 2530 .prnmes2 2540 LDA message1,X 2550 BEQ prnmes5 2560 JSR &FFE3 2570 INX 2580 BNE prnmes2 2590 .prnmes5 2600 RTS 2610 : 2620 .Rserv 2630 CPX thisROM 2640 BNE Rserv3 2650 : 2660 CMP #9 2670 BNE Rserv2 2680 BIT isec 2690 BPL Rserv2 2700 JSR prnmes2 2710 LDA #9 2720 : 2730 .Rserv2 2740 CMP #&FE 2750 .Rserv3 2760 BNE Rserv15 2770 : 2780 TYA 2790 PHA 2800 JSR &FFE7 2810 LDA #&A6 2820 LDX #0 2830 LDY #&FF 2840 JSR &FFF4 2850 STX &1D 2860 STY &1E 2870 : 2880 LDA &20B 2890 CMP #newosb DIV 256 2900 BEQ Rserv5 2910 STA oldosb+1 2920 LDA &20A:STA oldosb+0 2930 LDA #newosb DIV 256:STA &20B 2940 LDA #newosb MOD 256:STA &20A 2950 : 2960 .Rserv5 2970 LDA #&7A 2980 JSR &FFF4 2990 LDY #0 3000 STY isec 3010 CPX #&64 3020 BNE Rserv7 3030 LDA #&78 3040 JSR &FFF4 3050 JMP Rserv10 3060 : 3070 .Rserv7 3080 JSR codld 3090 LDA #&FF 3100 STA isec 3110 LDY #&EA 3120 STA (&1D),Y 3130 JSR pcomm 3140 : 3150 LDA #brk MOD 256:STA &202 3160 LDA #brk DIV 256:STA &203 3170 LDA #event MOD 256:STA &220 3180 LDA #event DIV 256:STA &221 3190 : 3200 LDA #&14 3210 LDX #6 3220 JSR &FFF4 3230 LDA #&80 3240 STA &14 3250 : 3260 LDX #message2-message1 3270 JSR prnmes2 3280 : 3290 .Rserv10 3300 PLA 3310 TAY 3320 LDA #0 3330 .Rserv15 3340 LDX &F4 3350 RTS 3360 : 3370 .newosb 3380 CMP #&84 3390 BEQ newosb2 3400 CMP #&85 3410 BNE newosb5 3420 .newosb2 3430 LDX #A% MOD 256 3440 LDY #A% DIV 256 3450 RTS 3460 : 3470 .newosb5 3480 CMP #&C8 3490 BNE newosb7 3500 TXA 3510 AND #&FD 3520 TAX 3530 LDA #&C8 3540 .newosb7 3550 JMP (oldosb) 3560 : 3570 .pcomm 3580 STA &800D 3590 .pstat 3600 NOP 3610 NOP 3620 LDA &800D 3630 BNE pstat 3640 RTS 3650 : 3660 .pselect 3670 LDA thisROM 3680 JSR sidesel 3690 JMP pstat 3700 : 3710 .sidesel 3720 STA &F4 3730 LDA #&C 3740 STA &FE05 3750 LDA &F4 3760 STA &FE05 3770 RTS 3780 : 3790 .instr 3800 CMP #&80 3810 BCC instr4 3820 CMP #&C0 3830 BCC instr3 3840 ASL &14 3850 BCS instr1 3860 CMP &15 3870 BEQ instr2 3880 CLC 3890 RTS 3900 .instr1 3910 STA &15 3920 .instr2 3930 RTS 3940 .instr3 3950 ORA #&40 3960 CMP &15 3970 BNE instr2 3980 LDA #&80 3990 STA &14 4000 LDA #&20 4010 : 4020 .instr4 4030 PHP 4040 SEI 4050 STY &13 4060 STX &12 4070 STA &16 4080 LDA &F4 4090 PHA 4100 JSR pselect 4110 : 4120 LDY #1 4130 .instr5 4140 LDA (&12),Y 4150 STA &8010,Y 4160 DEY 4170 BPL instr5 4180 : 4190 LDY &13 4200 LDA &16 4210 ORA #8 4220 .instr7 4230 JSR pcomm 4240 PLA 4250 JSR sidesel 4260 LDA &16 4270 CMP #4 4280 BNE instr9 4290 : 4300 .instr8 4310 LDA #&80 4320 STA &14 4330 JMP main 4340 .instr9 4350 PLP 4360 RTS 4370 : 4380 .esc 4390 PHP 4400 SEI 4410 LDA &F4 4420 PHA 4430 JSR pselect 4440 LDA &FF 4450 STA &8010 4460 LDA #&C0 4470 STA &16 4480 BNE instr7 4490 : 4500 .event 4510 STA &19 4520 PHP 4530 LDA &F4 4540 PHA 4550 JSR pselect 4560 STX &800E 4570 STY &800F 4580 LDA &19 4590 STA &8010 4600 LDA #&40 4610 JSR pcomm 4620 PLA 4630 JSR sidesel 4640 LDA &19 4650 PLP 4660 RTS 4670 : 4680 .warm 4690 CLI 4700 LDY #0 4710 STY 0 4720 STY &17 4730 LDA #&80 4740 STA 1 4750 STA &18 4760 LDA #&20 4770 AND &8006 4780 BEQ warm2 4790 : 4800 LDX &8007 4810 .warm1 4820 INX 4830 LDA &8000,X 4840 BNE warm1 4850 LDA &8001,X 4860 STA &17 4870 LDA &8002,X 4880 STA &18 4890 : 4900 .warm2 4910 BCS warm4 4920 BIT langflg 4930 BPL warm4 4940 LDY #&FD 4950 LDA (&1D),Y 4960 BEQ warm99 4970 .warm4 4980 LDA &F4 4990 CMP #&C 5000 BNE warm5 5010 JMP &8000 5020 : 5030 .warm5 5040 LDA #1 5050 JSR warm100 5060 .warm7 5070 JSR pload 5080 BIT 1 5090 BVS warm12 5100 : 5110 .warm10 5120 LDA 0 5130 CLC 5140 ADC &17 5150 LDA 1 5160 ADC &18 5170 CMP #&F8 5180 BCC warm7 5190 : 5200 .warm12 5210 LDA #&FF 5220 STA langflg 5230 .warm99 5240 LDA #4 5250 : 5260 .warm100 5270 PHA 5280 .warm110 5290 LDA #&FF 5300 JSR instr 5310 BCC warm110 5320 PLA 5330 LDX #&17 5340 LDY #0 5350 JMP instr 5360 : 5370 .regsout 5380 STY &8018 5390 .regso1 5400 STX &8017 5410 .regso2 5420 STA &8016 5430 .regso3 5440 ROL A 5450 STA &8015 5460 ROR A 5470 RTS 5480 : 5490 .regsin 5500 LDX &8017 5510 .regsi1 5520 LDY &8018 5530 LDA &8016 5540 RTS 5550 : 5560 .datin 5570 LDY #0 5580 .datin1 5590 LDX #0 5600 .datin2 5610 BIT &8019 5620 BVC datin5 5630 BMI datin9 5640 LDA &801A 5650 STA &700,Y 5660 BVS datin7 5670 : 5680 .datin5 5690 BPL datin2 5700 CPY #&12 5710 BCC datin6 5720 CPY #&20 5730 BCC datin7 5740 CPY #&70 5750 BCS datin7 5760 : 5770 .datin6 5780 LDA &801A 5790 STA 0,Y 5800 .datin7 5810 CLV 5820 .datin9 5830 STX &8019 5840 INY 5850 BVC datin2 5860 LDY #7 5870 RTS 5880 : 5890 .blkout 5900 LDX #4 5910 .blkout1 5920 LDY #0 5930 .blkout2 5940 STX &1A 5950 .blkout3 5960 LDX #&80 5970 .blkout5 5980 CPY &1A 5990 BEQ txtout5 6000 LDA 0,Y 6010 JSR datout 6020 INY 6030 BNE blkout5 6040 : 6050 .txtout 6060 LDX #&40 6070 LDY #0 6080 .txtout2 6090 LDA &700,Y 6100 JSR datout 6110 INY 6120 CMP #&D 6130 BNE txtout2 6140 .txtout5 6150 LDX #&C0 6160 : 6170 .datout 6180 NOP 6190 NOP 6200 BIT &801B 6210 BVS datout 6220 BMI datout 6230 STA &801C 6240 STX &801B 6250 RTS 6260 : 6270 .brk 6280 LDY #&FF 6290 .brk2 6300 INY 6310 LDA (&FD),Y 6320 STA &20,Y 6330 TAX 6340 BNE brk2 6350 TYA 6360 BEQ brk2 6370 INY 6380 STY &1A 6390 LDY #&20 6400 JSR pselect 6410 LDA #&80 6420 JSR pcomm 6430 JSR blkout3 6440 : 6450 .main 6460 LDX #&FF 6470 TXS 6480 .main2 6490 SEI 6500 LDA thisROM 6510 JSR sidesel 6520 CLI 6530 .main3 6540 LDX &8014 6550 BEQ main4 6560 STX &801D 6570 LDA #0 6580 STA &8014 6590 : 6600 .main4 6610 LDX &801D 6620 CPX &801E 6630 BEQ main9 6640 : 6650 INX 6660 CPX #vduend MOD 256 6670 BCC main7 6680 LDX #vdustart MOD 256 6690 .main7 6700 LDA &8000,X 6710 STX &801D 6720 JSR &FFEE 6730 JMP main3 6740 : 6750 .main9 6760 LDA &8013 6770 BEQ main2 6780 : 6790 LDX &801D 6800 CPX &801E 6810 BNE main3 6820 : 6830 STA osjmp-cod400+&401 6840 JSR osjmp-cod400+&400 6850 JMP main 6860 ] 6870 B%=O%-V%+U% 6880 P%=&FF00 6890 vdustart=&FF1F 6900 [OPT I \ 2P Client code 6910 JMP warm 6920 JMP Rserv 6930 EQUB &82 6940 EQUB 8 6950 EQUB 0 6960 EQUS "(C)" 6970 EQUB 0 6980 EQUB &FF 6990 : 7000 .reset 7010 LDX #&FF 7020 TXS 7030 .reset2 7040 LDA refresh-&FF,X 7050 .reset4 7060 STA &FB00,X \ Copy refresh code 7070 STA &FA80,X 7080 DEX 7090 CMP #&C9 7100 BNE reset2 7110 DEX 7120 BMI reset4 7130 LDA #hostcmd7 MOD 256 7140 STA &FFFC \ Redirect Reset 7150 BNE hostcmd7 7160 : 7170 CMP #0 7180 LDA cycle+1 7190 EOR #&80 7200 STA cycle+1 7210 LDA &FF0D \ Get host command 7220 CMP cmd \ Check if changed 7230 STA cmd 7240 .refresh 7250 RTS 7260 .vduend \ End of VDU queue 7270 : 7280 .irq \ Called by &FEE5 access 7290 PHA 7300 LDA &FEE5 \ Get byte 7310 .ivec 7320 STA &200 \ Store or fetch 7330 STA &FEE5 \ Send byte 7340 INC ivec+1 \ Update address 7350 BNE irqexit 7360 INC ivec+2 7370 .irqexit 7380 PLA 7390 .anrti 7400 RTI 7410 : 7420 .cycle 7430 JSR &FB00 7440 BEQ cycle5 \ No change 7450 ORA #0 7460 .cycle5 7470 RTS 7480 : 7490 .nmi \ Called every 1ms 7500 PHA 7510 JSR cycle \ Refresh RAM 7520 BEQ irqexit \ No host command 7530 : 7540 .hostcmd 7550 CMP #9 7560 BCC hostcmd2 \ cmd=8, save mem 7570 BNE hostcmd10 \ cmd<>9 7580 LDA #&8D \ cmd=9, load mem 7590 BNE hostcmd4 \ opcode=STA 7600 : 7610 .hostcmd2 7620 LDA #&AD \ opcode=LDA 7630 .hostcmd4 7640 STA ivec 7650 LDA &FF10 \ Get transfer add 7660 STA ivec+1 7670 LDA &FF11 7680 STA ivec+2 7690 : 7700 LDA #irq MOD 256 7710 STA &FFFE \ Set IRQ vector 7720 LDA #anrti MOD 256 7730 STA &FFFA \ Ignore NMIs 7740 BCS hostcmd6 7750 BRK \ Trigger P->H 7760 NOP 7770 : 7780 .hostcmd6 7790 CLI 7800 .hostcmd7 7810 LDA #0 7820 STA &FF0D 7830 .hostcmd8 7840 JSR cycle 7850 BNE hostcmd \ Process command 7860 BEQ hostcmd8 \ Loop back 7870 .hostcmd10 7880 JMP hostcmd12 7890 : 7900 .regsin10 7910 LDY &FF18 7920 .regsin11 7930 LDX &FF17 7940 .regsin12 7950 LDA &FF15 7960 ROR A 7970 LDA &FF16 7980 RTS 7990 : 8000 .irq5 8010 STA &FC 8020 PLA 8030 ORA #4 8040 PHA 8050 AND #&10 8060 BEQ irq7 \ Not BRK, exit 8070 : 8080 TXA 8090 PHA 8100 TSX 8110 LDA &103,X \ Pop address 8120 CLD 8130 SEC 8140 SBC #1 8150 STA &FD 8160 LDA &104,X 8170 SBC #0 8180 STA &FE 8190 PLA 8200 TAX 8210 LDA &FC 8220 JMP (&202) \ Jump to BRKV 8230 .irq7 8240 LDA &FC 8250 RTI 8260 : 8270 .evjmp 8280 JMP (&220) 8290 : 8300 JMP (&21C) 8310 JMP (&21A) 8320 JMP (&218) 8330 JMP (&216) 8340 JMP (&214) 8350 JMP (&212) 8360 JMP (&210) 8370 CMP #&D 8380 BNE &FFEE 8390 LDA #&A 8400 JSR &FFEE 8410 LDA #&D 8420 JMP (&20E) 8430 JMP (&20C) 8440 JMP (&20A) 8450 JMP (&208) 8460 EQUW anrti 8470 EQUW reset 8480 EQUW anrti 8490 ] 8500 C%=O%-V%+U% 8510 P%=&F800 8520 [OPT I 8530 .tclear 8540 LDA &FF1E \ Clear VDU queue 8550 STA &FF14 8560 LDA #0 8570 STA &FF13 \ Clear command 8580 STA &FF19 \ Clear status 8590 STA &FF1B \ Clear status 8600 : 8610 .tclear10 8620 LDA #irq5 MOD 256 8630 STA &FFFE 8640 LDA #nmi MOD 256 8650 STA &FFFA 8660 : 8670 .tclear20 8680 LDA #0 8690 STA &FF0D 8700 RTS 8710 : 8720 .hostcmd12 8730 CMP #&C 8740 BNE hostcmd15 \ Not execute 8750 LDX #&FF 8760 TXS \ Reset stack 8770 LDA &FF11 \ Get address 8780 PHA 8790 STA osbtab+2 \ Set memtop 8800 STA osbtab+3 8810 LDA &FF10 8820 PHA 8830 SEI 8840 PHP 8850 JSR tclear 8860 LDA #1 8870 RTI \ Jump to code 8880 : 8890 .hostcmd15 8900 CMP #&28 8910 BEQ hostcmd92 \ Start/stop 8920 BCC hostcmd92 8930 : 8940 CMP #&FF 8950 BNE hostcmd20 \ Not reset 8960 TAX 8970 TXS \ Clear stack 8980 INX 8990 STX &FF 9000 LDX #&23 9010 STX &FF1E \ Clear VDU queue 9020 .hostcmd17 9030 LDA vectab,X \ Init vectors 9040 STA &200,X 9050 DEX 9060 BPL hostcmd17 9070 : 9080 .hostcmd18A 9090 JSR tclear 9100 .hostcmd18 9110 JMP hostcmd18 \ Wait for NMI/IRQ 9120 : 9130 .hostcmd20 9140 CMP #&C0 9150 BNE hostcmd25 \ Not escape 9160 LDA &FF10 9170 STA &FF \ Set escflg 9180 BMI hostcmd92 \ Clear VDU queue 9190 : 9200 .hostcmd90 9210 LDA &FFFA 9220 CMP #anrti MOD 256 9230 BNE hostcmd95 9240 JMP hostcmd7 9250 : 9260 .hostcmd92 9270 JSR tclear10 9280 PLA 9290 RTI 9300 : 9310 .hostcmd95 9320 JSR tclear20 9330 PLA 9340 RTI 9350 : 9360 .hostcmd25 9370 CMP #&40 9380 BNE hostcmd30 \ Not event 9390 TXA 9400 PHA 9410 TYA 9420 PHA 9430 LDX &FF0E \ Get regs 9440 LDY &FF0F 9450 LDA &FF10 9460 JSR evjmp 9470 PLA 9480 TAY 9490 PLA 9500 TAX 9510 JMP hostcmd90 9520 : 9530 .hostcmd30 \ Host BRK 9540 TXA 9550 PLA 9560 PHA 9570 PHA 9580 JSR tclear 9590 LDX #0 9600 STX &FD 9610 LDY #&FD 9620 STY &FE 9630 JSR datin10 9640 PLA 9650 TAY 9660 PLA 9670 TAX 9680 PLA 9690 STA &FC 9700 JMP (&202) 9710 : 9720 .rdch 9730 LDA #osrdch MOD 256 9740 JSR oscomm 9750 JMP regsin12 9760 : 9770 .cli 9780 LDA #oscli MOD 256 9790 STA &FF13 9800 JSR txtout10 9810 JMP osstat 9820 : 9830 .byte 9840 CMP #&82 9850 BCC byte15 9860 CMP #&86 9870 BCS byte15 9880 TAX 9890 LDY osbtab-&82,X 9900 LDX #0 9910 .anrts 9920 RTS 9930 : 9940 .osbtab 9950 EQUB 0 9960 EQUB 8 9970 EQUB &80 9980 EQUB &80 9990 : 10000 .byte15 10010 CMP #&DA 10020 BNE byte20 10030 TXA 10040 BNE byte18 10050 TYA 10060 BNE byte18 10070 LDA &FF1E 10080 STA &FF14 10090 .byte18 10100 LDA #&DA 10110 .byte20 10120 JSR regso10 10130 LDA #osbyte MOD 256 10140 JSR oscomm 10150 JMP regsin10 10160 : 10170 .word 10180 STA &FF16 10190 LDA #osword MOD 256 10200 STA &FF13 10210 LDA &FF16 10220 BNE oswd15 10230 LDA #5 10240 JSR blkout10 10250 JSR osstat 10260 JSR regsin12 10270 BCS anrts 10280 LDY #0 10290 LDA (blk),Y 10300 TAX 10310 INY 10320 LDA (blk),Y 10330 TAY 10340 JMP datin10 10350 : 10360 .oswd15 10370 STX rgX 10380 CMP #&E 10390 BCC oswd17 10400 LDA #&E 10410 : 10420 .oswd17 10430 TAX 10440 LDA oswifrm-1,X 10450 STA &FF18 10460 LDA oswito-1,X 10470 STA &FF17 10480 LDA oswoto-1,X 10490 LDX rgX 10500 JSR blkout10 10510 JSR osstat 10520 LDA &FF18 10530 AND #&1F 10540 JSR datin11 10550 JMP blkout19 10560 : 10570 .args 10580 JSR regso10 10590 LDA #osargs MOD 256 10600 STA &FF13 10610 LDY #0 10620 LDA #4 10630 CLD 10640 JSR blkout10 10650 JSR osstat 10660 JSR datin10 10670 JMP regsin10 10680 : 10690 .bget 10700 STY &FF18 10710 LDA #osbget MOD 256 10720 .bget12 10730 JSR oscomm 10740 JMP regsin12 10750 : 10760 .bput 10770 JSR regso11 10780 LDA #osbput MOD 256 10790 BNE bget12 10800 : 10810 .find 10820 JSR regso10 10830 PHA 10840 LDA #osfind MOD 256 10850 STA &FF13 10860 PLA 10870 BEQ find20 10880 JSR txtout10 10890 : 10900 .find20 10910 JSR osstat 10920 JMP regsin10 10930 : 10940 .file 10950 STA &FF16 10960 LDA #osfile MOD 256 10970 STA &FF13 10980 LDA #&12 10990 JSR blkout10 11000 LDY #0 11010 LDA (blk),Y 11020 TAX 11030 INY 11040 LDA (blk),Y 11050 TAY 11060 JSR txtout10 11070 JSR osstat 11080 LDX blk 11090 LDY blk+1 11100 LDA #2 11110 .file15 11120 JSR datin11 11130 LDX blk 11140 LDY blk+1 11150 JMP regsin12 11160 : 11170 .gbpb 11180 STA &FF16 11190 LDA #osgbpb MOD 256 11200 STA &FF13 11210 LDA #&D 11220 JSR blkout10 11230 JSR osstat 11240 CLD 11250 LDA #0 11260 BEQ file15 11270 : 11280 .oscomm 11290 STA &FF13 11300 .osstat 11310 LDA &FF13 11320 BNE osstat 11330 RTS 11340 : 11350 .regso10 11360 STX &FF17 11370 .regso11 11380 STY &FF18 11390 STA &FF16 11400 RTS 11410 : 11420 .txtout10 11430 STX txt 11440 STY txt+1 11450 LDX #&40 11460 LDY #0 11470 .txtout12 11480 LDA (txt),Y 11490 JSR datout10 11500 INY 11510 CMP #&D 11520 BNE txtout12 11530 .txtout15 11540 LDX #&C0 11550 : 11560 .datout10 11570 BIT &FF19 11580 BVS datout10 11590 BMI datout10 11600 STA &FF1A 11610 STX &FF19 11620 .datout15 11630 RTS 11640 : 11650 .blkout10 11660 STA num 11670 .blkout11 11680 STX blk 11690 STY blk+1 11700 LDX #&80 11710 LDY #0 11720 .blkout15 11730 CPY num 11740 BEQ blkout17 11750 LDA (blk),Y 11760 JSR datout10 11770 INY 11780 BNE blkout15 11790 : 11800 .blkout17 11810 JSR txtout15 11820 .blkout19 11830 LDX blk 11840 LDY blk+1 11850 RTS 11860 : 11870 .datin10 11880 LDA #0 11890 .datin11 11900 STX rpl 11910 STY rpl+1 11920 TAY 11930 LDX #0 11940 .datin12 11950 BIT &FF1B 11960 BVC datin15 11970 BMI datin19 11980 BPL datin17 11990 : 12000 .datin15 12010 BPL datin12 12020 .datin17 12030 LDA &FF1C 12040 STA (blk),Y 12050 CLV 12060 : 12070 .datin19 12080 STX &FF1B 12090 INY 12100 BVC datin12 12110 RTS 12120 : 12130 .wrch 12140 STX tmp 12150 LDX &FF1E 12160 INX 12170 CPX #vduend MOD 256 12180 BCC wrch15 12190 LDX #vdustart MOD 256 12200 .wrch15 12210 CPX &FF1D 12220 BEQ wrch15 12230 : 12240 STA &FF00,X 12250 STX &FF1E 12260 LDX tmp 12270 RTS 12280 : 12290 .oswoto 12300 EQUB 0 12310 EQUB 5 12320 EQUB 0 12330 EQUB 5 12340 EQUB 4 12350 EQUB 5 12360 EQUB 8 12370 EQUB &E 12380 EQUB 4 12390 EQUB 1 12400 EQUB 1 12410 EQUB 5 12420 EQUB 0 12430 EQUB &10 12440 : 12450 .oswifrm 12460 EQUB &20 12470 EQUB &20 12480 EQUB &20 12490 EQUB &20 12500 EQUB &24 12510 EQUB &20 12520 EQUB &20 12530 EQUB &20 12540 EQUB &24 12550 EQUB &21 12560 EQUB &21 12570 EQUB &20 12580 EQUB &20 12590 EQUB &20 12600 : 12610 .oswito 12620 EQUB &25 12630 EQUB &20 12640 EQUB &25 12650 EQUB &20 12660 EQUB &25 12670 EQUB &20 12680 EQUB &20 12690 EQUB &20 12700 EQUB &25 12710 EQUB &29 12720 EQUB &25 12730 EQUB &20 12740 EQUB &28 12750 EQUB &30 12760 : 12770 .vectab 12780 EQUW anrts 12790 EQUW hostcmd18A 12800 EQUW irq7 12810 EQUW irq7 12820 EQUW cli 12830 EQUW byte 12840 EQUW word 12850 EQUW wrch 12860 EQUW rdch 12870 EQUW file 12880 EQUW args 12890 EQUW bget 12900 EQUW bput 12910 EQUW gbpb 12920 EQUW find 12930 EQUW anrts 12940 EQUW anrts 12950 EQUW anrts 12960 : 12970 ] 12980 D%=O%-V%+U% 12990 P%=D% 13000 [OPT I 13010 .langflg 13020 EQUB 0 13030 .isec 13040 EQUB 0 13050 .oldosb 13060 EQUW 0 13070 .thisROM 13080 EQUB 0 13090 ] 13100 NEXT 13110 PRINT"IF YOU ARE USING TAPES," 13120 PRINT"INSERT CASSETTE THAT WILL HOLD RUN CODE." 13130 OSCLI"SAVE E2PCODE FFFF"+STR$~V%+" +"+STR$~(D%-A%)+" FFFF"+STR$~U%+" FFFF"+STR$~U% 13140 VDU26:CLS