Copy Link
Add to Bookmark
Report

Machine Language - PART VII

by Lyle Giese (LYLEG on DELPHI)


It looks like this month we will finish up the Sequential File Reader. So what will I do next month? Let me know what YOU want written about. I really want to write about something that will interest you, and the best way to do that is to tell me! My DELPHI username is LYLEG, and if you are on Genie tell deb! and she will forward the comments to me.

When we left off last month we just opened the file to be read and now are ready to decide if we want to send it to the printer or the screen. Of course, we first print a message to the screen asking Screen or Printer?

In line 1280, we get a character from the keyboard (if there is one, remember this routine will a CHR$(0) if there are no keys pressed). We check for an "s" for the screen. If we found one we JSR to the screen setup routine. If not we check for a "p".

Let's look at the 'OSCR' subroutine starting at line 6500. Why are we opening a logical file for the screen? Doesn't the Programmers Reference Guide say it is not needed? Yes, that is true. But our output routine will need to be able to send to the screen or the printer. The printer needs the logical file to be there. So it can be easier to send the output to a logical file rather that decide for each character how to send it, depending on the output device selected.

Of course, we could have written two output routines. Then every time we sent a character, we would have to check and see which output device was selected and branch to the proper routine.

Ok, now if we want to send our file to our printer we will go to line 6000 for the PRINTER subroutine. There we ask what device number we are going to use. Here (in lines 6060-6090) we limit the device number to 4 through 7. After we get the device number we convert it from PETSCII to the number we must use for the SETLFS routine.

Next we can select the secondary address within the limits zero to nine. I limited myself to this range to make the routines here simple. Again, we have to convert from PETSCII to the number to be used for the SETLFS routine.

Now we can open the logical file. For a printer channel, we don't need a file name and set the length of the filename to zero and finally JSR OPEN. Why don't we check the printer file the same way we did the disk file?

Well, first of all, nothing has been sent to the printer yet. Until we open the output channel (JSR CHKOUT) the secondary address and the listen commands are not sent. At that time is when we find out if the printer is not there, when the program hangs up (depending on the printer and interface).

Finally we are getting to the heart of the whole thing! Read a character and send it to our output device. First (in line 1400-1410) we open an input channel to the disk drive. And then we try to get our first character from the disk drive.

Some of CBM's DOS routines (depending on the type of drive) will send several null bytes before sending the first byte of the file, and here we trap them. Next we must store that character as we must read the status byte and store it also.

Now here is where I made the routine "generic", by loading up the byte representing the outfile and opening an output channel to it. At this point we could care less if the output device was the screen, printer or even a disk drive (of course we would have to write a different subroutine for opening an output file on the disk drive.)

In line 1490, we are checking for a successful opening of the output channel. If the channel is not opening, I do a CLRCHN (restore default I/O) and try again. Why? I had quite a bit of trouble with this routine locking up when sending a file to my printer until I put lines 1490-1530 in.

It seems that my printer interface could not keep up with the rapid opening and closing of channels on the serial bus. It would miss the JSR CHKOUT in line 1480 once in a while. Then in line 1550, CHROUT assumes the channel is properly opened and will crash your program.

This one place where the PRG misses an important point. If you look at the description of CHROUT on page 278-279 (of the PRG for the C-64), they miss that little detail. And of course I put in a way to break out of this loop in case the printer really wasn't there (lines 1510-1530).

Now is the time to check the status byte we stored in line 1460. At this point we are only interested in the end of file bit and use the AND instruction to look at only that bit. If it is not set we will continue on as we have not reached the end of the file yet.

I decided that it would be nice to be able to pause the output in order to take time to read the contents of the screen before it scrolls out of sight. Or a way to abort out if we found out this file was not the one we really wanted to look at or if we wanted to just see what the file contained.

I used the SHFLAG byte at $028D to see if the Shift key is pressed. This byte is updated by the systems normal IRQ routines. If the shift key only is down this byte holds a value of 1. If the CTRL key is down, a 4 is placed there. And if the logo key is down a 2 is found here. If 2 or more of these keys are depressed the sum of the key values is found there at $028D.

As long as the shift key is down (or shift lock), the program will go into a loop rechecking the SHFLAG byte. If the Shift and Control keys are down (for a value of 6), then abort out just as if we hit the end of the file.

In line 1650 we jump back to and get another byte for outputting.

Now when we finish we have to start closing channels and logical files in line 1680. We have to close the read file before the disk command channel. In this program, it is not as important. But if we were writing to a disk file and closed the command file, that would close ALL open files in the drive, even if we didn't want them closed yet.

Next we go after the printer (or screen). On some printers, incoming characters are buffered until the buffer is full or a carriage return is received. So here we send a carriage return to make sure the buffer is emptied before we close up.

Now a message is printed to tell us to press the return key before the program is allowed to start over, which clears the screen. There (if you remember) hitting the return with no character in our filename buffer will exit this program.

And that concludes our file reader finally! Next month??? You tell me.
PLEASE!

Lyle Giese
AKA LYLEG

[ED. NOTE: This is LYLEG'S final article in his multi-part series on a Sequential File Reader. Included in this issue of the *StarBoard* Journal is the full PAL source code and the object code. Load Object Code,8,1 and then SYS49152 to use. If you haven't been following along for the last few months, be sure to go back and retrieve his earlier articles. They are excellent!

mlcol7-s

FILE00013 ==0801== 
50 sys700
75 .opt p,oo
80 ;****************
81 ;* *
82 ;* lyle giese *
83 ;* version 1.0 *
84 ;* 06/21/86 *
85 ;* *
86 ;****************
120 readst = $ffb7
130 setlfs = $ffba
140 setnam = $ffbd
150 open = $ffc0
160 close = $ffc3
170 chkin = $ffc6
180 chkout = $ffc9
190 clrchn = $ffcc
200 chrin = $ffcf
210 chrout = $ffd2
220 getin = $ffe4
230 clall = $ffe7
300 index = $fb
310 fnam = $033c;using cassette buffer to store filenames
320 flen = $fd;for length of filename
330 outfile = $fe
340 rtemp = $03ff
350 atemp = $03fe
360 pdev = $03fd
370 shflag = $028d
380 high = $03fc
390 low = $03fb
490 *= $c000
500 ;set up screen
510 start lda #$00;make border and background black
520 sta $d020
530 sta $d021
540 lda #$07;make the characters yellow
550 sta $0286
555 ;send first message to screen
560 lda #<amess
570 sta index
580 lda #>amess
590 sta index+1
600 jsr messout;send message to screen
610 ;get filename for disk read
620 lda #<fnam;load index with location for filename
630 sta index
640 lda #>fnam
650 sta index+1
660 lda #$00
670 sta flen
680 jsr clrchn;make sure screen and keyboard is active
690 nokey jsr getin;get a char from the keybuf
700 beq nokey;if nothing is in keybuf a reg will hold a zero
710 cmp #$14;ck for delete key
720 bne ckrt
730 lda flen;before deleting make sure that there
740 beq nokey;is a char in fnam
750 lda #$14;delete char on screen
760 jsr chrout
770 dec flen
780 jmp nokey
790 ckrt cmp #$0d;ck for return to either exit program
800 bne valkey;or open disk file
810 lda flen;ck number of char in keybuf
820 bne dopen;if any chars then open disk file
830 rts;if return pressed with no char in keybuf then exit routine
840 valkey ldy flen;load y reg with flen
850 cpy #$12;ck for max char allowable
860 beq nokey
870 sta (index),y;store in fnam buffer
880 jsr chrout;and echo char to screen
890 inc flen;inc flen pointer
900 jmp nokey
910 dopen ldy flen;add ,s to fnam
920 lda #","
930 sta (index),y
940 iny
950 lda #"s"
960 sta (index),y
970 iny
980 sty flen
1000 ;open channels to disk drive
1010 lda #$00;first command channel
1020 jsr setnam;no file name needed here
1030 lda #$0f;open15,8,15
1040 ldx #$08
1050 ldy #$0f
1060 jsr setlfs;open logical file
1070 jsr open;command channel opened
1080 bcc ropen;ck if open was ok
1090 jmp derror;could not open channel
1100 ropen lda flen;get length of filename
1110 ldx #<fnam
1120 ldy #>fnam
1130 jsr setnam
1140 lda #$08
1150 ldx #$08
1160 ldy #$00
1170 jsr setlfs
1180 jsr open;open8,8,8,"fnam,s"
1190 bcc ckerror
1200 jmp derror;could not open read file
1210 ckerror jsr rerror;ck error chan on disk drive
1215 ;select output
1220 lda #<bmess;print message 'screen or printer'
1230 sta index
1240 lda #>bmess
1250 sta index+1
1260 jsr messout
1270 jsr clrchn;make sure screen and keyboard active
1280 nsorp jsr getin
1290 cmp #"s"
1300 bne p
1310 jsr oscr;set up screen for output
1320 jmp read
1330 p cmp #"p"
1340 bne nsorp;must be s or p
1350 jsr printer;do printer setup
1360 read =*
1400 ldx #$08;open input channel from disk
1410 jsr chkin
1420 zero jsr chrin
1430 beq zero;if zero byte throw it away.
1440 sta atemp
1450 jsr readst;read the i/o byte
1460 sta rtemp;keep it for later
1470 bsend ldx outfile;open output channell
1480 jsr chkout
1490 beq send;ck if chkout worked
1500 jsr clrchn;chkout failed
1510 jsr getin;break out of this loop by pressing any key
1520 beq bsend;no key pressed try to open output chan again
1530 jmp done;exit out of this loop
1540 send lda atemp;reload acc for send
1550 jsr chrout;send the byte
1560 jsr clrchn;restore default channels
1570 lda rtemp;ck for end of file
1580 and #$40;ck for 64 decimal
1590 bne done;if eof then close all files
1600 pause lda shflag;ck for shift and/or crtl key
1610 cmp #$01;$01=shift only down
1620 beq pause
1630 cmp #$05;$05=shift and ctrl key down
1640 beq done;exit if shift/crtl pressed
1650 jmp read
1680 done lda #$08;start closing channels
1690 jsr close;disk read first
1700 lda #$0f
1710 jsr close;disk command channel next
1720 ldx outfile;send cr to output device
1730 jsr chkout;if using printer then that
1740 lda #$0d;will clear all buffers making
1750 jsr chrout;sure all characters are
1760 jsr clrchn;are printed
1770 sta index+1
1780 jsr messout
1790 lda outfile
1800 jsr close;and output for printer or screen
1810 lda #<emess
1820 sta index
1830 lda #>emess
1840 sta index+1
1850 jsr messout
1860 nocr jsr getin
1870 cmp #$0d;is it a cr
1880 bne nocr
1890 jmp start;go back to the beginning
3000 derror jsr clrchn;make sure i/o initialized
3010 jsr clall;make sure all open channels are closed
3020 lda #<cmess;unable to open error chan
3030 sta index
3040 lda #>cmess
3050 sta index
3060 jsr messout
3070 rts;this error is fatal and we don't want to try again
4000 rerror ldx #$0f;read and ck disk error chan
4010 jsr chkin
4020 null jsr getin
4030 beq null
4040 sta high
4050 jsr getin
4060 sta low
4070 cmp #$30;if first two chars are
4080 bne ck;ascii zero and zero
4090 lda high;then no error occured
4100 cmp #$30;
4110 beq empty;remove the entire error message
4120 ck lda #$0d;if not then print error
4130 jsr chrout;error message
4140 lda high
4150 jsr chrout
4160 lda low
4170 repeat jsr chrout
4180 jsr getin
4190 cmp #$0d
4200 bne repeat
4210 pla:pla;remove return address from stack
4220 jsr clrchn
4230 lda #$08:jsr close
4240 lda #$0f:jsr close;close disk chan
4250 lda #<emess
4260 sta index
4270 lda #>emess
4280 sta index+1
4290 jsr messout
4300 ncr jsr getin
4310 cmp #$0d
4320 bne ncr
4330 jmp start
4340 empty jsr getin;no disk error but
4350 cmp #$0d;should still read the entire
4360 bne empty;message out of error chan
4370 jsr clrchn
4380 rts
5000 messout ldy #$00;send message to screen
5010 lpy lda (index),y;index points to start of message
5020 beq end;and it must end with a zero byte
5030 jsr chrout
5040 iny
5050 bne lpy;has y looped around to zero
5060 inc index+1;if it has we must inc
5070 jmp lpy;the hi byte of our index address
5080 end rts
6000 printer lda #<pmess;printer selection
6010 sta index
6020 lda #>pmess
6030 sta index+1
6040 jsr messout
6050 lpp jsr getin
6060 cmp #"4";compare to ascii 4
6070 bcc lpp;less than 4
6080 cmp #"8";
6090 bcs lpp;greater than 7
6100 sta atemp
6110 jsr chrout;echo to screen
6120 lda atemp
6130 sec:sbc #$30;convert from petscii
6140 sta pdev
6150 lda #<secmess;ask for secondary address
6160 sta index
6170 lda #>secmess
6180 sta index+1
6190 jsr messout
6200 lps jsr getin
6210 cmp #"0";zero to nine only for this program
6220 bcc lps
6230 cmp #$3a
6240 bcs lps
6250 sta atemp
6260 jsr chrout;echo to screen
6270 lda atemp
6280 sec:sbc #$30;convert from petscii
6290 tay
6300 lda #$04
6310 sta outfile
6320 ldx pdev
6330 jsr setlfs;open logical file #4 for printer
6340 lda #$00
6350 jsr setnam;no filename for printer
6360 jsr open;openoutdev,pdev,secadd
6370 rts
6500 oscr lda #$03;open file to screen
6510 sta outfile
6520 ldx #$03
6530 ldy #$00
6540 jsr setlfs
6550 lda #$00
6560 jsr setnam
6570 jsr open
6590 rts
7000 amess =*;opening message
7010 .byte $93;clear/home
7020 .byte $0d,$0d,$0d,$0e
7030 .asc " SEQUENTIAL FILE READER"
7040 .byte $0d,$0d
7050 .asc " By Lyle Giese"
7060 .byte $0d,$0d
7070 .asc " Use the Shift and Shift Lock to pause
7080 .byte $0d
7090 .asc " listing. Press the Ctrl and Shift to"
7100 .byte $0d
7110 .asc " exit current file. To exit just"
7120 .byte $0d
7130 .asc " hit (rvon)return(rvof) at the Filename > prompt."
7140 .byte $0d,$0d
7150 .asc " Filename > "
7160 .byte $00
7200 bmess =*;screen or printer message
7210 .byte $0d
7220 .asc " (rvon)S(rvof)creen or (rvon)P(rvof)rinter? "
7230 .byte $00
7300 cmess =*;unable to open error channel to disk drive
7310 .byte $0d
7320 .asc " Unable to open error channel to disk
7330 .byte $0d
7340 .asc " drive. Try again later!"
7350 .byte $0d,$00
7400 dmess =*;disk error trying to open read channel
7410 .byte $0d
7420 .asc " (rvon) DISK ERROR (rvof)"
7430 .byte $0d,$00
7500 emess =*;end of file
7510 .byte $0d
7520 .asc " (rvon) Press return to continue (rvof) "
7530 .byte $0d,$00
7600 pmess =*;printer device number
7610 .byte $0d
7620 .asc " Device Number(4-7)? "
7630 .byte $00
7700 secmess =*;secondary address
7710 .byte $0d
7720 .asc " Secondary Address(0-9)? "
7730 .byte $00

← previous
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT