by Erhard Pütz (aka Atreju aka Floppydoc)
prepared and translated by Mathy v. Nisselroy
Ever since the 1993 ABBUC Annual meeting (Jahreshauptversammlung) I've been working with the XEP 80 and gained quite a bit of knowledge and experience. I've used the XEP under BASIC, MAC65, BobTerm and from DOS to read texts.
At this time I want to ask everybody who's got information not mentioned in the manual, to send it to me. I'm especially interested in Information about the Hardware. Like, what graphicsprocessor as used?
While working with the XEP some very annoying things cought my attention. First there is this constant need to switch video plugs. Really nerve recking is readjusting of screen height, horizontal screen position and brightness. The height of the screen is almost right when the XEP is working in the American TV-standard with 50 Hz. But then the screen flickers and who knows how long the monitor will put up with the imposed 60 Hz. I once read that the higher screen frequency increases the current in the coils (Comment by Mathy: I don't quite know what these coils are called in English, but the direct the electronic beams that draw the picture on your cathode ray tube (according to this booklet I have)). This increases the load on both the electronics, which might not be designed handle this higher current, and the coils, which might burn out.
After switching to 50 Hz though, the screen is significantly higher than the standard XL/XE screen, pushing both upper and lower parts of the graphics off the screen. And the characters look really course. Once readjusted, one is rewarded with a good 80 character screen.
I've heard people say, the XEP would be slow. Well, when I print text to the XEP screen (X:) (original device driver), it rushes by so fast I hardly have time to press Ctrl-1 to halt the screen. Slow you say? Absolutely not, rather fast actually, in my opinion much faster then the original screen editor (E:). So I tried out some demo's. So this is it, they really are slow. But why? For is purpose I printed out one of the BASIC-listings and read through it. And read it again, and again, and again... Oh my God, who committed this crime...Oops, programmed this. At that time I didn't understand the programm, but it was one big chaos and even on the first glance one would find the slowest BASIC solutions. So, I'm gonna cut this thing short and state: the XEP 80 is fast. And thiss is mentioned in the manual really: Data transfer speed between XEP and computer takes place at 15.7 kBit. That's quite fast, but why this rare number? Why not 19.2 kBit? In that case the XEP would be able to keep up with the highest transfer rate of BobTerm. And why on the other hand, can the XEP only keep up with speeds of 4800 baud under BobTerm, where it should at least get 9600 baud? Let's start with the number 15.7 kBit. This means 15700 bits per second. The duration of one bit in this case is approximately 63.7us (micro seconds = 10^-6 or 0.000001 sec.). The time the microcessor in our computer needs to execute a command is measured in cycles. With the Atari 8bit every cycle takes approximately .564 us. One bit therefore takes about 113 cycles. The execution of command takes 2 to 7 cycles. While one bit is send, the computer could execute 16 to 56 commands. Let's use an average of 35. Then we can say one thing for sure: our 8 bitter can handle a transfer rate of 15.7 kBit hands down. Back to the question why it only works up to 4800 baud under BobTerm. Here's part of the XEP driver (V1.2) for BobTerm
LDX #$00 ; Load X with zero SEI ; don't execute IRQ's STX $D40E ; disable NMI's STA WSYNC ; pause STX PORTA ; send startbit STA WSYNC ; pause STA PORTA ; send bit 0 ROR ; next bit STA WSYNC ; pause STA PORTA ; send bit 1 ROR ; next bit STA WSYNC ; pause STA PORTA ; send bit 2 ROR ; next bit STA WSYNC ; pause STA PORTA ; send bit 3 ROR ; next bit STA WSYNC ; pause STA PORTA ; send bit 4 ROR ; next bit STA WSYNC ; pause STA PORTA ; send bit 5 ROR ; next bit STA WSYNC ; pause STA PORTA ; send bit 6 ROR ; next bit STA WSYNC ; pause STA PORTA ; send bit 7 ROR ; next bit STA WSYNC ; pause STA PORTA ; send Mode bit LDA #$FF STA WSYNC ; pause STA PORTA ; send stopbit STA $D40E ; enable NMI's CLI ; IRQ's permitted LDX #$20 ; wait 90 us DEX BPL LOOP LDA PORTA ; read XEP status AND #Mask ; ($02 or $20) BEQ Busy ; XEP not ready yet RTS ; ready, 1 byte sent
Everywere, where it reads "pause" the computer does the following: NOTHING. This command tells the computer it should halt the microprocessor until one screen line is processed. This seems to take up as much time as one bit at 15.7 kBit, or 63.7 microseconds. This command was issued 11 times, add to that the 166 cycles in the 90 us waiting loop, where the computer can't do much either. This makes 866 cycles or maximum 431, on average 250 commands, the computer can not execute, just because it is halted. The data BobTerm receives via the RS232 interface however, come in faster then it can be processed. The data not processed in time are lost. And this only because the computer is busy doing nothing while transfering data to the XE. How could one change this and why could the XEP print to screen even faster yet? The computer has to the whole job, like for instance preparing the next byte that should be send to the XEP, in the time between 2 bytes. But what if the next byte to be send would instantaneously be available? The computer should get it from the buffer or wherever, while 1 byte is send to the XEP. To achieve this, the byte should be automatically - without the CPU having anything to do with it - be send and this is done by HARDWARE. Such a device is built into the computer and calls itself POKEY. That's the chip that, among other things, handles the datatraffic with your disk drive, printer and cassette. If we then think about how fast the data transfer with a disk drive can be, namely 51 kBit/s th a Speedy or even 78 kBit/s with the HSS Copier (Mathy: both are German hardware upgrades for the 1050 disk drive), it becomes clear what advantages there are to use a hardware solution.
As far I can see, POKEY can not be used for datatrafficing with the XEP, because the XEP uses 9 bit data words during data transfer, where POKEY only uses 8 bits. A standard SIO chip, like the 6551, do it. The nineth bit, used to distinguish between data and commands, could be emulated by the parity bit. And here the 6551 has five possibilities: None, odd, even, mark and space parity. How we would handle the nineth bit when the computer receives it is one of the things I have to think about, but it should be possible. So we take an EPROM, in which we place the new XEP 80 driver, a bit of electronics to decode some signals, a 6551 and a triple DIP switch. The DIP switch is used to select a device number (Mathy: Hm, nice idea! Where have I heard that one before :-)) and connect the whole thing to the parallel bus of the XL/XE. For the electrical engineers among you I have to add that the XL/XE first of al needs a couple of powerfull bus drivers in the shape of two 74AS244 and one 74AS245, especially if you're running a BlackBox!
The driver for the XEP 80 basically exists of two parts. One of those parts is a so called Relocator, meaning, it moves the main programm to the top of the memory. Now I've recently worked with TurboWord+ und while reading the manual, I bumped into something strange. The driver of the XEP 80 should be called AUTORUN.SYS under TurboWord+ and SpartaDOS, because otherwise the MEMHI would be too low. Read it, tried it, seen it. But why? With AUTORUN.SYS, MEMHI is set at $95FF, when run by hand with XEP80 (RETURN) or from a batch file, it's set at $8FFF. I accepted it for a long time, but since it kept bugging me, I checked into this. I'm not gonna tell you how. But what came out will knock you off your sock When run by hand, the driver will install itself twice. But only the last one installed will be used. And it installs itself twice, because the file XEP80 ends with an INIT address, instead of a RUN address. DOS jumps to the INIT address ($2E2) after loading the file and when returning, tries to jump to the RUN address. But since there is none, it jumps to the beginning of the file, which starts the relocator once again. Using a disk monitor, I changed INIT to RUN and that was it. I was rewarded with 1.5 kByte more free memory.
One thing you can not do is press RESET or otherwise cause a warm start. A warm start will reinitialise the device drivers, including the XEP 80 driver. One would think that all values are entere again, but the value for MEMHI is NOT entered. Sigh, those programmers at ATARI, real pro's. But even they can forget some things. However, after a warm start, MEMHI is set to the start of the play list. With BASIC this is $9C1F. If you now fill up the memory nicely, you'll eventually overwrite the XEP driver, which is located between $9600 and $9C1F. If at this point you press RESET again, not even DOS will be reinitialised and you will be unable to save anything. And that's by far not all. Small error, big results. Well, that's about all I want to say about the XEP 80 for now, but the text is over 10 kByte anyhow. Maybe it's even usefull to somebody. I'm always happy to get an echo.
Greetings, your Floppydoc - Erhard Puetz
When I said in my previous article that I would be please about an echo, I meant, I would be pleased with ANY echo, not ONE echo. But I shouldn't complain, better ONE echo than NO echo at all. The echo said to me: Erhard, after I read you article about the XEP 80 in the ABBUC magazine (Mathy: number 38), I pulled my XEP 80 out of the drawer. I've always wanted to use it with BobTerm, but since the XEP driver for BobTerm doesn't switch the XEP to the German (Mathy: ahem, I thought it was called the European or PAL) standard, I've always had a flickering, too small image. Can't we do something about that?
Sure, I say, one takes the XIO command that sets the XEP 80 to the 50 Hz standard, turns that into a small machine language program and loads it as AUTORUN.SYS before BobTerm - Just a moment, this wont gonna work this way. There is no XEP driver initialised yet, making the XIO command disappear into thin air. OK, first the XEP driver, then the XIO command, then BobTerm... Hmmm, won't work either. The XEP driver for BobTerm isn't hooked to the normal editor.
And, BobTerm loads and initializes the driver. - Think, Think, Think - The driver contains the subroutine for sending data to the XEP. That's the part we talked about in the previous article (Mathy: ABBUC magazine 38). Here is the address data for the driver: memory from $4000 to $422E and RUN $4001. Ah yes, this should work. At the end of the files, before the RUN address, I append a small routine and redirect the RUN address to it.
This is what that looks like:
$422F SEC ; A command is send $4230 LDA #$D7 ; the number $D7 sets the XEP to 50 Hz in textmode $4232 JSR $4145 ; That's the point where the Send-routine starts $4235 JMP $4001 ; driver installed .ORG $02E0 ; RUN vector .WORD $422F ; RUN address
Try it, it works. During all these try outs, I've searched through the XEP driver several times, and that's when I saw that the Send-outine starts a bit earlier than I told you last month. It starts like this:
$4139 X_DAT CLC ; Data will be send $413A .BYTE $413B X_DAT SEC ; A command is send $413C PHP ; Get Carry status $413D WAIT_3 LDX VCOUNT ; Number of just created image divided by two $4140 CPX #$6B ; Equal or greater than 107 $4142 BCS WAIT_3 ; Yes, then wait $4144 PLP ; return Carry Status $4145 ROR ; shift byte to the right until $4146 ROR ; bit 0 is send first. $4147 ROR $4148 ROR $4149 ROR
... And this is where the part from the article in magzine 8 continues.
What do my square eyes see there? An other way that's that suppose to do? Well, boldly said, it's not allowed to send data during the Vertical Blank. But it's not clear to me why. The VBI is disabled anyhow. Might the WSYNC register in the "austastluecke" (Mathy: some kind of interval. Maybe I'll know what this word means when I translate the next article about the XEP, should Erhard write more of them. :-) ) not deliver the apropriate timing? Let's try that. Starting with $413D I'll just write the NOP command 7 times. We're still losing time, but at least we're not waiting 50 times a second. So, loaded BobTerm with the changed driver and - Look at that. All of a sudden BobTerm works with the XEP 80 at 9600 baud, not just 4800. I've tried it out a bit more, but could not find any negative side effects. So I called the ABBUC BBS and looky here, works like a charm. With my chest raised in pride I called the ABBUCcian that had laid this task upon me. I've ooen it, I've done it, I said, not just the 50 Hz, but even 9600 baud.
The day before yesterday was the day that I decided to show off my newly gained knowledge in ABBUC magazine. So I called Wolfgang (Mathy: Wolfgang Burger is the president of ABBUC and previous SysOp of the ABBUC BBS) to ask him, if he would in interested in a sequel to the XEP 80 article. Sure, he said, opening up the way to help the ever information hungry ABBUCcians. And here's a little more, just to make sure you don't starve.
For $40E0 on, we have 13 bytes, with which the XEP is initialized:
value | function | |
---|---|---|
$D9 | Cursor always on | |
$D4 | Use ATASCII characterset | |
$DE | Bright characters on dark background | |
$D3 | Burst mode, no cursor data is send back | |
$60 | Left Margin 0 low nibble | |
$70 | Left Margin 0 Hi nibble | |
$AF | Right Margin low nibble 15 + 4*16 Hi nibble = 79 | |
$B4 | Right Margin hi nibble | |
$00 | Horizontal cursor position = 0 | |
$80 | vertical cursor position = 0 | |
$D0 | Erase List flag | |
$C5 | Fill RAM with SPACE-characters | |
$DC | Set Scroll window to X-cursor position |
Since all this trail and error stuff started to annoy me, I "just for a minute" reassembled the driver, so I now a fairly readable file to work with. This means I'm gonna write more articles about the XEP 80. Since I was able to delve up more information about the XEP 80, I can already tell you: the 19200 baud are in reachable distance and I seem to be on a hot trail with my suspiciouns about the 6551 SIO chip from the first article (I think).
The videocontroller inside the XEP 80 is a 48 pin chip. It's data bus is 16 bits wide on the video side. This way, two RAMs could be read simultaniously, one containing the text that should be displayed and another containing the text attributes. There are eight possible attributes:
attribute | display | |
---|---|---|
Inverse | A character plus it's surrounding area is display "Inverse" | |
Halve Bright | The character in displayed with a lower brightness. Other options are a higher brightness and even color. | |
Flickering | On, Off, On, Off | |
Double Height | Text in double height, internally some conditions have to be met though. | |
Double Width | Text in double wide. The next line can't be displayed though, so we have to leave a blank line between two lines of character | |
Underlined | An apparently freely defined character is mixed in. This can be the "underline" character or an "overline" or "strait through the middle" character or whatever you want | |
Hidden | The text is not displayed at all. This attribute should also be set when using a double height character, so the controller knows that this is the bottom halve of the double height haracter. | |
Graphics | Since this is an attribute, text and blockgraphics can be mixed at will. Except double height, all other attributes can be used at the same time |
And then there is the Graphics mode of the XEP 80. Just like the subject of block graphics, it's a very broad subject and will not be discussed here.
The controller offers the option of connecting a lightpen to it. Via interrupts, the horizontal and vertical positions are stored into two registers. HPEN is 7 bit wide (128 positions) and VPEN is 5 bit wide (32 positions). Since this does not provide us with a very high resolution, we can forget about drawing with a light pen.
Here we find a UART (Universal Asynchronus Receiver Transmitter), that, in it's addresses and functions, equals the good old 6551 so much, that I'm assuming it is. With a 4 bit pre-devider, the system clock (12MHz in the XEP 80) is devided into one of 16 steps. These steps are 3.4, 4, 4.5, ... ,11. The actual baudrate devider is 11 bits wide and is further devided by 16 at the output. In the XEP 80 the baudrate is set to 15625. The mathematics could however also look like this:
12 MHz : 6.5 = approximately 1.8432 MHz 12 MHz : 6.5 = approximately 1.8432 MHz 1.8432 MHz : 6 = 307200 Hz 1.8432 MHz : 3 = 614400 Hz 307200 Hz : 16 = 19.200 kHz 614400 Hz : 16 = 38.400 kHz
Those 19.200 kHz lies within manufacturers specifications. If 38.400kHz works, is something someone should try out. But since the dividers aren't used up yet (we can even go much faster), why won't it work.
That's it for this time.
Greetings, your FloppyDoc
0100 ;.OPT NOLIST 0110 .OPT NOEJECT 0120 ; 0130 BASE=$6000 0140 ; 0150 ;CHAR EQUATES 0160 ; 0170 LF=10 0180 CR=13 0190 ESC=$1B 0200 SPACE=$20 0210 CNTL=$5E 0220 CLS=$7D 0230 EOL=$9B 0240 ; 0250 ;80 COL COMMANDS 0260 ; 0270 XCH80=$50 0280 LMG80=$60 0290 LMH80=$70 0300 YCR80=$80 0310 SGR80=$99 0320 PAG80=$9A 0330 RMG80=$A0 0340 RMH80=$B0 0350 GET80=$C0 0360 CUR80=$C1 0370 RST80=$C2 0380 PST80=$C3 0390 CLR80=$C4 0400 LIS80=$D0 0410 SCR80=$D2 0420 SCB80=$D3 0430 GRF80=$D4 0440 ICM80=$D5 0450 PAL80=$D7 0460 CRS80=$D9 0470 MCF80=$DB 0480 PNT80=$DD 0490 ; 0500 ;MEMORY EQUATES 0510 ; 0520 DOSINI=$0C 0530 ICDNOZ=$21 0540 ICCOMZ=$22 0550 ICAX1Z=$2A 0560 ICAX2Z=$2B 0570 ICIDNO=$2E 0580 LMARGN=$52 0590 RMARGN=$53 0600 VCP=$54 0610 HCP=$55 0620 IN=$CC 0630 CDTMV3=$21C 0640 SDMCTL=$22F 0650 KEYDEL=$2D9 0660 KEYREP=$2DA 0670 DVSTAT=$2EA 0680 CRSINH=$2F0 0690 CHBAS=$2F4 0700 LISTF=$2FE 0710 SFLAG=$2FF 0720 HATABS=$31A 0730 ICDNO=$341 0740 ICCOM=$342 0750 PAL=$D014 0760 IRQEN=$D20E 0770 SKSTAT=$D20F 0780 PORTA=$D300 0790 PACTL=$D302 0800 DMACTL=$D400 0810 WSYNC=$D40A 0820 VCOUNT=$D40B 0830 NMIEN=$D40E 0840 ; 0850 *=BASE-2 0860 ; 0870 .WORD CEND-BEGIN ;RELOCATER INFO 0880 ; 0890 BEGIN JSR ERTS ;DOSINI VECTOR 0900 JMP CINIT ;RELOCATER JUMP 0910 ; 0920 PAUX1 .BYTE 0 0930 PAUX2 .BYTE 0 0940 ; 0950 READ JSR DISAB;DISABLE IRQ INTS 0960 LDA #GET80 0970 JSR CINP ;REQUEST, GET CHAR 0980 PHA ;SAVE CHAR 0990 JSR INPUT ;GET CURS 1000 JSR CURCK ;CHECK FOR X>$4F 1010 PLA ;RESTORE CHAR 1020 JMP ENAB 1030 ; 1040 CINP JSR CMD 1050 INPUT LDA #00 ;TIME CRITICAL CODE 1060 TAX ;MUST NOT CROSS A 1070 LDY #31 ;PAGE BOUNDARY 1080 STA DATIN 1090 IN0 LDA PORTA ;4 1100 AND INMSK ;4 1110 BEQ IN01 ;3 IF A 0, 2 IF NOT 1120 DEX 1130 BNE IN0 1140 DEY ;TIMEOUT LOOPS 1150 BNE IN0 1160 SEC ;NO RESPONSE 1170 RTS 1180 IN01 LDX #08 1190 LDY #12 ;2 1200 IN1 DEY 1210 BNE IN1 ;5*Y-1 1220 NOP ;2 1230 IN10 LDY #15 ;2 MAIN DLY COUNT 1240 IN2 DEY 1250 BNE IN2 ;5*Y-1 1260 LDA PORTA ;4 GET BYTE 1270 AND INMSK ;4 GET BIT 1280 CLC ;2 1290 BEQ IN25 ;0=3,1=2 1300 SEC ;1=2 1310 IN25 BCC IN26 ;0=3,1=2 1320 IN26 DEX ;2 DEC COUNT 1330 BMI IN3 ;2 (3 DONE) 1340 ROR DATIN ;6 SHIFT IN BIT 1350 BCC IN10 ;3 ALWAYS 1360 IN3 LDY #15 ;DELAY 1/2 BIT 1370 IN33 DEY 1380 BNE IN33 1390 LDA DATIN ;GET CHAR (Y=0) 1400 BCC I5 ;RETURN IF CHAR 1410 BPL I0 ;HORIZ WITH NO VERT 1420 AND #$7F ;CLEAR UPPER FLAG 1430 CMP #$51 ;TEST HORIZ/VERT 1440 BCC I00 ;HORIZONTAL 1450 AND #$1F ;CLEAR MID FLAG 1460 BCS I01 ;SAVE VERT 1470 I00 JSR I0 ;SAVE HORIZ 1480 BCC INPUT ;GET VERT 1490 I0 INY ;OFFSET FOR HORIZ 1500 I01 STA VCP,Y ;CURS POSITION 1510 STA VCS,Y ;CURS SHADOW 1520 CLC ;INDICATE RESPONSE 1530 I5 RTS 1540 ; 1550 CURCK LDA HCP ;CHECK HORIZ CURSOR 1560 CMP #$50 ;FOR >$4F 1570 BCC I5 ;IF NOT 1580 LDA #CUR80 ;GO GET REAL VALUE 1590 JSR CINP 1600 JMP I0 ;AND STORE IT (Y=0) 1610 ; 1620 CMD SEC ;THIS CODE MUST NOT 1630 BCS OUT ;CROSS A PAGE BOUNDARY 1640 OUTPUT CLC ;CMD FLAG=0 FOR CHAR 1650 OUT LDY #00 1660 JSR SEND ;SEND START BIT 1670 LDX #08 ;SETUP BIT COUNT OF 9 1680 NOP 1690 NOP 1700 NOP ;2+2+2+2=8 1710 OUT0 ROR A ;PUT BIT INTO CARRY 1720 BCS HI 1730 BCC LO ;2+3=5 CYCLES TO LO 1740 LO LDY #00 ;5+2 CYCLES TO JSR 1750 JSR SEND ;SEND A 0 1760 BCC OUT1 ;3 CYCLES 1770 HI LDY OUTMS ;3+4 CYCLES TO JSR 1780 JSR SEND ;SEND A 1 1790 BCS OUT1 ;3 CYCLES 1800 OUT1 DEX ;NEXT BIT 2 CYC 1810 BPL OUT0 ;MORE 3 OR 2 CYC 1820 BMI OUT2 ;SEND STOP BIT 3 CYC 1830 OUT2 LDY OUTMS ;SEND A 1 1840 BNE OUT3 1850 OUT3 JSR SEND ;2+3+4+3=12 1860 RTS 1870 SEND STY PORTA ;OUTPUT BIT 1880 LDY #12 ;TIMER FOR 15.7KB 1890 S1 DEY 1900 BNE S1 ;5*Y-1 CYCLES 1910 BEQ S2 ;3 1920 S2 NOP 1930 NOP 1940 NOP 1950 NOP ;2+2+2+2=8 1960 S3 RTS ;6 CYCLES 1970 ; 1980 COM LDA ICCOMZ ;GET COM BYTE 1990 CMP #$14 ;CHECK DEBUG OUT 2000 BNE COM1 ;TRY NEXT XIO 2010 LDA ICAX2Z ;GET AUX 2 2020 COMSD JSR DISAB ;STOP INTERRUPTS 2030 JSR CMD ;GO SEND 2040 JMP ENAB ;ENABLE AND NORM EXIT 2050 COM1 CMP #$15 ;TEST VALID 2060 BNE COM2 ;NEXT 2070 LDA ICAX2Z ;GET AUX 2 2080 BNE COMBR ;GO DO BURST 2090 STA MODE ;MAKE NORMAL 2100 LDA #SCR80 ;GET CMD 2110 BNE COMSD ;GO SEND 2120 COMBR STA MODE ;MAKE BURST 2130 LDA #SCB80 ;GET CMD 2140 BNE COMSD ;GO SEND 2150 COM2 CMP #$16 ;CHECK DEBUG IN 2160 BNE COM3 ;NEXT 2170 LDA ICAX2Z ;GET BYTE TO SEND 2180 JSR DISAB 2190 JSR CINP ;REQUEST, GET CHAR 2200 STA DVSTAT+1 ;FOR NOW 2210 JMP ENAB 2220 COM3 CMP #$19 ;CHECK 80/40 2230 BNE COM4 2240 JMP XIO19 ;DO IT 2250 COM4 RTS 2260 ; 2270 PCOM LDA ICCOMZ ;GET CMD 2280 CMP #$17 ;TEST VALID 2290 BNE S3 ;NO MORE FOR NOW 2300 LDA ICAX2Z ;GET AUX 2 2310 CMP #08 ;CHECK RESERVED 2320 BCS S3 ;NO GOOD 2330 AND #03 ;CHECK 3 AND 7 2340 EOR #03 2350 BEQ S3 ;NOT ALLOWED 2360 LDA ICAX1Z ;GET AUX1 2370 CMP #08 ;CHECK UPPER LIMIT 2380 BCS S3 ;NO GOOD 2390 STA PAUX1 2400 LDA ICAX2Z ;GET AUX 2 2410 STA PAUX2 2420 JMP EXIT 2430 ; 2440 WRITE LDY SFLAG ;CHECK CNTL 1 2450 BNE WRITE ;IF ON 2460 JSR DISAB 2470 LDY DEV ;ARE WE SCREEN? 2480 BEQ WR2 ;YES 2490 PHA 2500 LDA #00 2510 STA DEV 2520 LDA #SCR80 2530 JSR CMD 2540 PLA 2550 WR2 LDY LISTF ;CHECK LIST FLAG 2560 CPY LISTS 2570 BEQ WR3 2580 STY LISTS ;SAVE NEW VALUE 2590 PHA 2600 TYA 2610 BEQ WR25 2620 LDA #01 ;FORCE LSB 2630 WR25 ORA #LIS80 2640 JSR CMD ;SEND NEW VALUE 2650 PLA 2660 WR3 JSR ALIGN ;SET PARMS 2670 LDY CHBAS ;CHECK CHAR SET 2680 CPY CHSH 2690 BEQ WR5 2700 CPY #$E0 2710 BNE WR4 2720 STY CHSH 2730 PHA 2740 LDA #GRF80 2750 WR35 JSR CMD 2760 PLA 2770 JMP WR5 2780 WR4 CPY #$CC 2790 BNE WR5 2800 STY CHSH 2810 PHA 2820 LDA #ICM80 2830 BNE WR35 2840 WR5 LDY CRSINH ;CHECK CURS FLAG 2850 CPY CRSS 2860 BEQ WR6 2870 STY CRSS 2880 PHA 2890 TYA 2900 BEQ WR55 2910 LDA #01 2920 WR55 EOR #CRS80 ;CURSOR ON/OFF 2930 JSR CMD 2940 PLA 2950 WR6 JSR OUTPUT ;SEND CHAR 2960 LDA MODE ;TEST FOR BURST 2970 BNE WWAT ;IF SO 2980 JSR INPUT ;GET NEW CURSOR 2990 JSR CURCK ;CHECK FOR X>$4F 3000 JMP ENAB 3010 WWAT JSR ENAB ;ENABLE INTS 3020 LDY #25 ;OR SUCH 3030 JSR S1 3040 WW1 LDA PORTA 3050 AND INMSK 3060 BEQ WW1 3070 WW2 LDY #01 3080 RTS 3090 ; 3100 POPEN STX TIOCB 3110 LDX ICDNOZ 3120 JSR MATRIX 3130 BCS HANDGO 3140 LDY SDMCTL 3150 BNE WW2 3160 LDA #PST80 3170 JSR DISAB 3180 JSR CINP ;REQUEST, GET CHAR 3190 BNE POP1 3200 LDA #139 ;NOBODY HOME 3210 POP1 JSR ENAB 3220 TAY 3230 RTS 3240 ; 3250 HANDGO LDA ICDNOZ 3260 STX ICDNOZ 3270 PHA 3280 LDA ICCOMZ 3290 AND #08 3300 TAX 3310 JSR HAND 3320 PLA 3330 STA ICDNOZ 3340 RTS 3350 ; 3360 PWRT TAY ;SAVE CHAR 3370 STX TIOCB 3380 LDA ICDNO,X 3390 TAX 3400 JSR MATRIX 3410 TYA 3420 BCC PWP 3430 STA TCHAR ;SAVE CHAR FOR CALL 3440 LDY TIOCB ;GET UNIT # 3450 LDA ICDNO,Y 3460 PHA ;SAVE UNIT # 3470 TXA ;GET NEW VALUE 3480 STA ICDNO,Y ;REPLACE WITH NEW 3490 STA ICDNOZ ;AND ZERO PAGE 3500 LDX #06 3510 JSR HAND ;GO PRINT 3520 PLA ;RESTORE UNIT # 3530 LDX TIOCB ;GET POINTER 3540 STA ICDNO,X ;RESTORE OLD 3550 STA ICDNOZ 3560 RTS 3570 PWP LDY DEV ;CHECK OUTPUT DEV 3580 BNE PW0 3590 PHA 3600 LDY SDMCTL 3610 BEQ PW2 3620 PW1 LDY VCOUNT 3630 CPY #129 3640 BNE PW1 3650 PW2 JSR DISAB 3660 LDA #PNT80 3670 STA DEV 3680 JSR CMD 3690 JSR ENAB 3700 PLA ;RESTORE CHAR 3710 PW0 TAY ;SAVE CHAR 3720 LDA PAUX2 ;GET CNTL 3730 ROR A ;CHECK NO XLATE 3740 TYA ;RESTORE CHAR 3750 BCS DOIT ;DONT XLATE 3760 CMP #EOL ;CHECK EOL 3770 BNE XLATE ;XLATE IF NOT 3780 LDA #CR ;REPLACE WITH CR 3790 JSR DOIT ;SEND 3800 LDA PAUX2 ;GET CNTL 3810 AND #04 ;CHECK NO APPEND 3820 BNE WGDS ;DONT APPEND 3830 LDA #LF ;GET LF 3840 BNE DOIT ;SEND 3850 XLATE LDA PAUX2 ;GET CNTL 3860 CMP #02 ;CHECK LIGHT XLATE 3870 TYA ;RESTORE CHAR 3880 BCC DOIT ;DONE WITH XLATE 3890 AND #$7F ;REMOVE MSB 3900 CMP #$20 ;CHECK ASCII CHAR 3910 BCS DOIT ;GO PRINT ASCII 3920 PHA ;SAVE CHAR 3930 LDA #CNTL ;GET "CNTL" CHAR 3940 JSR DOIT ;SEND 3950 PLA ;RESTORE CHAR 3960 ORA #$40 ;MAKE ALPHA 3970 DOIT LDY SDMCTL 3980 BEQ DO1 3990 DO0 LDY VCOUNT 4000 CPY #129 4010 BNE DO0 4020 DO1 JSR DISAB 4030 JSR OUTPUT 4040 JSR ENAB 4050 WAIT LDY #25 ;FOR NOW 4060 JSR S1 4070 LDY #02 4080 W0 LDX #255 ;FOR NOW 4090 STX CDTMV3 ;SETUP VBLANK COUNT 4100 W1 LDA PORTA 4110 AND INMSK 4120 BNE WGDS ;AVAILABLE 4130 LDA CDTMV3 ;CHECK COUNTDOWN 4140 BNE W1 4150 DEY 4160 BNE W0 4170 WTMO LDY #138 ;DO TIMEOUT 4180 BNE WRTS ;COULD DO BRKKEY ALSO 4190 WGDS LDY #01 4200 WRTS RTS 4210 ; 4220 MATRIX CPX #02 4230 BEQ PNEXT 4240 BCS POVER 4250 LDA PAUX1 4260 LSR A 4270 POVER RTS 4280 PNEXT LDA #03 4290 CMP PAUX1 4300 BCC POVER 4310 LDA PAUX1 4320 AND #02 4330 BEQ POVER 4340 DEX 4350 RTS 4360 ; 4370 HAND LDA $E431,X 4380 PHA 4390 LDA $E430,X 4400 PHA 4410 LDA TCHAR ;RESTORE CHAR 4420 LDX TIOCB ;GET IOCB POINTER 4430 RTS ;CALL PRINTER HANDLER 4440 ; 4450 FORCOM LDA ICCOMZ 4460 CMP #$18 4470 BEQ XIO18 4480 RTS 4490 ; 4500 CINIT LDA #00 4510 STA TOGGLE 4520 JSR JINIT 4530 LDA #$50 4540 LDY #02 4550 JSR FSET 4560 LDA #$53 4570 JSR FIND 4580 LDA HATABS+1,X 4590 STA TEMPSV 4600 LDA HATABS+2,X 4610 STA TEMPSV+1 4620 LDA #$45 4630 JSR FIND 4640 LDA HATABS+1,X 4650 STA IN 4660 LDA HATABS+2,X 4670 STA IN+1 4680 LDY #15 4690 C003 LDA (IN),Y 4700 STA TMTAB,Y 4710 DEY 4720 BPL C003 4730 LDA #FORCOM-1&$FF 4740 STA TMTAB+10 4750 LDA #FORCOM-1/256 4760 STA TMTAB+11 4770 LDA SKSTAT 4780 AND #08 4790 BEQ C004 4800 XIO18 LDA #$45 4810 LDY #00 4820 JSR FSET 4830 LDA #$53 4840 LDY #01 4850 JSR FSET 4860 LDA #WRITE-1&$FF 4870 STA $346 4880 LDA #WRITE-1/256 4890 STA $347 4900 EOPEN LDX #00 4910 JSR FESUB 4920 LDA ICAX1Z ;GET AUX 1 4930 AND #32 ;CHECK CLEAR BIT 4940 BNE C005 ;DONT DO RESET 4950 LDA #00 4960 LDX #06 4970 C0035 STA VCS,X 4980 DEX 4990 BPL C0035 5000 LDA #$E0 5010 STA CHSH 5020 LDA #$4F 5030 STA RMARGS 5040 STA COMPOS 5050 JSR DISAB 5060 IO00 LDA #RST80 ;RESET 80 COL 5070 JSR CINP ;REQUEST, GET CHAR 5080 BCC IO01 ;GOT IT 5090 JSR JTOGL ;SWITCH PORTS 5100 BNE IO00 ;DO IT AGAIN 5110 IO01 LDA PAL ;CHECK COMPUTER TYPE 5120 AND #$0E 5130 BNE IOP1 5140 LDA #PAL80 5150 JSR CMD ;SET 80 COL TO 50HZ 5160 IOP1 JMP ENAB 5170 ; 5180 XIO19 LDX #06 5190 JSR FESUB 5200 LDA #$53 5210 JSR FIND 5220 LDA TEMPSV 5230 STA HATABS+1,X 5240 LDA TEMPSV+1 5250 STA HATABS+2,X 5260 LDA TMTAB+6 5270 STA $346 5280 LDA TMTAB+7 5290 STA $347 5300 C004 LDA #$45 5310 LDY #03 5320 JSR FSET 5330 JMP EXIT 5340 C005 LDA #SCR80 ;IN CASE A PRINT 5350 JMP COMSD ;HAS OCCURED 5360 ; 5370 EDTAB .WORD EOPEN-1 ;OPEN 5380 .WORD EXIT-1 ;CLOSE 5390 .WORD EGET-1 ;GET LINE OF TEXT 5400 .WORD WRITE-1 ;PUT (NO CURS) 5410 .WORD EXIT-1 ;STATUS 5420 .WORD COM-1 ;SPECIAL (CMD OUT) 5430 JMP EXIT ;INIT 5440 .BYTE 0 5450 ; 5460 PRTAB .WORD POPEN-1 ;OPEN 5470 .WORD EXIT-1 ;CLOSE 5480 .WORD ERTS-1 ;GET 5490 .WORD PWRT-1 ;PUT 5500 .WORD POPEN-1 ;STATUS 5510 .WORD PCOM-1 ;SPECIAL 5520 JMP EXIT ;INIT 5530 .BYTE 0 5540 ; 5550 SCTAB .WORD SOPEN-1 ;OPEN 5560 .WORD EXIT-1 ;CLOSE 5570 .WORD SREAD-1 ;GET-LOCATE 5580 .WORD SWRIT-1 ;PUT-PLOT 5590 .WORD EXIT-1 ;STATUS 5600 .WORD ERTS-1 ;SPECIAL 5610 SCT1 JMP EXIT ;INIT 5620 .BYTE 0 5630 ; 5640 TMTAB .WORD EXIT-1,EXIT-1 5650 .WORD EXIT-1,EXIT-1 5660 .WORD EXIT-1,EXIT-1 5670 JMP EXIT 5680 .BYTE 0 5690 ; 5700 SOPEN LDA ICAX2Z 5710 AND #08 5720 BEQ SCT1 5730 LDA ICAX1Z 5740 AND #16 5750 BNE SCT1 5760 LDA #00 ;SEND 0 5770 JSR DISAB 5780 JSR OUTPUT 5790 JSR INPUT 5800 LDA #SGR80 ;SET GRAPHICS 5810 JSR CMD 5820 LDA PAL 5830 AND #$0E 5840 BNE SOP1 5850 LDA #PAG80 5860 JSR CMD 5870 SOP1 LDA #CLR80 ;FILL WITH 0 SENT 5880 JSR CINP ;REQUEST, GET CHAR 5890 LDA #01 5900 JMP COMBR 5910 ; 5920 SREAD JSR DISAB 5930 JSR ALIGN ;SET PARMS 5940 JSR READ ;GET CHAR 5950 CMP #EOL ;CHECK EOL 5960 BNE SCT1 ;RETURN NORMAL 5970 LDA #SPACE ;REPLACE WITH SPACE 5980 BNE SCT1 ;RETURN NORMAL 5990 ; 6000 SWRIT PHA ;SAVE CHAR 6010 LDA #ESC ;FORCE PRINT 6020 JSR WRITE 6030 PLA ;RESTORE CHAR 6040 JMP WRITE ;SEND IT 6050 ; 6060 EGET LDA COMPOS 6070 BEQ EBACK 6080 LDA HCP 6090 STA HCPS 6094 STA HCPE 6100 EG1 JSR KCALL ;GET KB BYTE 6110 CMP #EOL 6120 BEQ EGBAK 6130 JSR WRITE ;SEND TO 80 COL 6132 LDY HCP ;THIS CODE IS FOR 6134 CPY HCPE ;SPECIAL CASE LINES 6140 BCC EG1 ;DONT UPDATE IF LESS 6142 STY HCPE 6144 BCS EG1 6150 EGBAK STY KSTAT ;SAVE STATUS 6160 CPY #$80 ;CHECK STAT 6170 BCS EBA0 ;DO EOL IF EOF/BREAK 6180 JSR DISAB ;DISAB FOR CMD 6190 LDA #00 6200 STA COMPOS 6210 LDA MODE 6220 BEQ EG2 6230 LDA #00 6240 BEQ EG3 6250 EG2 LDA HCPS 6260 EG3 JSR CMD ;X CURS TO OLD VAL 6270 LDA #MCF80 ;Y CURS TO FIRST 6280 JSR CMD 6290 EBACK JSR READ ;GO GET A CHAR 6300 CMP #EOL 6310 BNE EGXT ;NOT DONE YET 6312 LDY HCP 6314 CPY HCPE ;CHECK RIGHTMOST 6315 BCS EBA0 ;CURSOR POSITION 6316 LDA #SPACE ;IF NOT THERE 6318 BNE EGXT ;THEN FAKE SPACE 6320 EBA0 STA COMPOS ;SET NON 0 6330 JSR WRITE 6340 LDA #EOL ;RETURN WITH EOL 6350 EGXT LDY KSTAT ;GET STATUS 6360 RTS 6370 ; 6380 KCALL LDA $E425 6390 PHA 6400 LDA $E424 6410 PHA 6420 RTS 6430 ; 6440 DISAB LDY #00 6450 STY NMIEN 6460 SEI 6470 RTS 6480 ; 6490 ENAB LDY #$C0 6500 STY NMIEN 6510 CLI 6520 EXIT LDY #01 6530 ERTS RTS 6540 ; 6550 VCS .BYTE 0 6560 HCS .BYTE 0 6570 DEV .BYTE 0 6580 LMARGS .BYTE 0 6590 LISTS .BYTE 0 6600 MODE .BYTE 0 6610 CRSS .BYTE 0 6620 ; 6630 CHSH .BYTE 0 6640 RMARGS .BYTE 0 6650 COMPOS .BYTE 0 6660 ; 6670 DATIN .BYTE 0 6680 HCPS .BYTE 0 6685 HCPE .BYTE 0 6690 KSTAT .BYTE 0 6700 INMSK .BYTE 0 6710 OUTMS .BYTE 0 6720 TOGGLE .BYTE 0 6730 TIOCB .BYTE 0 6740 TCHAR .BYTE 0 6750 ; 6760 TEMPSV .WORD 0 6770 ; 6780 INMST .BYTE 02,$20 6790 OUTMT .BYTE 01,$10 6800 ; 6810 FETAB .BYTE 0,0,0,$4F,24,3 6820 .BYTE 62,0,2,39,30,6 6830 ; 6840 LOOKUP .BYTE "ESP" 6850 LOWAD .BYTE EDTAB&$FF,SCTAB&$FF,PRTAB&$FF,TMTAB&$FF 6860 ; 6870 ALIGN LDY HCP ;GET HCURS 6880 CPY HCS ;COMPARE TO SHADOW 6890 BEQ A1 ;NO CHANGE 6900 STY HCS ;SAVE NEW VALUE 6910 PHA ;SAVE CHAR 6920 TYA 6930 CMP #$50 6940 BCC A00 6950 LSR A 6960 LSR A 6970 LSR A 6980 LSR A 6990 ORA #XCH80 7000 PHA 7010 TYA 7020 AND #$0F 7030 JSR CMD 7040 PLA 7050 A00 JSR CMD ;SEND NEW CURSOR 7060 PLA 7070 A1 LDY VCP ;GET VCURS 7080 CPY #25 ;CHECK UPPER LIMIT 7090 BCC A15 7100 LDY #24 ;STATUS LINE 7110 A15 CPY VCS ;COMPARE TO SHADOW 7120 BEQ A2 ;NO CHANGE 7130 STY VCS ;SAVE NEW VALUE 7140 PHA ;SAVE CHAR 7150 TYA 7160 ORA #YCR80 ;SET CMD BIT 7170 JSR CMD ;SEND NEW CURSOR 7180 PLA 7190 A2 LDY LMARGN 7200 CPY RMARGN 7210 BCC A24 7220 LDY #00 7230 STY LMARGN 7240 A24 CPY LMARGS 7250 BEQ A3 7260 STY LMARGS 7270 PHA 7280 TYA 7290 AND #$0F 7300 ORA #LMG80 7310 JSR CMD 7320 LDA LMARGN 7330 LSR A 7340 LSR A 7350 LSR A 7360 LSR A 7370 BEQ A25 7380 ORA #LMH80 7390 JSR CMD 7400 A25 PLA 7410 A3 LDY RMARGN 7420 CPY RMARGS 7430 BEQ A4 7440 STY RMARGS 7450 PHA 7460 TYA 7470 AND #$0F 7480 ORA #RMG80 7490 JSR CMD 7500 LDA RMARGN 7510 LSR A 7520 LSR A 7530 LSR A 7540 LSR A 7550 CMP #04 7560 BEQ A35 7570 ORA #RMH80 7580 JSR CMD 7590 A35 PLA 7600 A4 RTS 7610 ; 7620 FESUB LDA FETAB,X 7630 STA SDMCTL 7640 STA DMACTL 7650 LDA FETAB+1,X 7660 STA VCP 7670 LDA FETAB+2,X 7680 STA HCP 7690 STA LMARGN 7700 LDA FETAB+3,X 7710 STA RMARGN 7720 LDA FETAB+4,X 7730 STA KEYDEL 7740 LDA FETAB+5,X 7750 STA KEYREP 7760 RTS 7770 ; 7780 FIND LDX #00 7790 F1 CMP HATABS,X 7800 BEQ F2 7810 INX 7820 INX 7830 INX 7840 BNE F1 7850 ; 7860 FSET JSR FIND 7870 SET LDA LOWAD,Y 7880 STA HATABS+1,X 7890 LDA #EDTAB/256 7900 STA HATABS+2,X 7910 F2 RTS 7920 ; 7930 JTOGL LDA #01 7940 EOR TOGGLE 7950 STA TOGGLE 7960 JINIT LDX TOGGLE 7970 LDY INMST,X 7980 STY INMSK 7990 LDY OUTMT,X 8000 STY OUTMS 8010 LDA #$FF 8020 STA PORTA 8030 LDX #$38 8040 STX PACTL 8050 STY PORTA 8060 LDX #$3C 8070 STX PACTL 8080 RTS 8090 ; 8100 CEND=* 8110 ; 8120 .END
0100 .OPT NOEJECT 0110 DOSINI=$0C 0120 IN=$CC 0130 OUT=$CE 0140 OFFSET=$D0 0150 MEMTOP=$2E5 0160 CBEGIN=LENGTH+2 0170 *=$3000 0180 ENTER SEC 0190 LDA MEMTOP 0200 SBC LENGTH 0210 LDA MEMTOP+1 0220 SBC LENGTH+1 0230 STA OUT+1 0240 STA OFFSET 0250 TAY 0260 DEY 0270 STY MEMTOP+1 0280 LDY #$FF 0290 STY MEMTOP 0300 INY 0310 STY OUT 0320 LDX #00 0330 LDA #CBEGIN&$FF 0340 STA IN 0350 LDA #CBEGIN/256 0360 STA IN+1 0370 JSR MOVI 0380 HERE TAX 0390 BMI MORE 0400 JSR MOVI 0410 CLC 0420 ADC OFFSET 0430 LDX #00 0440 JSR MOV 0450 BMI HERE 0460 MORE INX 0470 BEQ OVER 0480 DEX 0490 JSR MOVI 0500 BMI HERE 0510 MOV STA (OUT),Y 0520 INC OUT 0530 BNE MOVI 0540 INC OUT+1 0550 MOVI LDA (IN),Y 0560 INC IN 0570 BNE MOVO 0580 INC IN+1 0590 MOVO DEX 0600 BPL MOV 0610 ARND RTS 0620 OVER LDA #01 0630 STA OUT 0640 LDA OFFSET 0650 STA OUT+1 0660 LDA DOSINI 0670 STA (OUT),Y 0680 INC OUT 0690 LDA DOSINI+1 0700 STA (OUT),Y 0710 INC OUT 0720 TYA 0730 STA DOSINI 0740 LDA OFFSET 0750 STA DOSINI+1 0760 JMP (OUT) 0770 LENGTH=*
10 REM RELOCATING PROGRAM FOR XEP80 20 REM TO USE THIS PROGRAM THE FOLLOWING CRITERIA MUST BE MET: 30 REM . THE HANDLER SOURCE CODE MUST BE ASSEMBLED TWICE, THE FIRST 40 REM . ASSEMBLY AT ANY CHOSEN START ADDRESS AND THE SECOND AT 50 REM . THAT ADDRESS+$100. THE FIRST OBJECT CODE WILL BE CALLED 60 REM . H6000.OBJ AND THE SECOND OBJECT CALLED H6100.OBJ. THE 70 REM . RELOCATER CODE MUST BE ASSEMBLED AS FILE MOVE.OBJ. THIS 80 REM . PROGRAM WILL READ IN MOVE.OBJ THEN COMPARE BYTES BETWEEN 90 REM . H6000.OBJ AND H6100.OBJ AND CREATE A LINKED RELOCATABLE 100 REM . STRING. THIS STRING IS APPENDED TO THE MOVE.OBJ STRING 105 REM . THEN WRITTEN TO DISK AS AUTORUN.SYS 110 CLR :DIM A$(2048) 120 DIM REL$(14),OB1$(14),OB2$(14),OUT$(14) 130 REL$="D:MOVE.OBJ" 131 OB1$="D:H6000.OBJ" 132 OB2$="D:H6100.OBJ" 133 OUT$="D:AUTORUN.SYS" 200 PULL=3000:REND=3500:WRITE=4000 205 ADD=5000 210 TREND=32768:IN=1 300 OPEN #1,4,0,REL$:FILE=1 310 TRAP REND:TEND=0 320 GOSUB PULL 322 IF TEND=1 THEN GOTO 340 324 A$(IN,IN)=CHR$(DAT) 325 GOSUB ADD 330 GOTO 320 340 CLOSE #1 350 TRAP TREND 400 OPEN #2,4,0,OB1$ 410 OPEN #3,4,0,OB2$ 415 TRAP REND:TEND=0 417 FOR X=0 TO 5:FILE=2:GOSUB PULL:FILE=3:GOSUB PULL:NEXT X 418 FOR X=0 TO 1:FILE=2:GOSUB PULL:FILE=3:GOSUB PULL 419 A$(IN,IN)=CHR$(DAT):GOSUB ADD:NEXT X 420 COUNT=0 430 SPOT=IN 440 GOSUB ADD 445 IF COUNT>127 THEN GOTO 487 450 FILE=2:GOSUB PULL:IF TEND=1 THEN GOTO 550 455 T1=DAT 460 FILE=3:GOSUB PULL:T2=DAT 470 IF T1<>T2 THEN GOTO 500 480 A$(IN,IN)=CHR$(T1):COUNT=COUNT+1 485 GOTO 440 487 A$(SPOT,SPOT)=CHR$(128) 490 GOTO 420 500 A$(SPOT,SPOT)=CHR$(COUNT) 510 TR=T1-96:REM SHOULD READ FROM FILE 520 A$(IN,IN)=CHR$(TR) 530 GOSUB ADD 540 GOTO 420 550 A$(SPOT,SPOT)=CHR$(COUNT) 551 A$(IN,IN)=CHR$(0) 552 GOSUB ADD 553 A$(IN,IN)=CHR$(255) 554 CLOSE #2:CLOSE #3 560 START=ASC(A$(3,3))+ASC(A$(4,4))*256 570 FEND=START+IN-7 580 HI=INT(FEND/256):LO=FEND-HI*256 590 A$(5,5)=CHR$(LO):A$(6,6)=CHR$(HI) 591 GOSUB ADD:A$(IN,IN+6)="" 600 REM STOP 700 OPEN #4,8,0,OUT$ 710 ? #4;A$; 720 CLOSE #4 800 STOP 900 REM THIS SECTION CAN BE ENABLED TO OUTPUT A HEX VERSION OF THE FILE 1000 DIM T$(16):T$="0123456789ABCDEF" 1002 FOR X=0 TO LEN(A$)-1 1003 M=INT(X/256):MH=X-M*256:H=INT(MH/16):L=MH-H*16:M=M+1:H=H+1:L=L+1 1004 ? T$(M,M);T$(H,H);T$(L,L);" "; 1010 R=ASC(A$(X+1,X+1)) 1020 H=INT(R/16):L=R-H*16:H=H+1:L=L+1 1030 ? T$(H,H);T$(L,L) 1040 NEXT X 1050 STOP 3000 GET #FILE,DAT 3010 RETURN 3500 TEND=1:RETURN
100 REM ATTRIBUTES EXAMPLE 110 REM TO SET ATTRIBUTES USE FOLLOWING DEFINITIONS TO FORM COMMAND 120 REM . THE XEP80 CONTAINS TWO ATTRIBUTE REGISTERS 130 REM . REGISTER A IS USED WHEN A CHARACTER ASCII VALUE IS BELOW 128 140 REM . REGISTER B IS USED WHEN A CHARACTER ASCII VALUE IS ABOVE 127 150 REM . EACH REGISTER REMAINS CONSTANT ACROSS THE SCREEN 160 REM . THAT IS, NO MATTER WHERE A CHARACTER IS PLACED ON THE SCREEN 170 REM . ITS ATTRIBUTES WILL REMAIN THE SAME 180 REM . REGISTER BIT DEFINITIONS: 190 REM . BIT EFFECT IF A 0 200 REM . 0 REVERSE VIDEO 210 REM . 1 NO EFFECT 220 REM . 2 BLINKING 230 REM . 3 NO EFFECT 240 REM . 4 DOUBLE WIDE 250 REM . 5 UNDERLINE 260 REM . 6 BLANK 270 REM . 7 SPECIAL TEXT GRAPHICS 280 REM . TO ISSUE A COMMAND DO THE FOLLOWING: 290 REM . 1) PRINT CHR$(27); 300 REM . 2) PRINT CHR$(VALUE DERIVED FROM ABOVE BIT DEFINITIONS); 310 REM . 3) XIO 20,#1,12,A,"E:" 320 REM . WHERE A=244 FOR REGISTER A AND A=245 FOR REGISTER B 330 REM . THEN PRINT CHARACTERS ON THE SCREEN, EITHER WITH BIT 7 OFF 340 REM . TO USE REGISTER A, OR WITH BIT 7 ON TO USE REGISTER B 400 ? "}";:POSITION 28,11:? "E X A M P L E T E X T ":POKE 752,1 410 GOSUB 2000 500 REM SOME ATTRIBUTE COMBINATIONS 510 ? CHR$(27);CHR$(255-1);:XIO 20,#1,12,245,"E:" 520 ? CHR$(27);CHR$(255-1);:XIO 20,#1,12,245,"E:" 530 GOSUB 2000:REM REVERSE VIDEO 550 ? CHR$(27);CHR$(255-4);:XIO 20,#1,12,244,"E:" 560 ? CHR$(27);CHR$(255-1);:XIO 20,#1,12,245,"E:" 580 GOSUB 2000:REM BLINKING 600 ? CHR$(27);CHR$(255-16);:XIO 20,#1,12,244,"E:" 610 ? CHR$(27);CHR$(255-1);:XIO 20,#1,12,245,"E:" 630 GOSUB 2000:REM SOME DOUDLE WIDE 700 ? CHR$(27);CHR$(255);:XIO 20,#1,12,244,"E:" 710 ? CHR$(27);CHR$(255-16-1);:XIO 20,#1,12,245,"E:" 730 GOSUB 2000:REM OTHERS DOUBLE WIDE 750 ? CHR$(27);CHR$(255-16);:XIO 20,#1,12,244,"E:" 760 ? CHR$(27);CHR$(255-16-1);:XIO 20,#1,12,245,"E:" 780 GOSUB 2000:REM ALL DOUBLE WIDE 800 ? CHR$(27);CHR$(255-128);:XIO 20,#1,12,244,"E:" 810 ? CHR$(27);CHR$(255-128-1);:XIO 20,#1,12,245,"E:" 830 GOSUB 2000:REM ALL GRAPHICS 850 ? CHR$(27);CHR$(255);:XIO 20,#1,12,244,"E:" 860 ? CHR$(27);CHR$(255);:XIO 20,#1,12,245,"E:" 880 GOSUB 2000:REM BACK TO NORMAL 990 POKE 752,0:END 2000 ? "~~";:FOR X=0 TO 999:NEXT X:RETURN
100 REM SCROLLING WINDOW EXAMPLE 105 REM SCROLL LEFT AND RIGHT WITH JOYSTICK, WHEN FINISHED PRESS TRIGGER 107 POKE 53774,64:REM DISABLE BREAK KEY 110 POKE 83,255:POKE 752,1:REM SET RIGHT MARGIN, CURSOR OFF 112 FOR COL=0 TO 3*57 STEP 57:GOSUB 1050:REM CLEAR ALL WINDOWS 114 ? CHR$(125);:NEXT COL:COL=0:GOSUB 1050:REM SET FIRST WINDOW 120 ? CHR$(125);:POSITION 0,20:? "USE JOYSTICK TO SCROLL",,, 125 ? "PRESS TRIGGER BUTTON TO EXIT" 130 FOR X=0 TO 15:POSITION X*16,1:? "COLUMN ";X; 140 GOSUB 1000:FOR Y=3 TO 16:REM ALLOW SCROLLING 150 POSITION X*16+2,Y:? INT(RND(0)*100);:REM MAKE UP A VALUE 160 GOSUB 1000:REM ALLOW SCROLLING WHILE PRINTING 170 NEXT Y:NEXT X 180 GOSUB 1000:GOTO 190-STRIG(1)*10:REM ALLOW SCROLLING, CHECK TRIGGER 190 POSITION 0,20:? CHR$(253);:XIO 20,#1,12,220,"E:":POKE 83,79:POKE 752,0 195 POKE 53774,192:REM ENABLE BREAK KEY 200 END :REM WINDOW TO LEFT EDGE, RESET RIGHT MARGIN, CURSOR ON, EXIT 1000 REM JOYSTICK ROUTINE 1010 A=STICK(1):COL=COL+SGN((A=7)-(A=11)):REM GET DIRECTION AND MOVE 1030 COL=COL*(COL>-1 AND COL<177)+(COL=177)*176:REM LIMITS OF SCROLLING 1050 POSITION COL,20:? CHR$(253);:XIO 20,#1,12,220,"E:" 1060 REM LINE 1050 SETS THE NEW CURSOR AND ISSUES THE SCROLL COMMAND 1090 RETURN
0 GOTO 100:REM KEEP TIME DEPENDENT CODE NEAR BEGINNING 10 FOR M=0 TO 12:V=0:S=128:FOR N=0 TO 7:X=P+N:REM LOOPS FOR CIRCLE LIMITS 20 V=V+S*(X*X+Y*Y*2.3<2500):S=S/2:NEXT N:P=P+8:REM CIRCLE CALCULATION 30 IF V THEN G$(M+1,M+1)=CHR$(V):REM SET BITS FOR OUTPUT STRING 40 NEXT M:? G$;:GOTO 170:REM PRINT OUTPUT STRING 100 REM GRAPHICS DISPLAY EXAMPLE TO DRAW CIRCLE 110 POKE 752,1:? CHR$(125);:DIM G$(40),D$(40):REM CURSOR OFF 111 ? :? " PRESS ANY KEY TO BEGIN GRAPHICS PLOTTING (TOTAL TIME 5 MIN)" 112 ? :? " WHEN PLOT IS FINISHED PRESS ANY KEY TO RETURN TO TEXT SCREEN" 113 IF PEEK(764)=255 THEN 113 114 POKE 764,255:REM RESET CHARACTER INPUT BYTE 115 D$=CHR$(0):D$(40)=CHR$(0):D$(2)=D$:GRAPHICS 8+16:REM INIT STRING 117 POKE 53774,64:REM DISABLE BREAK KEY 120 FOR Y=-32 TO 32:REM VERTICAL AXIS LOOP 130 G$=D$:P=-50:GOTO 10:REM GO TO TIME CRITICAL CODE 170 NEXT Y 180 IF PEEK(764)=255 THEN 180:REM HOLD SCREEN 185 POKE 53774,192:REM ENABLE BREAK KEY 190 POKE 764,255:OPEN #1,12,0,"E:":POKE 752,0:END :REM RESTORE TEXT SCREEN
100 REM PRINTER CONFIGURATION PROGRAM 110 DIM A$(2048),IN$(16),OUT$(16):REM ALLOCATE STRINGS 120 IN$="D:AUTORUN.SYS":REM READ THIS FILE 130 OUT$="D:PRINT.SYS":REM CREATE THIS FILE 140 TRAP 32000:REM IF NO AUTORUN.SYS 150 OPEN #1,4,0,IN$ 160 TRAP 180:REM TO CATCH EOF 170 A=A+1:GET #1,B:A$(A,A)=CHR$(B):GOTO 170:REM BUILD INPUT STRING 180 CLOSE #1 190 I=136:? "AUX1 VALUE";:INPUT A:REM PRINTER AUX1 BYTE 200 A$(I,I)=CHR$(A) 210 I=137:? "AUX2 VALUE";:INPUT A:REM PRINTER AUX2 BYTE 220 A$(I,I)=CHR$(A) 230 OPEN #2,8,0,OUT$ 240 ? #1;A$;:CLOSE #2:REM WRITE MODIFIED STRING TO FILE 250 END 32000 ? "FILE NOT FOUND"