A.N.A.L.O.G. ISSUE 2 / MARCH 1981 / PAGE 44
One of the editors called me, quite unexpectedly the other day. “Hi, this is Lee”, he said. “I just came up with a great idea for an article that you can write for the next issue. How ’bout a tutorial on the new Assembler/Editor cartridge?” Now, I hate to even read tutorial articles, let alone write them, but I kept listening anyway. “Oh, and by the way”, he said as he baited his trap, “when the article is finished, I will let you borrow my video tape copy of FLASH GORDON!” That did it. I had to turn out some kind of tutorial article. Even though I hate tutorials, I was being forced to submit one for publication. After all, how long could it possibly take to write one little tutorial? It shouldn’t take more than five or six double spaced sheets of paper, maybe a week to ten days at the most. “When do you need this finished?”, I asked, not expecting the answer that followed. “I need this article by Friday”, was his reply. He couldn’t mean this Friday? This Friday was only three days away. “That’s this Friday”, he reiterated. My worst fears about Lee’s mental stability had been confirmed. He had lost his mind!
Since I missed “FLASH GORDON” when it was playing at the theater, giving Lee the benefit of the doubt seemed the safest thing to do. After all, a person writing a tutorial has three choices. He can write a tutorial, or he can write about something else and call it a tutorial (hoping that a certain person, in his crazed state will not notice), or he can do a little of both, like I am doing. I just don’t want to bore myself when I have to read this later, checking the spelling, etc.
This is a good time as any to put in a word about writing articles for A.N.A.L.O.G. magazine. We need you to share your ideas with the rest of us ATARI owners. People are always complaining that they can just type into their computers. It is really your own fault. Half the enjoyment of writing a “game” program, for example, is knowing that other people are enjoying your work right along with you. And when it is printed in a magazine, thousands can join in the fun too. Now I do have a selfish reason for telling you all this. The more people who write articles and submit programs, the less I have to do, and I can get down to the business of writing terrific game programs.
The Assembler/Editor cartridge which was released only a few months ago, is a much needed accessory, useful by those who are serious about writing compact and efficient programs. It was a long time in coming, since the cartridge was ready almost a year before the documentation. ATARI decided to wait until the manual was ready before releasing the ROM. The people who created this program managed to get a lot of features in the 8K memory space they had to work with. There are three separate sections ot the Assembler/Editor.
The Editor, is an enhanced version of the screen editor built into the ATARI personality module. Besides the regular edit features of the cursor positioning and character-line insertion and deletion, it also contains commands to renumber lines (the line numbering increments at a specified interval), so if the line numbers originally were 10, 12, 13, 22, then typing REN would produce line numbers of the sequence 10, 20, 30, 40. Besides deleting a line by typing it’s line number, you can now delete a group of lines in a program by typing DEL XX, YY. If you want to erase all the lines in a program between 300 and 450 inclusive, all you would have to do is DEL 300, 450.
Did you ever get bored of typing the line numbers of the program in, especially when they are set up in a numerical sequence? Did you ever wish that the machine could do it for you? Well, get out your whistles and party hats, the Assembler/Editor can do it all for you! After you type in the statement NUM, the editor will come up with the line numbers after every return you type in. You enter the statements. The computer does the rest. Oh, I wish that a few of these features had been implemented in ATARI BASIC.
We now come to the two string type commands that someone was thoughtful enough to include in the editor. The first is FIND. This command is used to find a specified string in a program. For example, let’s say we want to find the string “START”. Just type in ‘FIND/START/,’ and the first occurence of this string will be listed. More than likely, you want to list all occurances of the string that you are looking for. Just append an ‘A’, to the command so that it becomes ‘FIND/START/,A’ and the machine will list all the lines which contain the string “START” to the screen. You can even specify line delimiters, listing all lines between line X and line Y that have the string. During all of this, I have been using the chracter “/” as a delimiter. In reality, any character except a space, tab, and return can be used. And if the string you are searching for contains the character “/”, you will have to use something else. FIND./2.,A is legal. Here “.” was used instead of “/”, because the string contained a “/”. FIND?/2?,A is also legal. It sure beats looking through a 500 line program listing for a few spelling errors.
What if, after finding all the occurances of string “/2”, you realize that you have made a mistake. You want them all to be “/4” instead. You can either go through every line that contains the string, or you can let the computer do it for us. This brings us to the last edit feature that I find note worthy. That is the command REP. To replace all occurances of string “/2” with “/4” all we have to type is REP./2./4.,A and presto chango, it is done. This time I used the period “.” as a delimiter, as long as the character used is not in the strings. If the “/,A” was left off the end, only the first occurance of “/2” would have changed. You can even specify a line number range in which to replace, like the command “FIND”. But what if you do not want to replace every occurance? If you tack an “,Q” on the end of the command’ instead of an “,A”, the computer will list the line with the string and prompt you with a question “?”. If you type a “Y” followed by a return, the string will be changed. If you just type a return, the string will be left intact.
To do I/O (Input/Output) to the editor, you have three statements that may be used. Loading a program into the computer is the function of the command “ENTER”. You type the word ENTER followed by the pound sign “#”, and the device to load from. Entering a program from the cassette is “ENTER#C:”. From a disk file, you could use “ENTER#D:YIPPIE”.
Saving a program is done with a variation of the “LIST” command. Normally the LIST command is used to list a program on the screen, “LIST”, or on a printer. “LIST#P:”. In order to save a program on the cassette recorder, we LIST it to device C:; LIST#C:. To save it on a disk file, one types “LIST#D:YIPPIE”. The cartridge does have the commands “LOAD” and “SAVE” but these are used in the storage of binary load files only.
A variation on LIST is the command PRINT. PRINT does the same thing as LIST except it drops the line numbers in the process. I have not found much use for this command yet, except in one instance. One day while generating a data file of strings (yes folks, this cartridge does not check for syntax errors like BASIC does, because it does not store programs in a tokenized form). I had typed in the lines with line numbers so that the editor would not accept them as commands. After all the editing was done and the line numbers were no longer needed, I was going to write a BASIC program to read them in, and write them back out, minus the line numbers. Lee, however, came up with a great idea. “Why not do a PRINT to the disk drive with the data, then you don’t have to write a conversion program”, he said. You know, there may be hope for him yet.
Now, how would you like to use the added editing features on your BASIC programs. That is right! You can delete groups of lines, replace character strings. and enter lines with automatic line numbers. How do you do all this to your BASIC programs, you ask? First, after powering up with BASIC and loading your program, you LIST it to your storage device, be it cassette “C:” or disk “D:YIPPIE”. Then you remove the BASIC cartridge and insert the Assembler/Editor cartridge. As ENTER from your cassette or disk is performed, and voila, you can now work on your BASIC program with a much superior editor. To go back, we simply LIST the program to the storage device, swap back to BASIC, and perform ENTER from the device in BASIC. Now, it is just a simple matter of resaving programs, and you are done.
In this issue, I have discussed only the features of the Editor. In the next issue the Assembler will be covered, which allows you to produce machine language programs. And the Debugger, which allows you to examine memory locations, trace program execution, disassemble machine code, and many other things. This cartridge is well worth having, and like I said before, a long time in coming.
So you don’t think I read articles before they go in Charlie??? Well next issue, you had better get me that assembly language tutorial, or no borrowing any more science fiction video tapes! — Lee
A.N.A.L.O.G. ISSUE 3 / MAY 1981 / PAGE 16
This column is about the ATARI Editor/Assembler cartridge, which is of course available from ATARI. In the last issue, I talked about the new editing features of the cartridge, some tricks of the trade, and losing my Sci-Fi video tape privileges. But there is some good news, folks! I have just acquired a 32K memory board and have transplanted it into my ATARI 400. That’s right, the big kid has a little 400!
The Assembler half of the Editor/Assembler has one fault that everyone who has used it is aware of. It is very, very slow ! If your assembly program is over several hundred lines long, you might as well start reading “War and Peace” because it is going to take forever before it is finished. Assembly speed seems to be about two hundred lines a minute, which I consider to be terribly slow. Maybe ATARI will speed things up in their Macro Assembler that is rumored to be on the way. We will just have to wait!
This Assembler has a lot of plus features going for it, the nicest being the use of pseudo operations, also known as directives. These wonderful non-instructions (after all, this is a non-tutorial) enable special features in the Assembler. The most general case non-instruction is the .OPT directive. With it, you can set or reset a number of switches in the Assembler. It can be used to suppress the program listing, the generation of object code, the flagging of errors, and the page ejects that are normally inserted in an assembly listing every 56 lines. Whew, what a mouthful! Broken down, here is what the options look like.
|.OPT NOLIST||turns listing off|
|.OPT LIST||turns listing on (default)|
|.OPT NOOBJ||turns code generation off|
|.OPT OBJ||turns code generation on (default)|
|.OPT NOERR||turns error messages off|
|.OPT ERR||turns error messages on (default)|
|.OPT NOEJECT||turns page ejects off|
|.OPT EJECT||turns page ejects on (default)|
Multiple options may be enabled or disabled by inserting them on the same line, separated by commas.
|.OPT NOEJECT, NOOBJ||two options in one|
I am not going to go into too much detail here about the use of .OPT because when you buy the cartridge, you also receive an excellent eighty-page user’s manual which goes into much more detail than I possibly could. Please read the manual!
Another interesting feature is that you can also title the pages of the assembly listings. This makes for a more professional appearance. People will actually think that you know what you are doing. To title each page of the listing, just insert the directive .TITLE followed by a string in quotes. For example, .TITLE "STAR RAIDERS BY C.BACHAND" (just kidding folks!) would put the string that is in quotes at the top of every page in the listing. You can even put a subtitle on each page to identify the routines there. This will not change the main title, but it will force a page eject. Subtitles use the directive .PAGE instead of .TITLE.
I hope that everyone realizes that when you enter a directive, or any program line for that matter, into the computer, it must be preceeded by a line number. This point of interest might have slipped my mind earlier, so I am including it now. After all, I would not want people walking around with their heads cut off saying “The dang thing don’t work!”
This non-tutorial seems to have turned into a description of the unusual directives used by the Editor/Assembler cartridge. And so, not wanting to break with tradition, and since there seems to be only one other highly unusual non-instruction, I will now tell you the tale of the immortal .IF directive. This instruction to the Assembler allows you to selectively assemble blocks of code, depending on the value of a numeric expression. If the expression is equal to zero, then the code will be assembled. The format is shown below. First, the directive .IF, followed by a numeric expression, an at sign “@”, and last the label to jump to if the expression does not equal zero.
100 .IF SWITCH@NOASM 110 ;CODE TO ASSEMBLE 120 NOASM
You might be asking, “What use could this be to me?” Well, let us suppose that you are writing this great game program, all in assembly language. And you want it to handle either a joystick or a light pen. You do not need both devices in your program, but you do want to have two different versions of the game. This is where the .IF directive comes in very handy.
100 ;JUMP HERE FOR ALL GAME INPUTS WITH THE 110 ;LABEL JOYSTICK=0 FOR JOYSTICK INPUT OR 120 ;JOYSTICK=1 FOR LIGHT PEN INPUT 130 .IF JOYSTICK@NOJOYSTICK 140 JOYSTICK CODE GOES HERE. 150 NOJOYSTICK 160 .IF JOYSTICK-1@NOLIGHTPEN 170 ;LIGHT PEN CODE GOES HERE. 180 NOLIGHTPEN 190 ;END OF GAME INPUTS
Well, it is now about 2 o’clock in the morning and I am beginning to fall asleep in front of the typewriter. Only a few hours ago I received another phone call from our fearless leader and editor, (Count Drax to the uninformed) asking me for the umpteenth time “Where is the article?” I told him flat out that I have more important things to do with my time than to type away for him all day long. For example, I have to wash my car. I also have to catch a very important episode of “Gilligan’s Island” (this week, Gilligan volunteers to test the Professor’s home made thermo-nuclear device).
A.N.A.L.O.G. ISSUE 4 / SEPTEMBER 1981 / PAGE 50
One piece of software that has come my way is an Assembler/Editor program by Optimized Systems Software (OSS) called EASMD. This is a disk based program that is remarkably similar to ATARI’s cartridge Assembler. And well it should be, for it was written by the same people who wrote the ATARI Assembler. Now, since this version is resident in RAM, the programmers were not limited to the space restraints of a ROM cartridge. They had plenty of space left for those little extras such as long error messages, a symbol table at the end of an assembler listing, verification of a line after changing characters using the command REP, and the feature that makes me pick it over the cartridge: the directive .INCLUDE #filename.
You might have guessed that programmers who do a lot of work with an Assembler (like maybe 4K of object code is a lot, eh!), tend to have very large source code files. So much source code in fact, it will not all fit into the available RAM space (even with 48K). This is where the .INCLUDE directive of OSS’s EASMD comes into play. Instead of one big file of source code, the program is written as a bunch of little files. As an example, we will call these files "D:FILE1", "D:FILE2", and "D:FILE3". These will be my source files. We now make one last file, which contains the following statements:
0100 .INCLUDE 0100 .INCLUDE #D:FILE1 0110 .INCLUDE #D:FILE2 0120 .INCLUDE #D:FILE3
When these statements are executed, OSS’s EASMD will open FILE1, read the source code, close FILE1, open FILE2, read that source code, etc., etc.
INCLUDE directives are not necessarily limited to a separate file. They may be included within the text of a program. An example of this would be the inclusion of often used subroutines in one’s programs. Many of my own machine language programs make extensive use of joysticks and the START, SELECT, and OPTION switches. Since the code to access these devices was written to be the same in all cases, it is to my advantage to have the Assembler INCLUDE the code while it is in the process of assembling. This cuts down not only on typing, but also your disk space usage. The INCLUDE feature is an absolute necessity when your lines of source code start to number in the thousands.
Getting back to some resemblance of a tutorial, I would like to tell you a little about binary load files and a curious problem I encountered. This problem, it turns out, was with my understanding of binary loaded files at the time. But first, what the @&.%"?# is a binary load file?
As you may have noticed, the menu for Atari’s Disk Operating Systems, DOS for short, come onto your television screen, there are two options displayed which are rarely used by many casual users. These are (L) Binary Load, and (M) Run at Address. The first loads a binary file into RAM and the second specifies the address to start executing a machine language program at.
A binary file is organized in such a way that a program, such as DOS, will be able to load it into memory. The format that was finally decided upon, and which is used by both DOS II and the Assembler/Editor Cartridge is to start the file with two bytes containing 255’s (or $FF to those HEXadecimal hacks out there. Yes, we know who we are!!) as a file header. A loader program will generate an error if during a load it does not first encounter these two bytes. The next two bytes contain the starting address, the location where the binary load is to begin. The micro-processor expects to see addresses with the low byte first, high byte second (for a hex address of $1234 for example, the first byte would be $34, and the second would be $12) and so for conformity, the binary loader handles memory addresses in the same way. Now that the loader knows where to start loading, it next needs to know how many bytes to load into memory. The next two bytes however, do not contain this information, but they do contain the next best thing, the ending address of the binary load, in low byte first, high byte second format. The bytes that follow are what make up the actual machine language program. No, that’s not entirely true. It is only the ENDING ADDRESS minus the STARTING ADDRESS number of bytes that are loaded, If the end-of-file (EOF) has not been reached, then it tries to load another block of memory by looking for another starting address (low byte, high byte), another ending address (low byte, high byte), and more machine language data. In this way, a binary load file can load data into low memory, into high memory, and memory in between.
Now that you understand that (I hope!), we can discuss my problem. After a binary file is loaded into memory, we need to find a way to start it executing. If it is going to just sit there, it is of no use to us. There are three ways of giving life to your creation. #1, use the USR function in BASIC, #2, use the (M) Run At Address command in DOS, or #3, use the G command of the Debugger that resides in the Editor/Assembler Cartridge (or OSS’s EASMD for that matter). But I have heard stories of load file software running itself after loading. If this has ever happened to you, please do not try to exorcise evil spirits, for it is perfectly natural. There is a fourth way to run your software.
There are two secret (not any more, eh!) bytes in DOS which contain the address that the loader program jumps to after every memory load. Normally, these two bytes point to the routines to load another block of memory, but since these two bytes are located in RAM, they can be changed. Give you any ideas! If we change these two bytes to point to the entry point of OUR routine instead of THEIR routine, our program will start up immediately after loading! Wonderful, isn’t it!!
Now for the particulars. The starting address of these two bytes is 736 decimal (for you HEX hacks, better make it $2E0). Now comes the fun part. To get your load files to run automatically, six bytes (is that all?) must be appended onto your files. The first two bytes are the starting address of 736 (or $2E0 HEX), low byte first (224 or $E0 HEX), high byte second (2 or $02 HEX). Then comes the ending address of 737 (or $2E1 HEX), again using the low byte (225 or $E1 HEX), high byte (2 or $02 HEX) sequence. Sound familiar? The last two, and final bytes contain the entry point address of YOUR software. I am not a mind reader, so I cannot tell you wht the numbers should be, but only that they should also be in reversed (low byte, high byte order). In Assembly language, it would look like this:
0900 *=$02E0 ;Generates START and END addresses 0910 .WORD INTRO ;Your execution address here!
Now for a word of warning! The Auto-boot has to be the last block in a binary file. Take it from someone who knows. I wrote a program and put the AUto-boot at the beginning. The subsequent load file was 32 sectors longs and you can imagine my surprise when it tried to run itself after loading only one of those 32 sectors. This had me going crazy for a whole weekend! What had happened, if you haven’t already guesses, was that the DOS had loaded the new Auto-boot address into its RAM location and proceeded to run my space war program, even before the game was loaded into memory. Like jumping into a swimming pool before the water is put in!
A.N.A.L.O.G. ISSUE 5 / JANUARY 1982 / PAGE 38
“Have you ever wondered how and why something works?” This question has been asked by countless books and magazines, mostly as a lead for them to tell you just How and Why. That question is a little lengthy. “Have you ever wondered why, when you use the BASIC function STICK(0), that it doesn’t return nice numbers such as 0=LEFT, 2=RIGHT, etc., but instead gives you weird numbers like 15=NOTHING, 11=LEFT, 7=RIGHT, etc.?”.
Now that I’ve done my “Andy Rooney talking about his ties” imitation, it is time to switch scenes again. “Hey Ma! My joystick is BROKE! You’ll have to buy me another one!”, the little boy said. “That’s the third one that you’ve broken. You’ll just have to wait till I can get to the store next week.”, was his mother’s reply. This, for the little boy, just would not do. He was very involved in a game of Missile Command (tm) and had already accumulated well over one hundred and twenty thousand points and would probably die of old age by next week anyway. Maybe the Joystick could be repaired? There was nothing to loose. He just had to find out. Did you ever wonder what is in a Joystick? Did you ever wonder how a Joystick works? Did you ever wonder why they call it a Joystick? Ever wonder how the little boy broke all three of his joysticks or why his mother has put up with him for so long? And did you ever wonder why I am constantly saying “Did you ever wonder”?
A Joystick is a very simple device. After removing four screws and taking the bottom off, one finds only a few plastic parts, some wires, and a circuit board containing push button switches. A Joystick is just five switches and a connecting stick. So where do the funny numbers for up, down, left, and right come from? Well, I am going to tell you all about it. Atari Joysticks are connected into the computer by a parallel input port. This means that when your program reads information from this parallel port, there is one bit for each switch. The lowest most significant bit (we will call it bit “0” since numbering systems using computers start counting with the number “0”) senses the upward push on a Joystick. The following table shows the other bit positions.
Now, the nibble or four bit subbyte, is not the value returned by the joystick ports. The value returned is the inverse of the values shown in the previous table. The correct values are shown in the next table.
The inverse bit values you receive from the joystick ports are due to the way the joysticks themselves are wired. The switch contacts are connected to the port lines with pull-up resistors. These resistors apply a constant +5 volts signal to the lines forcing the logic to a high level. When you push on the joystick, the switch or switches (in a diagonal position) close and bring the signal from d5 volts to volts, bringing the logic at the port to a low logic level. The bit read from its corresponding switch is changed from a logic 1 to 0. All we need now is a demonstration in machine language.
MAPWARE, written by Harry C. Koons, is one of the more interesting programs to come out of APX (Atari Program Exchange). Using this program, it is possible to generate maps of any section of the earth. The software is written in BASIC and is distributed on two diskettes. The first disk contains programs to generate maps using different projection methods and a program to display a previously generated and stored map. The second disk contains the coordinate data of every important land feature in the world. This disk contains over 640 blocks of information, which translates to over 80 thousand characters of information. It even generates the U.S. state boundaries. Since the programs are written in BASIC, they tend to be on the slow side, usually taking from ten to twenty minutes to generate a map, but the results are well worth it. I strongly recommend this package to anyone with a 40K system.
Now, what does this program have to do with joysticks, you might be wondering. What can a joystick do to a stationary map? Believe me, these maps won’t be stationary for very long!
You’ve all seen scrolling. It happens every time you enter a line in a BASIC program with a full screen. The lines of text before it all move up when you hit RETURN. This is known as coarse vertical scrolling. Also, coarse horizontal scrolling. You usually see this when editing text, especially when characters are inserted or deleted in the middle of a line. The rest of the text moves sideways. We have all seen this happen. It’s really no big deal.
What you may not know is that the ATARI computer has the ability to FINE scroll vertically, and horizontally. Characters and pictures can be moved up and down in increments of one scan line on the television set. They can also be moved left and right in increments of one color clock (the width of a point in graphics mode 6 or 7). All this power is hidden in your machine, and you probably never know it unless you played such games as Atari’s SPACE INVADERS (horizontal scrolling) or ANALOG SOFTWARE’s Race In Space (vertical scrolling). We, using our map and out joystick are going to do both!
Now, it really does not have to be a map. You can use any picture that was drawn in full screen graphics mode 8 (GRAPHICS 8+16), as long as a screen dump of the picture has been stored on tape or diskette. The accompanying program will load your picture into RAM in full screen mode 6 (GRAPHICS 6° 16) even though the graphics were originally in full screen mode 8. The internal graphic representation between the two modes is the same, one pixel for each bit position in memory. And since graphics mode 6 has half the resolution, both horizontally and vertically, that graphics mode 8 has, you will be able to see only a quarter of the actual picture or map. The program will allow you to scroll the television’s screen over the picture while being controlled by the joystick. You will be able to see only 25% of the picture at any one time, but you will be able to choose which 25% to look at.
100 REM SCROLLING MAPWARE 110 REM DISPLAY PROGRAM 120 REM 130 REM BY CHARLES BACHAND 1982 140 REM 150 REM TO LOAD ANOTHER FILE, 160 REM PUSH SYSTEM RESET AND 170 REM TYPE RUN. 189 REM 190 DIM NAME$(20),MLOAD$(41) 200 DIM SCRL$(161),INIT$(130) 210 GRAPHICS 8:POKE 752,1:GOSUB 360 220 PRINT "MAP SCROLL PROGRAM":PRINT 230 PRINT "MAPWARE FILE NAME ==> "; 240 INPUT NAME*: TRAP 220:? :? :? 250 SETCOLOR 2,0,0:POKE 752, 1 260 PRINT "SCROLLING FILE => ";NAME$ 270 REM 280 REM LOAD GRAPHICS DATA 290 REM 300 CLOSE #1:OPEN #1,4,0,NAME$ 310 A=USR(ADR(MLOAD$)) 320 IF A>127 THEN 220 330 FOR COUNT=1 TO 500:NEXT COUNT 340 A=USR(ADR(INIT$),ADR(SCRL$)) 350 GOTO 350 360 REM 370 REM INITIALIZATION RUUTINES 380 REM FOR FINE SCROLLING OF DISPLAY 390 REM 400 REM BINARY DATA LOADER 410 REM 420 PRINT "LOADING ML SUBROUTINES" 430 FOR C0UNT=1 TO 41: READ VALUE 440 MLOAD$(COUNT)=CHR$(VALUE) 450 NEXT COUNT 460 REM 470 REM DISPLAY LIST INITIALIZER 480 REM 490 FOR COUNT=1 TO 130:READ VALUE 500 INIT$(COUNT)=CHR$(VALUE) 510 NEXT COUNT 520 REM 530 REM DISPLAY SCROLL ROUTINE 540 REM 550 FOR COUNT=1 TO 161: READ VALUE 560 SCRL$(COUNT)=CHR$(VALUE) 570 NEXT COUNT:POKE 752,0:PRINT 580 RETURN 590 REM DATA FOR MACHINE LANGUAGE 600 REM SUBROUTINES 610 REM 620 REM BINARY LOADER CODE 630 REM 640 DATA 104,162,16,169,7,157,66,3 650 DATA 169,0,157,72,3 660 DATA 169,30,157,73,3,165,88,157 670 DATA 68,3,165,89,157,69,3,32,86 680 DATA 228,189,67,3,133,212 690 DATA 169,0,133,213,96 700 REM 710 REM DISPLAY INITIALIZE CODE 720 REM 730 DATA 104,169,0,133,179,169,160 740 DATA 133,178,169,112,141,0,6 750 DATA 141,1,6,141,2,6,160,80 760 DATA 166,88,202,202,134,176,165 770 DATA 89,133,177,162,3,169,123 780 DATA 157,0,6,232,165,176,157,0,6 790 DATA 232,165,177,157,0,6,232 800 DATA 165,176,24,105,40,133,176 810 DATA 144,2,230,177,136,208,224 820 DATA 169,91,157,253,5,169,66 830 DATA 157,0,6,173,148,2,157,1,6 840 DATA 173,149,2,157,2,6,169,2 850 DATA 157,3,6,157,4,6,157,5,6 860 DATA 169,65,157,6,6,169,0,157,7,6 870 DATA 141,48,2,169,6,157,8,6 880 DATA 141,49,2,104,170,104,168 890 DATA 169,7,32,92,228,96 900 REM 910 REM FINE SCROLL CODE 920 REM 930 DATA 169,0,133,176,133,177 940 DATA 173,120,2,41,8,208,21 950 DATA 165,178,240,45,198,178 960 DATA 165,178,41,7,141,4,212 970 DATA 201,7,208,32,230,176 980 DATA 208,28,173,120,2,41,4 990 DATA 208,21,165,178,201,160 1000 DATA 240,15,230,178,165,178,41,7 1010 DATA 141,4,212,208,4,198,176 1020 DATA 198,177,173,120,2,41,2 1030 DATA 208,28,165,179,201,228 1040 DATA 240,22,230,179,165,179,41,1 1050 DATA 141,5,212,208,11,165,176,24 1060 DATA 105,40,133,176,144,2 1070 DATA 230,177,173,120,2,41,1 1080 DATA 208,28,165,179,240,24 1090 DATA 198,179,165,179,41,1 1100 DATA 141,5,212,201,1,208,11 1110 DATA 165,176,56,233,40,133,176 1120 DATA 176,2,198,177,160,0,185,4,6 1130 DATA 24,101,176,153,4,6,185,5,6 1140 DATA 101,177,153,5,6,200,200,200 1150 DATA 192,240,208,232,76,98,228 1160 END
0000 0100 .OPT NOEJECT 0110 ; 0120 ; MAPWARE SCROLL PROGRAM 0130 ; MACHINE LANGUAGE ROUTINES 0140 ; BY CHARLES BACHAND 1982 0150 ; 0160 ; NOTE: ALL MACHINE LANGUAGE ROUTINES 0170 ; PRESENTED HERE ARE RELOCATABLE 0180 ; SINCE ALL JUMPS WITHIN THE ROUTINES 0190 ; ARE RELATIVE JUMPS. 0200 ; 0210 ; SYSTEM EQUATES 0220 ; 0600 0230 LIST = $0600 DISPLAY LIST 0010 0240 IOCB1 = $10 CONTROL BLOCK OFFSET 0007 0250 GETCHR = $07 GET CHARACTERS CMD 0058 0260 SAVMSC = $0058 DISPLAY DATA PNTR 0294 0270 TXTMSC = $0294 SPLIT SCREEN PNTR 0342 0280 ICCOM = $0342 I/O COMMAND BYTE 0343 0290 ICSTA = $0343 I/O STATUS BYTE 0344 0300 ICBAL = $0344 I/O BUFFER (LOW) 0345 0310 ICBAH = $0345 I/O BUFFER (HIGH) 0348 0320 ICBLL = $0348 BUFFER LENGTH (LOW) 0349 0330 ICBLH = $0349 BUFFER LENGTH (HIGH) 0230 0340 DLISTL = $0230 DISPLAY LIST PNTR 0231 0350 DLISTH = $0231 DISPLAY LIST PNTR 0278 0360 STICK = $0278 JOYSTICK REGISTER D404 0370 HSCROL = $D404 HORIZONTAL SCROLL D405 0380 VSCROL = $D405 VERTICAL SCROLL E456 0390 CIOV = $E456 CENTRAL I/O VECTOR E45C 0400 SETVBV = $E45C VBLANK SET VECTOR E462 0410 XITVBV = $E462 EXIT FOR V-BLANK 00D4 0420 BASVAL = 212 RETURNED VALUE ADDR 0000 0430 SIZEL = 7680&$FF SCREEN SIZE (LOW) 001E 0440 SIZEH = 7680/256 SCREEN SIZE (HIGH) 0450 ; 0000 0460 *= $00B0 0470 ; 0480 ; PAGE 0 VARIABLE ASSIGNMENTS 0490 ; 00B0 0500 OFFLO *= *+1 SCROLL DATA (LOW) 00B1 0510 OFFHI *= *+1 SCROLL DATA (HIGH) 00B2 0520 XPOS *= *+1 X-COORDINATE DATA 00B3 0530 YPOS *= *+1 Y-COORDINATE DATA 0540 ; 00B4 0550 *= $1000 RELOCATABLE CODE 0560 ; 0570 ; INITIALIZATION ROUTINE TO SET UP NEW 0580 ; DISPLAY LIST, AND INITIALIZE POINTERS 0590 ; 1000 68 0600 INIT PLA POP PARAMETER COUNT 1001 A900 0610 LDA #0 BOTTOM OF SCREEN 1003 85B3 0620 STA YPOS INITIALIZE Y-COORD 1005 A9A0 0630 LDA #160 RIGHT EDGE OF SCREEN 1007 85B2 0640 STA XPOS INITIALIZE X-COORD 1009 A970 0650 LDA #$70 'SKIP 8 LINES' OPCODE 100B 8D0006 0660 STA LIST 3*8=24 SCAN LINES 100E 8D0106 0670 STA LIST+1 3*8=24 SCAN LINES 1011 8D0206 0680 STA LIST+2 3*8=24 SCAN LINES 1014 A050 0690 LDY #80 80 DISPLAY LINES 1016 A658 0700 LDX SAVMSC DISPLAY ADDR (LOW) 1018 CA 0710 DEX OFFSET FOR HSCROLL 1019 CA 0720 DEX OFFSET FOR HSCROLL 101A 86B0 0730 STX OFFLO DISPLAY POINTER (LOW) 101C A559 0740 LDA SAVMSC+1 DISPLAY ADDR (HIGH) 101E 85B1 0750 STA OFFHI DISPLAY POINTER (HIGH) 1020 A203 0760 LDX #3 DISPLAY LIST OFFSET 1022 A97B 0770 ILOOP LDA #$7B MODE 6 W/H+VSCROL+LMS 1024 9D0006 0780 STA LIST,X STORE INSTRUCTION 1027 E8 0790 INX INCREMENT INDEX 1028 A5B0 0800 LDA OFFLO DISPLAY POINTER (LOW) 102A 9D0006 0810 STA LIST,X LMS ADDRESS (LOW) 102D E8 0820 INX INCREMENT INDEX 102E A5B1 0830 LDA OFFHI DISPLAY POINTER (HIGH) 1030 9D0006 0840 STA LIST,X LMS ADDRESS (HIGH) 1033 E8 0850 INX INCREMENT INDEX 1034 A5B0 0860 LDA OFFLO DISPLAY POINTER (LOW) 1036 18 0870 CLC CLEAR CARRY FOR ADD 1037 6928 0880 ADC #40 MODE 8 BYTE COUNT 1039 85B0 0890 STA OFFLO STORE NEW VALUE 103B 9002 0900 BCC INIT2 OVERFLOW ON ADD? 103D E6B1 0910 INC OFFHI YES, NEW HIGH BYTE. 103F 88 0920 INIT2 DEY 80 INSTRUCTIONS? 1040 D0E0 0930 BNE ILOOP NO, DO SOME MORE. 1042 A95B 0940 LDA #$5B MODE 6 W/HSCROL + LMS 1044 9DFD05 0950 STA LIST-3,X CHANGE LAST OPCODE 1047 A942 0960 LDA #$42 MODE 0 W/LMS 1049 9D0006 0970 STA LIST,X STORE INSTRUCTION 104C AD9402 0980 LDA TXTMSC TEXT WINDOW PNTR (LOW) 104F 9D0106 0990 STA LIST+1,X STORE POINTER (LOW) 1052 AD9502 1000 LDA TXTMSC+1 TEXT WINDOW (HIGH) 1055 9D0206 1010 STA LIST+2,X POINTER (HIGH) 1058 A902 1020 LDA #$02 MODE 0 OPCODE 105A 9D0306 1030 STA LIST+3,X 2ND LINE TEXT 105D 9D0406 1040 STA LIST+4,X 3RD LINE TEXT 1060 9D0506 1050 STA LIST+5,X 4TH LINE TEXT 1063 A941 1060 LDA #$41 JUMP + WAIT FOR VBLANK 1065 9D0606 1070 STA LIST+6,X STORE OPCODE 1068 A900 1080 LDA #LIST&$FF DISPLAY LIST (LOW) 106A 9D0706 1090 STA LIST+7,X JUMP ADDRESS (LOW) 106D 8D3002 1100 STA DLISTL OS POINTER (LOW) 1070 A906 1110 LDA #LIST/256 DISPLAY LIST (HIGH) 1072 9D0806 1120 STA LIST+8,X JUMP ADDRESS (HIGH) 1075 8D3102 1130 STA DLISTH OS POINTER (HIGH) 1078 68 1140 PLA VBLANK ROUTINE (HIGH) 1079 AA 1150 TAX SET X REGISTER 107A 68 1160 PLA VBLANK ROUTINE (LOW) 107B A8 1170 TAY SET Y REGISTER 107C A907 1180 LDA #$07 VBLANK SET CODE 107E 205CE4 1190 JSR SETVBV SET VBLANK ADDRESS 1081 60 1200 RTS RETURN TO BASIC 1082 1220 *= $2000 RELOCATABLE CODE 1230 ; 1240 ; FAST MAP LOADING CODE 1250 ; 1260 ; READS IN 7680 BYTES FROM DEVICE #1 1270 ; TO SCREEN MEMORY VERY QUICKLY! 1280 ; 2000 68 1290 LOAD PLA POP PARAMCTER COUNT 2001 A210 1300 LDX #IOCB1 CONTROL BLOCK #1 2003 A907 1310 LDA #GETCHR GET CHARACTERS CMD 2005 9D4203 1320 STA ICCOM,X SET COMMAND 2008 A900 1330 LDA #SIZEL SCREEN SIZE (LOW) 200A 9D4803 1340 STA ICBLL,X SET LENGTH (LOW) 200D A91E 1350 LDA #SIZEH SCREEN SIZE (HIGH) 200F 9D4903 1360 STA ICBLH,X SET LENGTH (HIGH) 2012 A558 1370 LDA SAVMSC POINTER TO DISPLAY 2014 9D4403 1380 STA ICBAL,X I/O BUFFER (LOW) 2017 A559 1390 LDA SAVMSC+1 DISPLAY PNTR (HI) 2019 9D4503 1400 STA ICBAH,X I/O BUFFER (HIGH) 201C 2056E4 1410 JSR CIOV LOAD MAP DATA 201F BD4303 1420 LDA ICSTA,X GET STATUS BYTE 2022 85D4 1430 STA BASVAL RETURN VALUE 2024 A900 1440 LDA #0 GET A ZERO 2026 85D5 1450 STA BASVAL+1 ZERO HIGH BYTE 2028 60 1460 RTS THAT'S ALL FOLKS! 1470 ; 2029 1480 *= $3000 1490 ; 1500 ; VERTICAL BLANK SCROLL ROUTINE 1510 ; 3000 A900 1520 SCROLL LDA #0 ZERO ACCUMULATOR 3002 85B0 1530 STA OFFLO ZERO OFFSET (LOW) 3004 85B1 1540 STA OFFHI ZERO OFFSET (HIGH) 3006 AD7802 1550 LDA STICK CHECK STICK 3009 2908 1560 AND #$08 RIGHT BIT FOR LEFT? 300B D015 1570 BNE CHKRT NO, TRY RIGHT. 300D A5B2 1580 LDA XPOS LEFT EDGE? 300F F02D 1590 BEQ CHKUP YES, TRY UP. 3011 C6B2 1600 DEC XPOS DECREMENT X-COORD 3013 A5B2 1610 LDA XPOS GET X-COORD 3015 2907 1620 AND #7 AND SCROLL BITS 3017 8D04D4 1630 STA HSCROL FINE SCROLL 301A C907 1640 CMP #7 OVERFLOW? 301C D020 1650 BNE CHKUP NO, TRY UP. 301E E6B0 1660 INC OFFLO OFFSET FOR SCROLL 3020 D01C 1670 BNE CHKUP TRY GOING UP 1680 ; 3022 AD7802 1690 CHKRT LDA STICK CHECK STICK 3025 2904 1700 AND #$04 LEFT BIT FOR RIGHT? 3027 D015 1710 BNE CHKUP NO, TRY UP. 3029 A5B2 1720 LDA XPOS GET X-COORD 302B C9A0 1730 CMP #160 RIGHT EDGE? 302D F00F 1740 BEQ CHKUP YES, TRY UP. 302F E6B2 1750 INC XPOS INCREMENT X-COORD 3031 A5B2 1760 LDA XPOS GET X-COORD 3033 2907 1770 AND #7 OVERFLOW? 3035 8D04D4 1780 STA HSCROL FINE SCROLL 3038 D004 1790 BNE CHKUP NO, TRY UP. 303A C6B0 1800 DEC OFFLO OFFSET FOR SCROLL 303C C6B1 1810 DEC OFFHI OFFSET FOR SCROLL 1820 ; 303E AD7802 1830 CHKUP LDA STICK CHECK STICK 3041 2902 1840 AND #$02 DOWN BIT FOR UP? 3043 D01C 1850 BNE CHKDN NO, TRY DOWN. 3045 A5B3 1860 LDA YPOS GET Y-COORD 3047 C9E4 1870 CMP #228 AT TOP EDGE? 3049 F016 1880 BEQ CHKDN YES, TRY DOWN. 304B E6B3 1890 INC YPOS INCREMENT Y-COORD 304D A5B3 1900 LDA YPOS GET Y-COORD 304F 2901 1910 AND #$01 OVERFLOW CONDITION? 3051 8D05D4 1920 STA VSCROL FINE SCROLL 3054 D00B 1930 BNE CHKDN NO, TRY DOWN. 3056 A5B0 1940 LDA OFFLO GET OFFSET (LOW) 3058 18 1950 CLC CLEAR CARRY BIT 3059 6928 1960 ADC #40 BYTES IN MODE 8 LINE 305B 85B0 1970 STA OFFLO NEW OFFSET (LOW) 305D 9002 1980 BCC CHKDN VALUE > 255? 305F E6B1 1990 INC OFFHI YES, OFFSET (HIGH) 2000 ; 3061 AD7802 2010 CHKDN LDA STICK CHECK STICK 3064 2901 2020 AND #$01 UP BIT FOR DOWN? 3066 D01C 2030 BNE CHGDL NO, CHANGE DISPLAY. 3068 A5B3 2040 LDA YPOS BOTTOM EDGE? 306A F018 2050 BEQ CHGDL YES, CHANGE DISPLAY. 306C C6B3 2060 DEC YPOS DECREMENT Y-COORD 306E A5B3 2070 LDA YPOS GET Y-COORD 3070 2901 2080 AND #$01 AND SCROLL BITS 3072 8D05D4 2090 STA VSCROL FINE SCROLL 3075 C901 2100 CMP #$01 OVERFLOW? 3077 D00B 2110 BNE CHGDL NO, CHANGE DISPLAY. 3079 A5B0 2120 LDA OFFLO GET OFFSET (LOW) 307B 38 2130 SEC SET CARRY FOR SUBTRACT 307C E928 2140 SBC #40 BYTES IN MODE 8 LINE 307E 85B0 2150 STA OFFLO NEW OFFSET (LOW) 3080 B002 2160 BCS CHGDL VALUE > 255? 3082 C6B1 2170 DEC OFFHI YES, OFFSET (HIGH) 2180 ; 3084 A000 2190 CHGDL LDY #0 ZERO Y INDEX 3086 B90406 2200 CGI LDA LIST+4,Y LOAD ADR (LOW) 3089 18 2210 CLC CLEAR CARRY FOR ADD 308A 65B0 2220 ADC OFFLO ADD OFFSET (LOW) 308C 990406 2230 STA LIST+4,Y NEW LOAD ADR (LO) 308F B90506 2240 LDA LIST+5,Y LOAD ADR (HIGH) 3092 65B1 2250 ADC OFFHI ADD OFFSET (HIGH) 3094 990506 2260 STA LIST+5,Y NEW LOAD ADR (HI) 3097 C8 2270 INY POINT TO NEXT BYTE 3098 C8 2280 INY POINT TO NEXT BYTE 3099 C8 2290 INY POINT TO NEXT BYTE 309A C0F0 2300 CPY #240 END OF DISPLAY LIST? 309C D0E8 2310 BNE CGI NO, DO SOME MORE. 309E 4C62E4 2320 JMP XITVBV VERTICAL BLANK EXIT 30A1 2330 .END
A.N.A.L.O.G. ISSUE 6 / MAY 1982 / PAGE 50
A DOS option known as a MEM.SAV file allows your BASIC program and the Disk Operation System to share the same memory space. It is in a sense a form of Time-Sharing as practiced on large computer systems. This new Disk Operating System, DOS II, loads into the computer’s memory in two parts. The first file, DOS. SYS, is loaded and initialized, and control is then transferred to the cartridge if one is inserted; otherwise DOS proceeds to load in part two, file DUP.SYS into memory. DOS. SYS allows your BASIC program to do I/O (Input/Output) to disk files, but if you need to copy a disk or an individual file, write DOS files to a disk, get a directory listing, or do anything that cannot be done from BASIC, then you will have to go into the DOS menu. This is accomplished by typing the word ‘DOS’ followed by a [return].
DOS 1 came up in the menu mode almost instantly after the user typed ‘DOS’ [return] because the menu part of the program was always resident in the computer’s memory. This used up a lot of the computer’s memory space, which meant that you had less room left for your program. Since DOS 1 also had a few bugs in it, like not being able to use random access files or not being able to boot up the ATARI 850 Interface Module, the programmers at ATARI decided to rewrite the software, fixing any bugs and incorporating a few enhancements.
Normally, when one is using DOS II and needs access to the DOS menu options, you type ‘DOS’ [return], do what you have to do, type the ‘B’ [return] (Run Cartridge option), and re-enter BASIC. But something nasty has happened to your program. It’s GONE!!
Now, you are probably wondering, “What the %#$& did this computer do with my program?” It was wiped from memory by the DOS. The Disk Operating System loaded its menu program right on top of your BASIC program. Too bad for you. You should have enabled the MEM.SAV feature. Yes, now even you can stop your programs from being clobbered by DOS. Just think, no one will ever again ask, “What happened to your program?” Just send $29.95 plus $2.00 shipping and handling to “Clobbered for the Last Time,” P.O. Box 123, Ripoff City ...
Actually, it is not going to cost you anything to save your programs, except for an increase in disk access time. It works almost like magic! All you need is a file, 45 sectors long, on your system disk named ‘MEM.SAV’. The computer does the rest. The DOS menu has the option to create such a ‘MEM.SAV’ file for you. Once enabled, the operating system automatically makes use of it.
Now, every time you call up DOS, the system checks for a ‘MEM.SAV’ file. If there is one on the disk, the computer will save a part of your BASIC program (the part that would normally be overwritten by DOS) to the ‘MEM.SAV’ file. The DOS menu program is then loaded and executed. When you want to get back into BASIC, the system first reads the part of your program stored in the ‘MEM.SAV’ file, back to where it first found it. Your BASIC program is now in its original state and can be edited or executed. And this feature is not limited to the BASIC cartridge. You can use it with the Assembler/Editor, the Music Composer or the Pilot cartridge.
There are certain types of utility software that can get an assembly language programmer really excited. It’s akin to buying a new car, and discovering what all the little buttons do. This is how I feel about two new machine language programs, the ATARI Macro Assembler and Program-Text Editor™. These two programs brought back all the fun of Christmas, and they are not even games!
Programs of this nature do what they were designed to do, but they are still loaded with extra ‘Bells and Whistles’. These are not really needed but are certainly welcome, and are a sight for these sore eyes. The preliminary documentation that 1 received for the Macro Assembler ran just over sixty pages. When you consider that this documentation was on the skimpy side, you have an idea as to the size of the final manual. The same holds true for the text editor manual.
Programmers whose source files tended to become very lengthy (yeah, like six thousand lines is a lot, eh!), ran into problems with the ATARI Assembler Editor cartridge. In order to edit a file with this cartridge, the entire file must be able to reside in the computer’s memory. Even with all the comments removed, two thousand lines of code tend to fill the memory. Progress past this point can be made with the enhanced Assembler/Editor package by ‘Optimized Systems Software, Inc.’, in that you can now use many small files and have the Assembler sequentially access them during the assembly process. This surely works, but turns out to be a pain to edit.
Having the graphics routines on ‘D:FILE1’, the variable assignments on ‘D:FILE2’, system equates on ‘D:FILE3’, etc. sometimes becomes confusing. After a while, it is hard to keep ‘What goes where?’ straight in your mind. And let’s not forget those so called ‘necessary’ line numbers! In a six thousand line program, these numbers can use up at least 24K of disk space! What a waste.
ATARI’s new “Program-Text Editor” gets around the above mentioned problems. Line numbers are optional. BASIC seems to be the only language that really needs line numbers. This conserves both disk and memory space. Another place to conserve is in the implementation of the TAB key. Every program that I have seen that uses the TAB key has merely added extra spaces into the program. The Assembler cartridge does not need all these extra spaces, but programmers tend to include them to make the source code more readable. It was up to you whether to waste memory space, or get eye strain! The new ‘Program-Text Editor’ package can insert an actual TAB instruction in the code that when listed will tell the Editor to expand to the next defined tab column, thus saving even more memory space. Plus, as an added feature, your programs can now exceed the memory limits of your machine. You will now be able to edit a 200K-300K program, letting the editor swap the text into and out of the computer’s memory. The program will also automatically update the files and maintain a backup copy of your last editing session.
Next time, I will discuss ATARI’s ‘Program-Text Editor’ in greater depth along with talking about some of the many features of ATARI’s new ‘Macro Assembler’.
A.N.A.L.O.G. ISSUE 7 / SEPTEMBER 1982 / PAGE 60
I keep doing it, don’t I? For a number of times now, I have mentioned at the end of these tutorials the many interesting things that will be talked about in my next tutorial. And in all those times, I have traveled far away from the stated subject matter. Well, I promise not to do this ever again! From now on, there will be no more announcements (ha, fooled ya!). The reason for this being that by the time I’m ready to write all this stuff, something new has caught my attention. You are forced to take what you can get. And now, back to our story.
As more and more computer owners are finding the financial burden of owning their own printer more bearable (mainly due to the rapidly dropping prices, especially of those printers imported from Japan), they are asking for different ways to put their new-found toys to use. Many of the newer printers coming onto the market are microprocessor controlled, which allows them the ability to change not only character size and type style, but also the page length, line spacing, margin settings, underlining, and a host of other “neat” features. (“Yes, I use the Japanese character font every day. Doesn’t everyone?”)
“…but the feature that will concern us today is that of graphics, that unique and somewhat obscure ability to draw a picture on a screen and put it onto paper. For some, this is as easy as taking candy from a baby. For others, it is an impossibility, to be realized only in one’s mind. Join us now as we meet a man, a computer, and a not so ordinary printer, all of which are about to connect, in the “Twilight Zone”.”
This article contains a graphics program called “Archimedes Spiral”. The program, although quite short, takes nearly three hours to run! This is definitely not a quick demo. (To produce the transparent version of the spiral, delete line 240.) (it still looks like a hat to me. Ed.)
100 REM ARCHIMEDES SPIRAL 110 REM 129 REM ANALOG MAGAZINE 130 REM 140 GRAPHICS 8+16:SETCOLOR 2,0,0 150 XP=144:XR=4.71238905:XF=XR/XP 160 FOR ZI=-64 TO 64 170 ZT=ZI*2.25:ZS=ZT*ZT 180 XL=INT(SQR(20736-ZS)+0.5) 190 FOR XI=0-XL TO XL 200 XT=SQR(XI*XI+ZS)*XF 210 YY=(SIN(XT)+SIN(XT*3)*0.4)*56 220 X1=XI+ZI+160:Y1=90-YY+ZI 230 TRAP 250:COLOR 1:PLOT X1,Y1 240 COLOR 0:PLOT X1,Y1+1:DRAWTO X1,191 250 NEXT XI:NEXT ZI 260 GOTO 260
It would be so much simpler if you could hand out a hardcopy of the graphics to demonstrate your prowess with the computer. Your friends will be doing cartwheels and going hazoo-huzzah over your printing expertise. (Hazoo-huzzah?! Ed.) The most popular printers on the market today are the ones put out by Epson and C. Itoh. This being the case, we will write the hardcopy programs with these printers in mind.
There are basically two ways to output graphic information to a printer. Since each of the eight hammers of the print head are individually addressable, the most efficient method is to output a column of eight pixels to the printer at a time. While this is the fastest way to do graphics, the code tends to be somewhat lengthy, and a somewhat obscure problem can crop up. This problem relates to the fact that a byte of the value 155 ($9B Hex) which is the ATARI’s internal representation of a (RETURN), converts it to the decimal value 13 ($0D Hex), what the outside world understands as producing a carriage return signal. If the information for the eight pixels that you are working on adds up to 155, it will not look right in the final print out. This conversion is done in the 850 Interface module and I know of no way around it at this time.
The second method is to use only one hammer of the print head. It will take eight times longer to produce a hardcopy of a picture, since you will only be working with one scan line at a time, but the code will be shorter and simpler. A routine to produce a printed copy of the Archimedes spiral follows.
260 REM EPSON GRAPHICS 8 DUMPER 270 REM ONE LINE AT A TIME! 280 OPEN #1,8,0,"P:" 290 PUT #1,27:PUT #1,65:PUT #1,1 300 REM ABOVE SETS PIXEL SPACING TO 1 310 FOR Y=0 TO 191 320 PUT #1,27:PUT #1,75 330 PUT #1,64:PUT #1,1 340 REM ABOVE 4 BYTE GRAPHIC HEADER 350 FOR X=0 TO 319:LOCATE X,V,A 360 PUT #1,A:REM OUTPUT PIXEL 370 NEXT X:PRZNT #1:NEXT Y 380 END
Line 290 sets the printer’s line feed space of 1/72 of an inch. This the height of an individual print hammer. Lines 320 and 330 put the printer into graphics mode for one scan line. Line 330 specifies the number of bytes of graphic information to output to the printer. Since mode 8 graphics is 320 pixels across, we send this number to the printer in low byte, high byte format (64, 1). Line 350 sees if the pixel is a zero or a one, and line 360 sends it to be printed.
The next program listing is the same program written for the C.Itoh model 8510 printer. The main differences between this printer and the Epson is the method chosen to pass numeric values. A good example of this is how a 8510 is told that the next 320 bytes are to contain graphics. While the Epson people chose to specify number parameters as binary words (low byte, high byte) which is ideally suited to Assembly language programming, the manufacturer of the C.Itoh 8510 took an alternate route by passing numbers as character strings, something that BASIC can easily manipulate. Now the header of a 320 pixel line becomes: CHR$(27);"S0320".
260 REH C.ITOH GRAPHICS 8 DUMPER 270 REM 280 OPEN #1,8,0,"P:" 290 PRINT #1;CHR$(27);"T02" 300 REM ABOVE SETS PRINTER TO 1 PIXEL 310 FOR Y=0 TO 191 320 PRINT #1;CHRS(27);"S8320"; 340 REM ABOVE OUTPUTS GRAPHICS HEADER 350 FOR X=0 TO 319:LOCATE X,Y,A 360 PUT #1,A;REM OUTPUT PIXEL 370 NEXT X:PRINT #1:NEXT Y 380 END
One thing to keep in mind if you are presently without a graphics printer but know someone who has one, is that all the information being sent to the printer does not have to go directly to it. The pixel data can be stored initially on a disk file, and later transferred to the printer, when one becomes available, using the copy file command in DOS. The only negative effect in using the above programs with disk files is that the information will use up about 500 sectors of disk space. The next two programs will correct this problem by outputting six pixels per byte. The six pixel combination was decided upon as the largest number that divided evenly into 192 (the number of scan lines) and could not possibly equal 155 (the carriage return conversion problem mentioned earlier.)
260 REM EPSON GRAPHICS 8 DUMPER 270 REM SIX LINES AT A TIME! 280 OPEN #1,8,6,"P:":REM TRY DISK? 290 PUT #1,27:PUT #1,65:PUT #1,6 300 REM ABOVE SETS PIXEL SPACING TO 6 310 FOR Y=0 TO 191 STEP 6 328 PUT #1,27:PUT #1,75 330 PUT #1,64:PUT #1,1 340 REM ABOVE 4 BYTE GRAPHIC HEADER 350 FOR H=0 TO 319:A=0 352 FOR Y1=Y TO Y+5: LOCATE X,Y1,Z 354 A=A+A+Z:NEXT Y1 360 PUT #1,A:REM OUTPUT SIX PIXELS 379 NEXT X:PRINT #1:NEXT Y 380 END
260 REM C-ITOH GRAPHICS 8 BUMPER 270 REM SIX LINES AT A TIME! 280 OPEN #1,8,0,"P:":REM TRY DISK? 290 PRINT #1;CHR$(27);"T12" 300 REM ABOVE SETS PIXEL SPACING TO 6 310 FOR Y=0 TO 191 STEP 6 320 PRINT #1;CHR$(27);"S8320"; 340 REM ABOVE OUTPUTS GRAPHICS HEADER 350 FOR X=0 TO 313;A:=0 352 FOR Y1=Y+5 TO Y STEP -1 354 LOCATE X,Y1,Z;A=A+A+Z;NEXT Y1 360 PUT #1.A:REM OUTPUT PIXEL 370 NEXT X:PRINT #1:NEXT Y 380 END
These two programs will produce disk files that are now only 84 sectors long. A big improvement, don’t you think? Anyway, this will allow you to put eight of these files on each and every disk you own. After all, “Eight Is Enough”, don’t you know?
(Ed. Note: No one here at A.N.A.L.O.G is responsible for Charlie’s state of mind when he writes these non-tutorials, just thought you people would like to know.)