********************************************************************* This article is being presented through the *StarBoard* Journal of the FlagShip/StarShip, SIGS (Special Interest Groups) on the Delphi and GEnie telecommunications networks. Permission is hereby granted to non-profit organizations only to reprint this article or pass it along electronically as long as proper credit is given to both the author and the *StarBoard* Journal. ********************************************************************* Machine Language Part VI by Lyle Giese (LYLEG on DELPHI) Last month I started explaining my SEQ file reader for you. I got up to putting the opening message on the screen. Next we must get from you (the user) the filename of the file you want printed out. We have to start by deciding where we are going to store the filename. In BASIC, BASIC takes care of that automatically. But of course that convenience is offset by the slow speed of BASIC. In this program I decided to use the cassette buffer at $033C. Again I will use the index and index+1 memory locations to point to the filename. I will also need another variable for the length of the filename. For that I used $FD and initialized it by putting a Zero byte in it. I issued a call to the KERNAL CLRCHN routine next, just to make sure I was getting my input from the keyboard. Next call the GETIN routine to get the keypresses. If no keys are pressed it will return with a zero in the Accumlator, which the instruction in line 700 checks for. Next we need to check for the delete key (we don't make typing mistakes do we?). If we haven't put any characters in the filename, it would be hard to delete one. So in line 730 & 740 we check to make sure we have characters there. Then delete the last character printed on the screen and DECrement the FLEN variable in line 770. Next we have to check for a carriage return. The carriage return is used for two things. It will mark the end of the filename after we have typed it in. Also, we use it to exit the routine. By checking FLEN after getting a carriage return (in lines 810 & 820), if there are no characters yet, we exit by the RTS instruction in 830. Or Branch if Not Equal to the DOPEN routine. Then if we get to line 840, we have a character we want to add to the filename. We need to first check the length of the filename before we add it to the filename. If the filename is too long we really don't want the extra characters. At this point, we branch back (line 860) to make you press the return button before trying to find the file. But 18 characters? Filenames can be only 16 characters long! That's right, but add the prefix '0:' or '1:' for those of us that have dual drives and the max length now becomes 18. I did not check for valid characters by limiting input to numbers and/or letters only. I only checked for the delete key and the return key. So that is something to watch out for or a feature for you to add. Now echo the character to the screen for the you to see and jump back for more characters to NOKEY, which is at line 690. After we have finished typing the filename, we need to go to the disk drive and open a read channel from which to get the characters. But since we are making a SEQ file reader, I added ',S,R' to the end of the filename and adjusted FLEN accordingly. Now, open the command channel to the disk drive so we can see any disk errors that might occur. That takes us down to line 1090. That checks for errors opening the error channel. Now we can open our read channel. We start by setting the filename for the system with the SETNAM routine. Next the SETLFS and the OPEN routine. Now we just performed the equivelent of OPEN8,8,8,"FNAM,S,R". Again go back to your Programmers Reference Guide if you have problems using the KERNAL routines. Knowing how to read that portion of the PRG is esstenial to programming in ML on a Commodore computer. Note in opening the disk channel, I didn't have to remember many numbers? By using the names (which are defined at the beginning of the program), I didn't have to remember where I put the filename or where I put the file length number either. Sure makes it easy to write a program that way. Also, what if I made a mistake in placing my filename buffer? If you didn't use a name for it, you would have to go through the program very closely changing every reference to it. But here I only have to change it in one location, in the beginning. It would be very easy to miss one spot in the program making debugging even harder! Now that we have done that we must check to make sure that the file was there and the disk drive properly openned a channel for us. We do that two ways. The first one actually checks to make sure the computer was able to properly open the file to the drive. We do that in line 1190. Next we will read the disk's error channel via a call to the subroutine CKERROR (line 1210). That takes us to line 4000. We open an input channel to file #$0F and read the error channel. If the first two characters out are $30 and $30, that means an error of 00 occured, which of course means no error. Then we would just take all of the characters out of the error channel to tidy things up and ReTurn from Subroutine. If anything else is returned in the first two characters, something went wrong. Then we want to read and print out the error message on the screen. That's why we store the first two characters. While printing the error message, we check for the end of the message by checking for a carriage return. Now that we found an error, we can't return to where we were in the program, because that would lead us down into the file read and print routines. We want to go back to the beginning of the program. So in line 4140, we start by printing the disk error message on the screen to the user. Now we have think about how ML handles a subroutine. When the JSR instruction is called, the return address has to go somewhere so that we can find our place when the RTS instruction is issued. That place is the stack. The 6510 pushes the return address as two bytes onto the stack. Since I haven't used the stack for any other storage, it should be the last two entries on the stack. So we pull two bytes off of the stack and throw them away. Now this is an advanced technique, but it is important to understand it. In this case it can be quite handy. But if I had used the stack for other storage I could not have done this that easily. At line 4220, we start closing things up by first restoring default I/O by calling CLRCHN. And then we close the read channel and then the error channel. Now I decided to print a short message to indicate I wanted the user to press the return key and wait for him to press the return key. Why? It is to give you a chance to read the error message before clearing the screen when we go back to the beginning of the program. So at this point we would restart the program. But I have rambled on enough for one month. Next month we will look at how I handled the screen or printer option and some of the problems encountered doing that. [ED. NOTE: The partial source code to accompany this article is the next file in this month's edition of the *StarBoard* Journal.]