In This Issue...
Yes, ProDOS is Now Being Shipped
We bought an Apple //e last weekend, and it came with system disks for both DOS 3.3 and ProDOS. There was no DOS Reference Manual, although a little of DOS is mentioned in the Owner's manual. There is a very nice ProDOS User's Manual, 150 pages of text and photos and drawings. The dealer says he still has no word on ProDOS as a separate product.
I Can't Believe He Typed The Whole Thing!
One of our readers took a few evenings and typed in the source code of the whole CX ROM from the Apple //e Reference Manual Addendum. This is the code from $C100 through $CFFC, which is listed on pages 23-49. He added some of his own comments to the source, which more fully explain what is going on in there. The source for the F8 ROM is on the disk too, but without many comments (pages 3-18 of the addendum). Naturally, the source files are in the format of the S-C Macro Assembler.
We think having the source of these ROMs on disk could enhance the //e in two ways: you can make a larger size copy of the listings, so they can be read in normal room light; and you can experiment with improvements to the code. If you have a PROM burner that will burn 2764s, I think you can even replace the chips. If you'd like a copy, send us $15: we'll mail the disk to you, and pass along a percentage to the energetic typist.
International Personal Robotics Conference
If you are among the many experimenting with little personal robots, such as Heathkit's HERO, you may be interested in attending the above named conference in Albuquerque next April 13-15. They are expecting around 4000 to show up from all over the world. You can meet such well known robotics experts as Joseph Engleberger, Nels Winless and others. It's a fair bet you'll find Jack Lewis of Micromation there. For more info, call Betty Bevers of IRPC at (303) 278-0662, or write to them at 1547 South Owens St. #46, Lakewood, Colorado 80226.
Clarification about Our Copyrights
We frequently are asked if it is all right to use ideas and even programs published in the Apple Assembly Line in articles or books our readers write for publication elsewhere, or even in software they plan to sell.
Sure! Just give us credit. Say where you got it, and hopefully tell your customers how they too can subscribe. The more you sell, the more we sell. The more we spread the good information around, the more we all benefit.
Do you like treasure hunts? Dis-assembling, analyzing, understanding, and modifying programs written in assembly language, with nothing to go by but the program in memory and maybe a user's manual ... to me it is a treasure hunt.
Last week I desperately need to make full use of a Novation Cat II Modem. "Full use" of almost any peripheral device implies the use of assembly language. Even though Novation includes a very nice manual for the purpose, it did not answer half my questions.
Novation also includes a disk with a program called Com-Ware II. This program is assembly language, and takes 74 sectors on the disk. Somewhere, hidden in a small, dark corner, guarded by gnomes, surrounded by wild beasts, lay the answers to all my questions.
I started by BLOADing the file. Then "CALL -151" to get into the monitor, and typed "AA60.AA73". The first two bytes diplayed the length of the file, and the last two bytes are the starting address. I learned it loaded at $900, and was $4825 bytes long.
I started using the monitor L command to scan through the program, and discovered that the programmer had placed all the screen messages "in line". That is, rather than putting all the screen text at the end of the whole program, or in the middle, or wherever, he coded the ASCII strings right in place. Each message was preceded by "JSR $3866", and ended with a $00 byte. The subroutine at $3866 retrieved the return address from the stack, used it to address the message text while printing it out, and then placed a new return address on the stack to continue execution right after the $00 byte.
This makes it difficult to use a program like Rak-Ware's wonderful DISASM, because you have to tell the boundaries of all non-executable code. And there seemed to be LOTS of messages.
On the other hand, it also makes it easier to follow the flow of the program. The buried messages are almost like living comments, telling me exactly what is going on in every section of code.
I decided to get my Apple to help. I wrote a "quick and dirty" program to scan through the whole image from $900 through $5125, looking for every occurrence of "JSR $3866". I printed out the address of the next byte, which is the first byte of message text. Then I searched for the terminating $00 byte, and printed out its address. Then I went back and printed out the message text.
After several tries, I even made my quick and dirty program nice and clean. I printed all the messages out, nicely formated for easy visual scanning. I set my printer on 8 lines/inch and 12 chars/inch to save paper, and let 'er rip. Six whole pages! I think a third of Com-Ware is taken up by messages!
Here is a sample of the printout. Notice that I printed control characters, including <RETURN>, as "^" followed by the printing form of the character. Thus "^M" means <RETURN>.
1481...14CC ^M^M<0> SET HIGH BIT^M<1> CLEAR HIGH BIT^M<2> LEAVE HIG H BIT ALONE^MCHOICE(0-2): 14EF...152E ^M^M<0> SEND LF AFTER CR^M<1. DO NOT SEND LF AFTER CR^M CHOICE(0-1):
I believe a lot of programs of interest use a similar technique for message printing, and slight adaptation of my MESSAGE SEARCH program could help YOU find some buried treasure!
1000 *SAVE S.MESSAGE SEARCH 1010 *-------------------------------- 1020 * FIND ALL MESSAGES IN COM-WARE II VERSION 5.0-3 1030 * 1040 * ALL MESSAGES ARE PRECEDED BY "JSR $3866" 1050 * AND END WITH A $00 BYTE: 1060 * 1070 * 20 66 38 <MSG> 00 1080 *-------------------------------- 1090 MSG.PNTR .EQ $00,01 1100 END.PNTR .EQ $02,03 1110 *-------------------------------- 1120 PRINTAX .EQ $F941 1130 COUT .EQ $FDED 1140 CROUT .EQ $FD8E 1150 *-------------------------------- 1160 KEYBOARD .EQ $C000 1170 STROBE .EQ $C010 1180 *-------------------------------- 1190 FIND LDA #$900 COMWARE WAS BLOADED AT $900 1200 STA MSG.PNTR 1210 LDA /$900 1220 STA MSG.PNTR+1 1230 .1 LDA MSG.PNTR 1240 CMP #$5125 COMWARE ENDS AT $5125 1250 LDA MSG.PNTR+1 1260 SBC /$5125 1270 BCC .2 ...NOT AT END YET 1280 RTS ...FINISHED 1290 *---SEARCH FOR A $20 BYTE-------- 1300 .2 LDY #0 1310 LDA (MSG.PNTR),Y 1320 CMP #$20 1330 BEQ .4 FOUND $20 1340 .3 JSR INC 1350 BNE .1 ...ALWAYS 1360 *---CHECK FOR $66, $38 AFTER $20--- 1370 .4 INY 1380 LDA (MSG.PNTR),Y 1390 CMP #$66 1400 BNE .3 1410 INY 1420 LDA (MSG.PNTR),Y 1430 CMP #$38 1440 BNE .3 1450 *---FOUND A MESSAGE!------------- 1460 LDX #10 1470 JSR MARGIN 1480 JSR PAUSE 1490 JSR INC SKIP OVER THE $20, $66, $38 1500 JSR INC 1510 JSR INC 1520 LDA MSG.PNTR+1 PRINT STARTING ADDRESS 1530 STA END.PNTR+1 1540 LDX MSG.PNTR 1550 STX END.PNTR 1560 JSR PRINTAX 1570 *---SEARCH FOR END OF STRING----- 1580 LDY #0 1590 .5 LDA (END.PNTR),Y 1600 BEQ .6 FOUND END 1610 INC END.PNTR 1620 BNE .5 1630 INC END.PNTR+1 1640 BNE .5 1650 *---FOUND END OF STRING---------- 1660 .6 LDA #"." PRINT "..." 1670 JSR COUT 1680 JSR COUT PRINT THE END ADDRESS 1690 JSR COUT 1700 LDA END.PNTR+1 1710 LDX END.PNTR 1720 JSR PRINTAX 1730 LDA #$A0 PRINT " " 1740 JSR COUT 1750 JSR COUT 1760 JSR COUT 1770 *---PRINT OUT THE STRING--------- 1780 LDY #0 1790 LDX #0 1800 .7 LDA (MSG.PNTR),Y 1810 BEQ .9 ...END OF STRING 1820 ORA #$80 1830 CMP #$A0 PRINTING CHARACTER 1840 BCS .8 ...YES, GO PRINT IT 1850 ORA #$40 ...NO, CONTROL, CHANGE TO 1860 PHA PRINTING FORM 1870 LDA #"^" PRINT "^" FOLLOWED BE CHAR 1880 INX 1890 JSR COUT 1900 PLA 1910 .8 JSR COUT 1920 INX 1930 JSR INC ADVANCE MSG.PNTR 1940 CPX #55 IS THIS LINE FULL? 1950 BCC .7 ...NO, KEEP GOING 1960 LDX #24 ...YES, START NEW LINE 1970 JSR MARGIN INDENT 1980 LDX #0 1990 BEQ .7 ...ALWAYS 2000 *-------------------------------- 2010 .9 JSR CROUT 2020 JMP .1 2030 *-------------------------------- 2040 INC INC MSG.PNTR 2050 BNE .1 2060 INC MSG.PNTR+1 2070 .1 RTS 2080 *-------------------------------- 2090 PAUSE LDA KEYBOARD ANY KEY PRESSED? 2100 BPL .3 ...NO, RETURN 2110 STA STROBE ...YES, CLEAR STROBE 2120 CMP #$8D WAS KEY <RETURN>? 2130 BNE .2 ...NO, JUST A PAUSE 2140 .1 JMP $3D0 ...YES, ABORT 2150 .2 LDA KEYBOARD ANY KEY PRESSED? 2160 BPL .2 ...NO, KEEP WAITING 2170 STA STROBE ...YES, CLEAR STROBE 2180 CMP #$8D WAS KEY <RETURN>? 2190 BEQ .1 ...YES, ABORT 2200 .3 RTS ...NO, END OF PAUSE 2210 *-------------------------------- 2220 MARGIN JSR CROUT START A NEW LINE 2230 LDA #$A0 SKIP OVER (X) SPACES 2240 .10 JSR COUT 2250 DEX 2260 BNE .10 2270 RTS |
Have you ever wanted just a quick peek at the catalog entry for a file? Maybe you want to know where the track/sector list is? Or maybe you want to see if there are any control characters in the name? Or if the number of sectors is more than 255? You need to peek, because CATALOG won't tell you these details.
After all these years, I found out a simple way to do it. That is, assuming you can OPEN, SAVE, LOCK, or otherwise somehow make DOS go looking for the file.
After DOS has found the file, it leaves the directory sector containing the filename in the buffer at $B4BB-B5BA. DOS also leaves an index to the very byte at which the information on your file is found. The value in $B39C, if added to the address $B4C6, gives you the address of the start of the entry. $22 bytes later it ends.
A minute ago I saved the contents of this and a few other short articles on a file named V4N5 SHORT SUBJECTS. Then I left my word processor, typed CALL -151 to get into the monitor, and... Well, here, look for yourself:
]CALL-151 *B39C B39C- D2 (offset from B4C6) *C6+D2 =98 (first byte of entry) *98+22 =BA (last byte of entry) *B598.B5BA B598- 0C 0E 00 D6 B4 CE B5 A0 (track $0C, sector $0E, type $00) B5A0- D3 C8 CF D2 D4 A0 D3 D5 B5A8- C2 CA C5 C3 D4 C3 A0 A0 B5B0- A0 A0 A0 A0 A0 A0 A0 A0 B5B8- A0 07 00
The first byte at B598 is the track, and the second is the sector, where the track/sector list for this file is stored. The third byte is the file type (00 means an unlocked text file). The last two bytes are the file size. All the bytes in between are the file name.
If you are interested in the entry for a file you cannot reach directly, perhaps because there are hidden characters in the name, just LOCK, UNLOCK, or whatever a file above or below it in the catalog. Then peek at B39C and B4BB...B5BA to find the entry you are really interested in.
Bill and I found this technique extremely useful on the most recent consulting job we handled.
We also took advantage of the fact that the track/sector list of a file read or written on can be found at the beginning of the file buffer. If there are three buffers (MAXFILES=3), and if the file in question was the only one being accessed at the time, the T/S list will be found at $9600...$96FF. You can get the data you need immediately, without even finding your favorite ZAP utility.
The //e 80-column firmware scrolls in an annoying fashion. If you are trying to watch a listing go by, it looks like a bunch of kids on the playground, jumping up and down. And it is slower than almost any brand of 80-column card that plugs into slot 3.
The "slot 3" kind of 80-column card usually has a general purpose CRT controller chip on it. These chips use a wrap-around memory, and have one register that tells the chip where in memory to start the screen display. Scrolling is instantaneous, because it only involves writing a new address into two registers.
The //e 80-column card has no built-in features at all. All it is, is plain old RAM. A few extra circuits allow alternate columns to be taken first from the mother board and then from the 80-column card, back and forth. And the video rate is doubled, so 80 columns appear on each line. The scroll routine moves the whole screen up in two steps. First all the odd columns (in main memory) are moved up, and then all the even columns (in 80-column card memory). That is why you see the zig-zag effect.
The scroll is slower than a 40-column scroll by a factor of two. After all, it is essentially the same code, just called twice.
As I said in my article on fast scrolling in the September 1982 issue of AAL, you have to bear in mind that the authors of the programs in Apple ROM were not usually aiming for speed. They were trying to squeeze as much as possible into that tiny space, and make it as general as they could. The //e 80-column firmware supports windows smaller than a full screen, and that is seldom found in other types of 80-column cards.
On the other hand, since I am used to not having nice windows in the other cards, I can live with that in the //e. And I am having a hard time adjusting to that see-saw slow-motion scroller.
So, I re-wrote all the fast screen tricks from the September 1982 article to work in the //e with the Apple 80-column card. It scrolls as smooth as glass, but I still can't read it: now it's too fast!
1000 * S.SCREEN TRICKS //E 80-COLUMN 1010 *-------------------------------- 1020 * FAST SCREEN CLEAR SUBROUTINE 1030 *-------------------------------- 1040 GCLEAR LDA #255 1050 .HS 2C SKIP OVER NEXT TWO BYTES 1060 CLEAR LDA #$A0 1070 SET LDY #119 1080 .1 LDX #1 1090 .2 STA $C054,X 1100 STA $400,Y LINES: 0 8 16 1110 STA $500,Y 2 10 18 1120 STA $600,Y 4 12 20 1130 STA $700,Y 6 14 22 1140 STA $480,Y 1 9 17 1150 STA $580,Y 3 11 19 1160 STA $680,Y 5 13 21 1170 STA $780,Y 7 15 23 1180 DEX 1190 BPL .2 1200 DEY 1210 BPL .1 1220 RTS 1230 *-------------------------------- 1240 * SET SCREEN TO ALL VALUES 1250 *-------------------------------- 1260 SETALL LDA #0 1270 .1 PHA 1280 JSR SET 1290 PLA 1300 CLC 1310 ADC #1 1320 BNE .1 1330 RTS 1340 *-------------------------------- 1350 * ALTERNATE SCREEN UNTIL KEY PRESSED 1360 *-------------------------------- 1370 ALTER LDA #$20 INVERSE BLANK 1380 JSR SET 1390 JSR CLEAR 1400 LDA $C000 1410 BPL ALTER 1420 STA $C010 1430 RTS 1440 *-------------------------------- 1450 * FAST SCROLL UP SUBROUTINE 1460 *-------------------------------- 1470 SCROLL LDY #0 1480 .1 LDX #1 1490 .3 LDA $C054,X 1500 LDA $400,Y SAVE LINES: 0 8 16 1510 PHA 1520 LDA $480,Y MOVE 1>0, 9>8, 17>16 1530 STA $400,Y 1540 LDA $500,Y MOVE 2>1, 10>9, 18>17 1550 STA $480,Y 1560 LDA $580,Y MOVE 3>2, 11>10, 19>18 1570 STA $500,Y 1580 LDA $600,Y MOVE 4>3, 12>11, 20>19 1590 STA $580,Y 1600 LDA $680,Y ET CETERA 1610 STA $600,Y 1620 LDA $700,Y 1630 STA $680,Y 1640 LDA $780,Y 1650 STA $700,Y 1660 PLA MOVE 8>7, 16>15 1670 CPY #40 1680 BCC .2 DISCARD OLD LINE 0 1690 STA $780-40,Y 1700 .2 DEX 1710 BPL .3 1720 INY 1730 CPY #120 1740 BCC .1 1750 RTS 1760 *-------------------------------- 1770 * SCROLL AROUND, MOVING TOP LINE TO BOTTOM 1780 *-------------------------------- 1790 SCR LDY #39 SAVE TOP LINE ON STACK 1800 .1 LDA $C054 1810 LDA $400,Y 1820 PHA 1830 LDA $C055 1840 LDA $400,Y 1850 PHA 1860 DEY 1870 BPL .1 1880 JSR SCROLL SCROLL SCREEN UP ONE LINE 1890 LDY #0 STORE OLD TOP LINE 1900 .2 LDA $C055 1910 PLA ON BOTTOM OF SCREEN 1920 STA $7D0,Y 1930 LDA $C054 1940 PLA 1950 STA $7D0,Y 1960 INY 1970 CPY #40 1980 BCC .2 1990 RTS 2000 *-------------------------------- 2010 * ROTATE SCREEN UNTIL KEY PRESSED 2020 *-------------------------------- 2030 S JSR SCR SCROLL AROUND ONCE 2040 LDA $C000 ANY KEY PRESSED? 2050 BPL S NO, SCROLL AGAIN 2060 STA $C010 YES, CLEAR STROBE 2070 RTS ...AND RETURN |
A letter from Bill Basham (Diversi-DOS author) defending the practice of omitting the automatic VERIFY after SAVE to gain speed, was published in the September 1983 Softalk (page 37, 38). At the top of page 38 Bill claimed that the checksumming method used by DOS was of no value at all, because the checksum only depended on the last two bytes. In other words, Bill claims that errors in the first 340 bytes of a sector will not be caught.
Diversi-DOS is a fine product, and many thousands are enjoying its advantages. Nevertheless, Bill is wrong about the checksum. It does indeed catch errors throughout a sector. For a complete explanation, see the February 1984 Softalk. David Wagner clearly explains how the checksummer works, and refutes Bill's claim. See his letter on page 40.
You can look at the code, too. We printed a full commented source listing of this code in the June 1981 issue of AAL.
Well, now we know. The rumors were basically correct: 68000 processor, 128K RAM, 3.5 inch disk drive (but only one), portable, Lisa descendant, about $2500, and no expansion slots.
That last "feature" still has me a little shaken. I thought that if anybody knew better, it would be Apple, whose whole fortune is based on the expandability of the Apple ][. My first reaction was totally negative: who wants to bother with a dead-end machine? A total of 128K of RAM, and the screen memory occupies over 20K. Now that I've read a little more about the internals, and about the design objectives, things look a lot brighter. The on-board memory will be expandable to 512K when the 256K chips get more affordable.
System expansion will take place via the high-speed RS-422 serial ports. One of the designers pointed out that at 1 million bits per second (which can be reached with external clocking) you can transfer the entire memory image of the machine in one second. A couple of manufacturers (Davong and Tecmar) have already announced hard disks. Tecmar also announced an IEEE 488 interface. Macintosh designers also speak of "virtual slot" protocols for the serial ports, and "multi-drop (party line) capability".
There's another departure from usual Apple practice: no programming language is resident in the machine, or included in the purchase price! Several options will be available, including Pascal, Mac Basic, Microsoft Basic, Logo, and an Assembler/Debugger. The prices for the above packages will run in the $100-$150 range, not too bad. One article also mentioned C, about six months from now. It wasn't clear whether that was from Apple or an outside vendor. All of the above languages are scheduled for release in the next few months, except for Microsoft Basic. Russ Weaver, at Simtec/Quest, tells me he received that yesterday.
There is also 64K ROM (two 23256's) in the Mac, which holds the key to most programming. That ROM contains the code to support the "desk top" environment of mouse, icons, etc., the disk I/O, and the serial I/O. That is supposed to be 64K of the most tightly coded 68000 machine language around (as opposed to Lisa's compiled Pascal operating system code). I am told that there are over 400 entry points available to the programmer, with complete documentation coming soon from Apple for $250.
Several information sources have already popped up. If you haven't seen the February issue of Byte, go get it. There is a large section on Mac, including the best technical data so far. There are already two magazines specializing in Macintosh: Macworld, from the publishers of PC World, and ST.Mac, from Softalk. (Saint Mac? Come on.) Macworld looks very good, especially for evaluation and demonstration of software. I haven't seen a copy of ST.Mac yet, but Softalk is about the best of the "general" Apple magazines so I expect good things from their entry. You can pay $2495 for a Macintosh serial number and get a year's free subscription to ST.Mac.
Buried on the right side of page 65 of the November, 1983 issue of Call APPLE is the examination by Martin Smith of another quirk of the 6502. I say "another quirk" because it is similar to the JMP indirect wrap-around bug. Remember it?
As reported in the October 1980 issue of Apple Assembly Line, "JMP ($xxFF)" will not jump to the address pointed to by the two bytes beginning at $xxFF; rather the two bytes at $xxFF and $xx00 will be used. (Where xx means any page of memory.
A similar wrap-around situation can be found when indexing like this:
STACK .EQ $100 LDX #1 LDA STACK-1,X
Since STACK-1 is $FF, a page zero address mode is assembled. Indexing from within page zero never leaves page zero, so the above example references loacation $0000 rather than $0100.
The above is important, because many programmers use it in a "WHEREAMI" section of code to find the program's current address:
STACK .EQ $100 WHEREAMI JSR $FF58 (KNOWN rts INSTRUCTION) TSX LDA STACK-1,X GET PCL LDY STACK,X GET PCH
For the Merlin Assembler, the problem can be corrected by forcing the assembler to use an absolute addressing mode rather than a page zero addressing mode. This is done by suffixing a ":" to the opcode, like this:
LDA: STACK-1,X
The S-C Assemblers have no syntactical way to force absolute mode, but it can be done by defining the symbol STACK after its use. Here's an interesting example:
0800- BD FF 00 1000 LDA STACK-1,X 0100- 1010 STACK .EQ $100 0803- B5 FF 1020 LDA STACK-1,X
Since the assembler doesn't know the value of STACK in the first line, it has to assume it will be a two-byte address, and allocates that much space. By the time it gets to the last line it knows better.
The fact that indexing wraps around inside page zero is a plus sometimes. (I guess that explains why the chip works that way!) It has the effect of letting you use both positive and negative index offsets. Just beware of getting so used to negative offsets that you try to use them OUTSIDE page zero!
We always want speed. Making computers compute faster keeps our industry humming. Yet nearly every major program has pieces of code called delays.
We use them to generate carefully controlled, timed events: for example, generating a musical tone. We use them to synchronize events, or to provide time for external events to occur. We even use them just to slow the computer down so we can watch it work.
Delays are used so often that Woz had the foresight to put a general purpose delay subroutine permanently inside the monitor ROM. It resides at $FCA8. It is short (only 12 bytes), sweet (only uses one register, the same one which controls how long a delay you get), and slow (on purpose). Here is a listing:
WAIT SEC PREPARE TO SUBTRACT .1 PHA SAVE A COPY OF A-REG .2 SBC #1 COUNT A-REG DOWN TO ZERO BNE .2 ...UNTIL A=0 PLA GET SAVED COPY OF A-REG SBC #1 COUNT THIS COPY DOWN TOO BNE .1 ...UNTIL A=0 RTS
To use this subroutine, you load the A-register with a value which will determine the length of the delay, and then JSR WAIT. When the subroutine returns, A=0 and somewhere between 29 and 167309 clock cycles have elapsed. The formula, somewhat confusingly printed on page 165 of the white Apple II Reference Manual (and elsewhere in other manuals), is:
# cycles = (5*A*A + 27*A + 26)/2
For an example of its use, look in the monitor listing at $FBDD (the bell routine). Examples of other timing loops are found in the tape cassette I/O routines ($FCC9-$FD0B) and the paddle reading subroutine ($FB1E).
Bill and I spent the last two weeks working with software which surrounds the Novation Cat Modem. It is loaded with calls on the monitor WAIT subroutine. It is exceedingly tiresome to crank out a formula like the quadratic above by hand, or even with a calculator, over and over and over, when you have several Apples sitting in the same room!
After four or five trips to the manual and the calculator, I decided to work out the times for all possible values of the A-register. Once and for all.
Here is a little Applesoft program which does the job, and elsewhere in this AAL you will find a full page showing all the cycle counts.
1000 REM $FCA8 DELAY TIMES 1005 DIM P$(256) 1010 BL$ = " ":BR$ = " ": FOR A = 1 TO 256 1015 IF A = 65 THEN BL$ = " " 1016 IF A = 193 THEN BR$ = " " 1020 T = (A * A * 5 + A * 27 + 26) / 2 1030 X = A: IF A = 256 THEN X = 0 1040 X$ = RIGHT$ (" " + STR$ (X),3) 1050 TR$ = RIGHT$ ( STR$ (T + 1000000),3):T = INT (T / 1000):TL$ = RIGHT$ (" " + STR$ (T),3):T$ = TL$ + "." + TR$ 1060 H = INT (X / 16):L = X - H * 16 1070 H = H + 7 * (H > 9):L = L + 7 * (L > 9) 1080 H$ = "$" + CHR$ (H + 48) + CHR$ (L + 48) 1090 P$(A) = H$ + BL$ + X$ + BR$ + T$ 1100 NEXT 2000 FOR I = 1 TO 64: PRINT P$(I)" "P$(I + 64)" "P$(I + 128 )" "P$(I + 192): NEXT
The A-register values are given in both hex and decimal. The delay count is given in thousands of cycles. Each cycle is close to one microsecond, so you could think of the counts as being in milliseconds.
The purists among you will want to multiply these cycle counts by the ACTUAL clock period (.9799268644 microseconds average, according to Sather) to get ACTUAL time.
RWTS in DOS or ProDOS also give lessons in the use of precise delays. You will find weird little pieces of code which make no sense whatever inside RWTS. Things like PHA followed immediately by PLA, followed by a NOP. These are usually just delaying tricks. A PHA-PLA pair takes exactly seven cycles, a NOP 2 more. There is a delay while waiting for the motor to come up to speed. Another while stepping the head from track to track.
These last two are intertwined, so that delays used while stepping across tracks count towards the total delay required to get the disk rotating at 300 rpm.
Don Lancaster in his Enhancing the Apple books makes good use of delays in synchronizing graphics generation with the CRT. By updating a picture in one graphics page while displaying another, and then switching pages, you can get pretty impressive animation. However, the page flipping operations sometimes splatter the display. Using delays just right, you can make the switching occur when it won't be noticed. You can even mix graphics into the middle of a text screen or vice versa, or mix hi-res and lo-res on the same screen.
Jim Sather in "Understanding the Apple II" also uses delays to control the screen switches in interesting ways. Jim figured out exactly how many cycles everything in the video generation circuitry takes. Using his programs you can even use hi-res to draw underlines on text screens! A horizontal scan takes exactly 65 clock cycles. A vertical scan takes exactly 17030 cycles. The following program, adapted from one given on page 3-16 of Sather's book, splits the screen between hi-res and lo-res. Tapping the space bar moves the boundaries of the split. Play with it!
1000 *SAVE SATHER 3-16 1010 *-------------------------------- 1020 * HIRES-LORES SPLIT 1030 * SATHER 3-16 1040 *-------------------------------- 1050 KYBD .EQ $C000 1060 STRB .EQ $C010 1070 GRAPHICS .EQ $C050 1080 TEXT .EQ $C051 1090 NOTMIXED .EQ $C052 1100 PAGE1 .EQ $C054 1110 LORES .EQ $C056 1120 *-------------------------------- 1130 * TOGGLE HI/LO-RES EVERY 8515 CYCLES 1140 *-------------------------------- 1150 .OR $300 1160 SPLIT LDY PAGE1 HI/LO PAGE 1 1170 LDY NOTMIXED 1180 LDY GRAPHICS 1190 *-------------------------------- 1200 SLEW LDY #39 (2) SLEW SCREEN IF KEY PRESSED 1210 JSR WAITX10 (390) 6*65+7 CYCLES 1220 LDY STRB (4) 1230 *-------------------------------- 1240 KEYCHK LDY KYBD (4) ANY KEY PRESSED? 1250 BMI SLEW (2 OR 3) YES, SLEW ONE LINE 1260 ADC #1 (2) MAKE ALTERNATING 0 AND 1 1270 AND #1 (2) 1280 TAX (2) REMEMBER, 0 OR 1 1290 LDY LORES,X (4) LORES IF X=0, HIRES IF X=1 1300 LDX #8 (2) 1310 JSR WAITX1K (8000) 1320 LDY #49 (2) 1330 JSR WAITX10 (490) 1340 CLC (2) 1350 BCC KEYCHK (3) ...ALWAYS 1360 * ====== 1370 * (8515) 1380 * 1390 *-------------------------------- 1400 * TIMING ROUTINES 1410 *-------------------------------- 1420 * 1430 *---WAIT 10Y CYCLES-------------- 1440 *---(INCLUDING JSR)-------------- 1450 WAITX10 DEY (2) WAIT Y-REG TIMES 10 1460 .1 DEY (2) 1470 NOP (2) 1480 BNE .2 (3 OR 2) 1490 RTS (6) 1500 .2 BNE .1 (3) ...ALWAYS 1510 *-------------------------------- 1520 * 1530 *---WAIT 1000X CYCLES------------ 1540 *---(INCLUDING JSR)-------------- 1550 LOOP1K PHA (3) 1560 PLA (4) 1570 NOP (2) 1580 NOP (2) 1590 WAITX1K LDY #98 (2) WAIT X-REG TIMES 1000 1600 JSR WAITX10 (980) 1610 NOP (2) 1620 DEX (2) 1630 BNE LOOP1K (3 OR 2) 1640 RTS (6) 1650 *-------------------------------- 1660 *-------------------------------- 1670 * HORIZONTAL SPLIT 1680 * BY BOB SANDER-CEDERLOF 1690 *-------------------------------- 1700 HSPLIT 1710 LDA GRAPHICS (4 4) 1720 LDA KYBD (4 4) SEE IF SHOULD SLEW 1730 BPL .1 (3 2) 1740 STA STRB (4) 1750 BMI .3 (3) 1760 .1 NOP (2) 1770 BPL .3 (3) 1780 .3 JSR DLY12 (12 12) 1790 NOP (2 2) 1800 NOP (2 2) 1810 * --- --- 1820 * (32 33) 1830 * 1840 LDA TEXT (4) 1850 JSR DLY21 (21) 1860 CLC (2) 1870 BCC .2 (3) 1880 .2 BCC HSPLIT (3) 1890 * ---- 1900 * (33) 1910 * 1920 *-------------------------------- 1930 * JSR DLY.. (6) (6) 1940 DLY21 PHA (3) 1950 PLA (4) 1960 NOP (2) 1970 DLY12 RTS (6) (6) 1980 * ---- ---- 1990 * (21) (12) |
MON.WAIT ($FCA8) Delay Times in Kilocycles |
---|
$01 01 0.029 $41 065 11.453 $81 129 43.357 $C1 193 95.741 |
$02 02 0.050 $42 066 11.794 $82 130 44.018 $C2 194 96.722 |
$03 03 0.076 $43 067 12.140 $83 131 44.684 $C3 195 97.708 |
$04 04 0.107 $44 068 12.491 $84 132 45.355 $C4 196 98.699 |
$05 05 0.143 $45 069 12.847 $85 133 46.031 $C5 197 99.695 |
$06 06 0.184 $46 070 13.208 $86 134 46.712 $C6 198 100.696 |
$07 07 0.230 $47 071 13.574 $87 135 47.398 $C7 199 101.702 |
$08 08 0.281 $48 072 13.945 $88 136 48.089 $C8 200 102.713 |
$09 09 0.337 $49 073 14.321 $89 137 48.785 $C9 201 103.729 |
$0A 10 0.398 $4A 074 14.702 $8A 138 49.486 $CA 202 104.750 |
$0B 11 0.464 $4B 075 15.088 $8B 139 50.192 $CB 203 105.776 |
$0C 12 0.535 $4C 076 15.479 $8C 140 50.903 $CC 204 106.807 |
$0D 13 0.611 $4D 077 15.875 $8D 141 51.619 $CD 205 107.843 |
$0E 14 0.692 $4E 078 16.276 $8E 142 52.340 $CE 206 108.884 |
$0F 15 0.778 $4F 079 16.682 $8F 143 53.066 $CF 207 109.930 |
$10 16 0.869 $50 080 17.093 $90 144 53.797 $D0 208 110.981 |
$11 17 0.965 $51 081 17.509 $91 145 54.533 $D1 209 112.037 |
$12 18 1.066 $52 082 17.930 $92 146 55.274 $D2 210 113.098 |
$13 19 1.172 $53 083 18.356 $93 147 56.020 $D3 211 114.164 |
$14 20 1.283 $54 084 18.787 $94 148 56.771 $D4 212 115.235 |
$15 21 1.399 $55 085 19.223 $95 149 57.527 $D5 213 116.311 |
$16 22 1.520 $56 086 19.664 $96 150 58.288 $D6 214 117.392 |
$17 23 1.646 $57 087 20.110 $97 151 59.054 $D7 215 118.478 |
$18 24 1.777 $58 088 20.561 $98 152 59.825 $D8 216 119.569 |
$19 25 1.913 $59 089 21.017 $99 153 60.601 $D9 217 120.665 |
$1A 26 2.054 $5A 090 21.478 $9A 154 61.382 $DA 218 121.766 |
$1B 27 2.200 $5B 091 21.944 $9B 155 62.168 $DB 219 122.872 |
$1C 28 2.351 $5C 092 22.415 $9C 156 62.959 $DC 220 123.983 |
$1D 29 2.507 $5D 093 22.891 $9D 157 63.755 $DD 221 125.099 |
$1E 30 2.668 $5E 094 23.372 $9E 158 64.556 $DE 222 126.220 |
$1F 31 2.834 $5F 095 23.858 $9F 159 65.362 $DF 223 127.346 |
$20 32 3.005 $60 096 24.349 $A0 160 66.173 $E0 224 128.477 |
$21 33 3.181 $61 097 24.845 $A1 161 66.989 $E1 225 129.613 |
$22 34 3.362 $62 098 25.346 $A2 162 67.810 $E2 226 130.754 |
$23 35 3.548 $63 099 25.852 $A3 163 68.636 $E3 227 131.900 |
$24 36 3.739 $64 100 26.363 $A4 164 69.467 $E4 228 133.051 |
$25 37 3.935 $65 101 26.879 $A5 165 70.303 $E5 229 134.207 |
$26 38 4.136 $66 102 27.400 $A6 166 71.144 $E6 230 135.368 |
$27 39 4.342 $67 103 27.926 $A7 167 71.990 $E7 231 136.534 |
$28 40 4.553 $68 104 28.457 $A8 168 72.841 $E8 232 137.705 |
$29 41 4.769 $69 105 28.993 $A9 169 73.697 $E9 233 138.881 |
$2A 42 4.990 $6A 106 29.534 $AA 170 74.558 $EA 234 140.062 |
$2B 43 5.216 $6B 107 30.080 $AB 171 75.424 $EB 235 141.248 |
$2C 44 5.447 $6C 108 30.631 $AC 172 76.295 $EC 236 142.439 |
$2D 45 5.683 $6D 109 31.187 $AD 173 77.171 $ED 237 143.635 |
$2E 46 5.924 $6E 110 31.748 $AE 174 78.052 $EE 238 144.836 |
$2F 47 6.170 $6F 111 32.314 $AF 175 78.938 $EF 239 146.042 |
$30 48 6.421 $70 112 32.885 $B0 176 79.829 $F0 240 147.253 |
$31 49 6.677 $71 113 33.461 $B1 177 80.725 $F1 241 148.469 |
$32 50 6.938 $72 114 34.042 $B2 178 81.626 $F2 242 149.690 |
$33 51 7.204 $73 115 34.628 $B3 179 82.532 $F3 243 150.916 |
$34 52 7.475 $74 116 35.219 $B4 180 83.443 $F4 244 152.147 |
$35 53 7.751 $75 117 35.815 $B5 181 84.359 $F5 245 153.383 |
$36 54 8.032 $76 118 36.416 $B6 182 85.280 $F6 246 154.624 |
$37 55 8.318 $77 119 37.022 $B7 183 86.206 $F7 247 155.870 |
$38 56 8.609 $78 120 37.633 $B8 184 87.137 $F8 248 157.121 |
$39 57 8.905 $79 121 38.249 $B9 185 88.073 $F9 249 158.377 |
$3A 58 9.206 $7A 122 38.870 $BA 186 89.014 $FA 250 159.638 |
$3B 59 9.512 $7B 123 39.496 $BB 187 89.960 $FB 251 160.904 |
$3C 60 9.823 $7C 124 40.127 $BC 188 90.911 $FC 252 162.175 |
$3D 61 10.139 $7D 125 40.763 $BD 189 91.867 $FD 253 163.451 |
$3E 62 10.460 $7E 126 41.404 $BE 190 92.828 $FE 254 164.732 |
$3F 63 10.786 $7F 127 42.050 $BF 191 93.794 $FF 255 166.018 |
$40 64 11.117 $80 128 42.701 $C0 192 94.765 $00 000 167.309 |
Here is a quick look at some of the books and articles about the 68000 that I have found to be helpful.
Another possible source of 68000 information is the newsletter "DTACK Grounded", published by Digital Acoustics, 1415 E. McFadden, Suite F, Santa Ana, CA 92705. I've only seen one or two issues, back before I got interested in 68000, so I don't know exactly what they've been up to lately. I'll be finding out soon and pass it on. I might note that the issue I have (#7, Feb-Mar 1982) contains about 12 pages of more-or-less interesting gossip, and no code. I don't know if that is typical.
Books:
68000 Assembly Language Programming. Gerry Kane, Doug Hawkins & Lance Leventhal. OSBORNE/McGraw-Hill, 1981.
The 68000: Principles and Programming. Leo. J. Scanlon. Blacksburg/Sams, 1981.
MC68000 16-bit Microprocessor User's Manual, third edition. Motorola/Prentice-Hall, 1982.
MK68000 Microcomputer Programming Reference Guide. Mostek Corp, 1981.
Programming the M68000. Tim King and Brian Knight. Addison-Wesley, 1983.
Articles:
Design Philosophy Behind Motorola's MC68000. Thomas W. Starnes (of Motorola, Inc.) Byte. April-June, 1983 (3 parts).
68000 Instructions and Addressing Modes. Joe Hootman. Micro. #'s 52,54-57,60-62 (8 parts).
An MC68000 Overview. Joe Jelemensky & Tom Whiteside. Micro. #'s 52,54.
For some reason none of the //e manuals I own give a complete chart in one place of all the new soft switches. If I print one here, I'll have one when I need it, so that's what the first chart on the following page is.
I have ordered them according to the location you peek at to find which position the soft switch is in. The first column is the location you read. The sense of the switch is given by bit 7 of the byte you read, and that bit's value is given at the top of the next two columns.
Note that there is an error in the Apple //e Reference Manual, on both pages 133 and 214, where the SLOTCXROM soft switch is described. In both places, the slot/internal designations are backwards. It looks like the book was written rationally, and the circuit behaves irrationally, because the SLOTC3ROM switch operates the opposite manner from the SLOTCXROM switch. Oh well...
The maze of information regarding the bank switching switches has me baffled. The second chart should help demystify things. I show which switches to throw which way to make any particular range of memory come from the main 64K or the auxiliary bank. To keep the chart from growing beyond the page, I did not include the LCBANK, SLOTCX, or SLOTC3 switches.
First Chart:
Status 0 1 ==================================== C011 C08(8-B) C08(0-3) LCBANK Bank 1 Bank 2 D000-DFFF ------------------------------------ C012 C081,2,9,A C080,3,8,B LCRAM Select ROM Select RAM D000-FFFF ------------------------------------ C013 C002 C003 RAMRD Read Main Read Aux 200-BFFF ------------------------------------ C014 C004 C005 RAMWRT Write Main Write Aux 200-BFFF ------------------------------------ C015 C006 C007 SLOTCX Slot Internal C100-C7FF ------------------------------------ C016 C008 C009 ALTZP Main Aux 0-1FF, D000-FFFF ------------------------------------ C017 C00A C00B SLOTC3 Internal Slot C300-C3FF, C800-CFFF ------------------------------------ | Status 0 1 ==================================== C018 C000 C001 80STORE RAMRD/RAMWRT PAGE2 400-7FF, 2000-3FFF ------------------------------------ C019 VBL in display in blanking ------------------------------------ C01A C050 C051 TEXT Graphics Text ------------------------------------ C01B C052 C053 MIXED All Text or Mixed text all graphics & graphics ------------------------------------ C01C C054 C055 PAGE2 Page 1/Main Page 2/Aux 400-7FF, 2000-3FFF ------------------------------------ C01D C056 C057 HIRES Lo-Res Hi-Res ------------------------------------ C01E C00E C00F CHARSET Normal Alternate ------------------------------------ C01F C00C C00D 80COL 40 Columns 80 Columns ==================================== |
Second Chart:
Address Main Memory Aux Memory ======================================= E000-FFFF C008 ALTZP=0 C009 ALTZP=1 C080,3,8,B C080,3,8,B LCRAM=1 LCRAM=1 --------------------------------------- C000-CFFF I/O Space --------------------------------------- 4000-BFFF Read: C002 Read: C003 Write: C004 Write: C005 --------------------------------------- 2000-3FFF C001 80STORE=1 C001 80STORE=1 C057 HIRES=1 C057 HIRES=1 C054 PAGE2=0 C055 PAGE2=1 |
Good programs interact frequently with their users, providing error messages, helpful prompts, and information about what the program is doing. For programmers, this raises the question of what to do with the messages once they have been printed, especially if you want to get rid of them while leaving the rest of the screen intact.
I have used several strategies to clear specific areas of the text screen. The simplest solution, and probably the most commonly used, is to place all messages at the end of the page. Then you can HTAB and VTAB to the first character of the message and CALL the Monitor routine at $FC42 (CLREOP). From Applesoft, CALL -958. Such messages must be kept to the lower part of the screen, however, and the method can interfere with decorative borders, etc., placed around your screens.
Another thing I have done is to print strings of blanks over the offending message. I use a loop to HTAB and VTAB to the left margin of the message area, incrementing the vertical coordinate each time, then printing a string variable set to a predetermined number of blanks. This method is slow, but not unbearable. Still, it is clumsy and wastes memory storing the blanks.
Of course, instantaneous clears of a given area are easily done by resetting the text window through POKEing values to locations $25-$28, then executing a HOME. This requires POKEing 4 values before the clear, however, and POKEing 4 coordinates to reset the current window when you are done (or "TEXT" to reset the default window). Downright unpleasant. For a time I resorted to this method to protect my decorative borders, however.
Now I have come up with a routine that I think is an improvement over the above. It clears rectangular areas of the text screen given the width and depth (number of lines) needed. Because it uses the Monitor COUT routine, it should also work with those hi-res character generator utilities that interface to the normal output hooks, giving a controlled hi-res screen clear. While it requires Applesoft in ROM, it is fully relocatable, making it ideal for people who use Ampersand utilities like AmperMagic or The Routine Machine.
The routine, which I call "ERASE", is used by first HTABing and VTABing to the upper left corner of the area to be cleared. Then CALL the routine giving the width and depth of the area to be cleared, using commas, like so:
CALL ADDRESS,WIDTH,DEPTH
For example, assume you BLOAD the routine at $300, the most common place to do such things. (At least while we are testing the program.) Then, to clear an area 15 characters wide by 4 lines deep, write:
CALL 768,15,4The command shown above uses simple constants, but ERASE can handle any quantities "width" and "depth" up to formulas as complex as those Applesoft can normally handle. (I can't brag about that part, since all the work is done by Applesoft's formula evaluation routine "FRMEVL", called indirectly in my program by the "JSR GETBYT".
In case you don't have John Crossley's article on Applesoft Internal Entry Points, GETBYT is a subsidiary routine that evaluates formulas, bringing back a single-byte integer in the X-register and in location $A1--"FACLO". I don't use "FACLO" in this routine. GETBYT gives an illegal quantity error if the formula evaluates to more than 255 or less than 0.)
If you specify a width or depth of zero, ERASE will give an illegal quantity error. If the width of the line goes past the right edge of the screen, the blanks will wrap around the screen on the next line down. ERASE will pick up at the correct horizontal/vertical location when clearing subsequent lines, however. If the area to be erased goes past the bottom of the screen, do not fear: ERASE wraps around to the top of the screen. Your program and variables will not be hurt.
Here is a short Applesoft program that demonstrates ERASE in action. The program first fills the entire screen with asterisks, and then clears three windows. The first window wraps around from the right edge of the screen to the left. The second wraps around from the bottom to the top. The third is in the middle of the screen. (I am assuming a 40-column screen here.)
100 FOR I = 1 TO 24: PRINT "****************************************"; : NEXT 110 HTAB 30: VTAB 10: CALL 768,20,5 120 HTAB 10: VTAB 20: CALL 768,20,8 130 HTAB 15: VTAB 10: CALL 768,10,5
And here is another demo, one which is closer to the way you will find yourself using ERASE. This one prints an array of six messages in six windows on the scrren, and lets you selectively erase them in any order one-by-one. As it turned out, the way I located the upper corners of the messages involved some lengthy formulas, but these ended up in the HTAB and VTAB statements. Note that I could have used data statements for similar results.
10 REM ******************************** 20 REM * * 30 REM * AREA ERASE DEMO * 40 REM * * 50 REM * JEFF CREAMER * 60 REM * * 70 REM ******************************** 80 REM 90 PRINT CHR$ (4);"BLOAD ERASE" 100 HOME : VTAB 5 110 PRINT " AREA #1 AREA #2 AREA #3" 120 PRINT " IN THIS AROUND LIVES IN" 130 PRINT " VICINITY HERE THIS CORNER" 140 VTAB 12 150 PRINT " AREA #4 AREA #5 AREA #6" 160 PRINT " THAT'S AT YOUR IS ALSO" 170 PRINT " ME! SERVICE! GREAT." 180 HTAB 15: VTAB 20 190 PRINT "ERASE WHICH?";: GET A$ 200 ON ASC (A$) = 13 GOTO 260 210 A = VAL (A$): ON A < 1 OR A > 6 GOTO 180 220 HTAB 12 * ( INT (((A - 1) / 3 - INT ((A - 1) / 3)) * 3 + .0 5)) + 3 230 VTAB (A < 4) * 5 + (A > 3) * 12 240 CALL 768,13,3 250 GOTO 180 260 HOME : VTAB 20: PRINT "BYE!": END
1000 *SAVE S.ERASE (JEFF CREAMER) 1010 *-------------------------------- 1020 * * 1030 * ERASE ROUTINE * 1040 * * 1050 * Jeff Creamer * 1060 * * 1070 * CALL 768,(WIDTH),(DEPTH) * 1080 * * 1090 *-------------------------------- 1100 * PAGE ZERO VARIABLES 1110 *-------------------------------- 1120 MON.CH .EQ $24 1130 MON.CV .EQ $25 1140 *-------------------------------- 1150 * APPLESOFT ROUTINES USED 1160 *-------------------------------- 1170 AS.CHKCOM .EQ $DEBE 1180 AS.GETBYT .EQ $E6F8 1190 AS.IQERR .EQ $E199 1200 *-------------------------------- 1210 * MONITOR ROUTINES USED 1220 *-------------------------------- 1230 MON.VTAB .EQ $FC22 1240 MON.PRBL2 .EQ $F94A 1250 *-------------------------------- 1260 .OR $300 1270 .TF ERASE 1280 *-------------------------------- 1290 * JEFF'S ERASE ROUTINE 1300 *-------------------------------- 1310 ERASE LDA MON.CV GET VERTICAL COORD 1320 PHA SAVE ON STACK 1330 LDA MON.CH AND HORIZ COORD 1340 PHA SAVE IT ON STACK, TOO 1350 JSR AS.CHKCOM COMMA? 1360 JSR AS.GETBYT YES, GET WIDTH TO ERASE 1370 TXA INTO ACC 1380 BEQ .4 WIDTH MUST BE NON-ZERO 1390 PHA PUSH WIDTH ON STACK 1400 JSR AS.CHKCOM COMMA NEXT? 1410 JSR AS.GETBYT YES, GET DEPTH 1420 TXA AND TRANSFER TO ACC 1430 BEQ .4 DEPTH MUST BE NON-ZERO 1440 TAY DEPTH INTO Y REGISTER 1450 PLA WIDTH BACK OFF STACK 1460 PHA BUT KEEP IT THERE ALSO 1470 TAX AND INTO X-REG 1480 .1 LDA MON.CV REMEMBER CV ON STACK 1490 PHA 1500 JSR MON.PRBL2 PRINT WIDTH # OF BLANKS 1510 PLA GET OLD CV OFF STACK 1520 DEY DECREMENT DEPTH 1530 BEQ .3 ZERO LINES LEFT? 1540 TAX OLD CV INTO X-REGISTER 1550 INX NEXT LINE 1560 CPX #24 OFF THE BOTTOM? 1570 BCC .2 NO, USE THIS ONE 1580 LDX #0 YES, WRAP BACK TO TOP 1590 .2 STX MON.CV 1600 JSR MON.VTAB ADJUST BASE ADDRESS 1610 PLA WIDTH OFF STACK 1620 TAX TO SET UP X AGAIN 1630 PLA HORIZ COORD OFF STACK 1640 PHA BUT MAINTAIN IT THERE ALSO 1650 STA MON.CH AND RESTORE HCURSOR 1660 TXA PUSH WIDTH BACK ON STACK 1670 PHA FOR NEXT TIME AROUND 1680 BNE .1 LOOP ALWAYS 1690 .3 PLA POP WIDTH OFF 1700 PLA GET HORIZ COORDINATE 1710 STA MON.CH AND RESTORE IT 1720 PLA GET VERTICAL COOORDINATE 1730 STA MON.CV RESTORE IT, TOO 1740 JSR MON.VTAB ADJUST BASE ADDRESS 1750 RTS DONE 1760 .4 JMP AS.IQERR ILLEGAL QUANTITY ERROR |
Jim Sather, author of "Understanding the Apple II", has designed and programmed a great new plug-in. It is basically a ROM card, but hold on to your hats!
The card has sockets for 8 EPROMs, and they can be any EPROM size from 2716 up through 27256. That means the card can hold a up to 256 kilobytes!
The card comes loaded already with three 2764 devices, programmed with licensed copies of DOS 3.3, FID, COPYA, the quikLoad operating system, and possibly more. I think Integer BASIC is on there too. With DOS on the card, you can leave it off your disks. You gain at least two tracks per disk this way.
The quikLoad operating system allows you to load any program from the card into RAM in a flash. If you have an EPROM programmer that can burn 2764s or larger, you can put favorites like the S-C Macro Assembler and our word processor permanently there. The programs don't even have to be modified, because they will be loaded into their normal RAM locations for execution.
You control the card by typing a control character along with RESET. For example, ctrl-C RESET catalogs a disk; ctrl-H RESET runs "HELLO"; others boot a disk or enter the monitor. Ctrl-Q RESET gives you a catalog of your quikLoader ROMs, in the form of a menu; a single keystroke then selects a program.
The board is compatible with Apple II, II Plus, and //e. In a II Plus with a 16K RAM card, you may need to perform a slight modification to the RAM card as explained in the documentation.
The boards are being manufactured by Southern California Research Group (SCRG), P. O. Box 2231, Goleta, CA 93118. Phone (805) 685-1931. Their price is $179.50. You can order them from us if you like, at $170 + shipping.
A few months back an article in Byte magazine presented some fast hi-resolution plotting routines. One of the secrets to fast plotting is table lookup rather than computation of base addresses and offsets. The article included a 560 byte table for all the possible quotients and remainers you can get when dividing X by 7, where X is the horizontal coordinate (0 to 279).
The table of quotients and remainders makes it easy to get the byte position on a line (quotient) and the bit position in the byte (remainder) for a given dot X-coordinate.
Typing a 560 byte table into the computer is no fun, no matter how you do it. You might go into the monitor and type directly in hex, then later BSAVE the table. Or you might use an Applesoft program to build the table. I think the easiest way is to write a few short macros, and let the assembler do the work.
If you have Version 1.1 of the S-C Macro Assembler, the following code will do the trick. Version 1.0 cannot handle it, because the nesting level goes too deep. The listing it prints out gets quite long, due to all the macro expansion. Therefore I am just printing the source code here. The table it produces is also long, so I am just showing the beginning and end of it.
1000 *-------------------------------- 1010 * GENERATE QUOTIENT-REMAINDER 1020 * TABLE FOR ALL POSSIBLE VALUES 1030 * OF X/7, WHERE X=0...255 1040 *-------------------------------- 1050 .MA DO.QS 1060 R .SE 0 1070 >DO.RS 1080 Q .SE Q+1 1090 .DO Q<40 1100 >DO.QS 1110 .FIN 1120 .EM 1130 *-------------------------------- 1140 .MA DO.RS 1150 .DA #Q,#R 1160 R .SE R+1 1170 .DO R<7 1180 >DO.RS 1190 .FIN 1200 .EM 1210 *-------------------------------- 1220 Q .SE 0 1230 >DO.QS 1240 *-------------------------------- |
Here is the beginning and end few lines of the hex dump of the table:
0800- 00 00 00 01 00 02 00 03 0808- 00 04 00 05 00 06 01 00 0810- 01 01 01 02 01 03 01 04 . . . 0A18- 26 02 26 03 26 04 26 05 0A20- 26 06 27 00 27 01 27 02 0A28- 27 03 27 04 27 05 27 06
Apple Assembly Line is published monthly by S-C SOFTWARE CORPORATION, P.O. Box 280300, Dallas, Texas 75228. Phone (214) 324-2050. Subscription rate is $18 per year in the USA, sent Bulk Mail; add $3 for First Class postage in USA, Canada, and Mexico; add $12 postage for other countries. Back issues are available for $1.80 each (other countries add $1 per back issue for postage).
All material herein is copyrighted by S-C SOFTWARE, all rights reserved.
Unless otherwise indicated, all material herein is authored by Bob Sander-Cederlof.
(Apple is a registered trademark of Apple Computer, Inc.)