Apple Assembly Line Volume 3 -- Issue 3 December, 1982 In This Issue... ---------------- Making Internal JMPs and JSRs Relocatable. . . . . . . . . 2 Add Bit-Control to Apple Monitor . . . . . . . . . . . . . 10 Assembly Listings on TEXT Files. . . . . . . . . . . . . . 13 Add a New Feature to ES-CAPE . . . . . . . . . . . . . . . 14 Applesoft Source, Completely Commented . . . . . . . . . . 15 New Enhanced 6502 Nearly Here! . . . . . . . . . . . . . . 16 Toggling Upper/Lower Case in the S-C Macro Assembler . . . 19 Save Garbage by Emptying Arrays. . . . . . . . . . . . . . 22 Splitting Strings to Fit Your Display. . . . . . . . . . . 26 Enhancing Your Apple II (A Review) . . . . . . . . . . . . 29 Clarification on Loading the RAM Card. . . . . . . . . . . 32 Quickies . . . . . . . . . . . . . . . . . . 13, 14, 15, & 30 Cross Assemblers continue to appear. We now have ready a version for the Intel 8048, and one for the yet unreleased Rockwell 65C02. More on the latter inside. Don Lancaster, famous author of many books published by Howard Sams, says the Apple II is probably going to have a greater impact on history than the automobile or television! Perhaps verging on Applolatry, but you will surely enjoy his new book. See Bill's reviews inside. If I am trying to learn how to program in assembly language, or to increase my skill at it, what (besides AAL) should I read? I strongly recommend Softalk, Nibble, Micro, and Call APPLE. Every month they publish excellent examples of assembly language programs which you can study, modify, and use. As for books, Roger Wagner's, Lance Leventhal's, and Don Lancaster's are my favorites at this time. Making Internal JMPs and JSRs Relocatable.........Peter Meyer ------------------------------------------------------------- A machine language routine is said to be relocatable if it can function properly regardless of its absolute location in memory. If a routine contains a JMP or a JSR to an INTERNAL address then it is not relocatable; if it is run in another part of memory then the internal JSR or JMP will still reference the former region of memory. JMPs and JSRs to subroutines at absolute locations (e.g. in the Monitor) do not impair the relocatability of a routine. I will explain here a technique whereby you can, in effect, perform internal JSRs and JMPs without impairing the relocatability of your routine. There is a small price to pay for this: namely, an increase in the length of your routine. Your routine must be preceded by a 2-part Header Routine which is 43 bytes long. In addition, each internal JSR requires 8 bytes of code, and each internal JMP requires 11 bytes of code. No tables or other data storage are required, except that three bytes must be reserved for a JMP instruction. These three bytes can be anywhere in memory, but must be at an absolute location. There are three bytes that normally are used only by Applesoft, namely, the ampersand JMP vector at $3F5 to $3F7. Since we are here concerned only with machine language routines in their own right, we can use the locations $3F5 to $3F7 for our own purposes. However, other locations would do just as well. The technique is fully illustrated in the accompanying assembly language program. This routine consists of three parts: (1) Header Part 1 (SETUP), which sets up a JMP instruction at VECTOR (at $3F5-$3F7, but could be different, as explained above) to point to Header Part 2. (2) Header Part 2 (HANDLER), which is a 15-byte section of code whose task is to handle requests to perform internal JSRs and JMPs (more on this below). (3) The main part of the routine, in which internal JSRs and JMPs (in effect) are performed using macro instructions. When your routine (including the Header) is executed, the first thing that happens is that Header Part 1 locates itself (using the well-known JSR $FF58 technique), then places a JMP HANDLER at VECTOR. Thereafter a JMP VECTOR is equivalent to JMP HANDLER, and a JSR VECTOR is equivalent to a JSR HANDLER. The HANDLER routine handles requests from your routine for internal JSRs and JMPs. To perform a JSR to an internal subroutine labelled SUBR simply include the following code: HERE LDA #SUBR-HERE-7 low byte of offset LDY /SUBR-HERE-7 high byte of offset TSX JSR VECTOR As explained above, the JSR VECTOR is in effect a JSR HANDLER. The Header Part 2 code takes the values in the A and Y registers and adds them to an address which it obtains from the stack to obtain the address of SUBR. It then places this address in INDEX ($5E,5F) and executes "JMP (INDEX)". An internal JMP, from one part of your routine to another, is performed in a similar manner. Suppose you wish to JMP from HERE to THERE. It is done as follows: HERE LDA #THERE-HERE-7 low byte of offset LDY /THERE-HERE-7 high byte of offset TSX JSR $FF58 JMP VECTOR Since we are (in effect) performing a JMP, rather than a JSR, we do a JMP VECTOR rather than a JSR VECTOR. The other difference is that we have a JSR $FF58 following the TSX. Clearly the sequence of instructions which allows you to perform a JMP or a JSR could be coded as a macro. The macros to use are shown in the accompanying program listing. By using macros an internal JMP or JSR can be performed with a single macro instruction bearing a very close resemblance to a real JSR or JMP instruction. The following program, which consists of the Header Routine plus a demonstration routine, can be assembled to disk using the .TF directive. It can then be BRUN at any address and it will function properly. Thus it is relocatable, despite the fact that there are (in effect) an internal JMP and two internal JSRs performed. When performing an internal JSR or JMP using my techniques, it is not possible to pass values in the registers, since these are required to pass information to the HANDLER routine. Nor is it advisable to try to pass parameters on the stack, even though the HANDLER routine does not change the value of the stack pointer. Better is to deposit values in memory and retrieve them after the transition has been made. The HANDLER routine passes control to the requested part of your routine using a JMP indirect. (INDEX at $5E,5F, has been used in the accompanying program, but any other address would do as well, provided that it does not cross a page boundary.) This means that the section of your routine to which control is passed (whether or not it is a subroutine) may find its own location by inspecting the contents of the location used for the JMP indirect. This feature of this technique is also illustrated in the accompanying program, in the PRINT.MESSAGE subroutine. The use of internal data blocks is something not normally possible in a relocatable routine, but it can be done if the techniques shown here are used. This method of performing internal JSRs and JMPs in a relocatable routine may be simplified if the routine is intended to function as a subroutine appended to an Applesoft program. If the subroutine is appended using my utility the Routine Machine (available from Southwestern Data Systems), then it is not necessary to include the 47-byte Header Routine. Internal JMPs and JSRs can still be performed exactly as described above, except that the address of VECTOR must be $3F5-$3F7. This technique is not described in the documentation to the Routine Machine. A full explanation may be found in the Appendix to the documentation accompanying Ampersoft Program Library, Volume 4 (also available from Southwestern Data Systems). 1010 .TF B.MEYER.1 1020 *SAVE S.MEYER.1 1030 *-------------------------------- 1040 * SETUP AND HANDLER ROUTINES 1050 * TO ALLOW INTERNAL JSRS AND 1060 * JMPS IN A RELOCATABLE MACHINE 1070 * LANGUAGE ROUTINE 1080 1090 * BY PETER MEYER, 11/3/82 1100 *-------------------------------- 1110 * LOCATIONS 1120 1130 INDEX .EQ $5E,5F 1140 STACK .EQ $100 - $1FF 1150 VECTOR .EQ $3F5 - $3F7 1160 *-------------------------------- 1170 * MACRO DEFINITIONS 1180 1190 .MA JSR 1200 :1 LDA #]1-:1-7 1210 LDY /]1-:1-7 1220 TSX 1230 JSR VECTOR 1240 .EM 1250 1260 .MA JMP 1270 :1 LDA #]1-:1-7 1280 LDY /]1-:1-7 1290 TSX 1300 JSR $FF58 1310 JMP VECTOR 1320 .EM 1330 *-------------------------------- 1340 * HEADER PART 1 1350 1360 SETUP JSR $FF58 FIND OURSELVES 1370 TSX 1380 CLC 1390 LDA #HANDLER-SETUP-2 1400 .DA #$7D,STACK-1 FORCE ABS,X MODE 1410 STA VECTOR+1 1420 1430 LDA /HANDLER-SETUP-2 1440 ADC STACK,X 1450 STA VECTOR+2 1460 1470 LDA #$4C "JMP" 1480 STA VECTOR 1490 BNE MAIN.ROUTINE ALWAYS 1500 *-------------------------------- 1510 * HEADER PART 2 1520 1530 HANDLER 1540 1550 * ON ENTRY A,Y HOLD OFFSET 1560 * FOR JMP OR JSR FROM ROUTINE 1570 * X IS STACK POINTER FROM BEFORE LAST JSR 1580 1590 CLC 1600 .DA #$7D,STACK-1 FORCE ABS,X MODE 1610 STA INDEX 1620 TYA 1630 ADC STACK,X 1640 STA INDEX+1 1650 JMP (INDEX) 1660 *-------------------------------- 1670 * MAIN ROUTINE, FOR EXAMPLE 1680 *-------------------------------- 1690 MSG .EQ $06 AND $07 1700 CH .EQ $24 1710 CV .EQ $25 1720 INVFLG .EQ $32 1730 COUNT .EQ $3C 1740 SETTXT .EQ $FB39 1750 VTABZ .EQ $FC24 1760 HOME .EQ $FC58 1770 COUT .EQ $FDED 1780 *-------------------------------- 1790 MAIN.ROUTINE 1800 JSR SETTXT 1810 JSR HOME 1820 MAIN.LOOP 1830 LDA #190 1840 STA COUNT 1850 .1 LDA #AALQT-PRINT.MESSAGE 1860 STA MSG 1870 LDA /AALQT-PRINT.MESSAGE 1880 STA MSG+1 1890 >JSR PRINT.MESSAGE 1900 DEC COUNT 1910 BNE .1 1920 LDA #LONGQT-PRINT.MESSAGE 1930 STA MSG 1940 LDA /LONGQT-PRINT.MESSAGE 1950 STA MSG+1 1960 >JSR PRINT.MESSAGE 1970 >JMP FORWRD 1980 1990 *-------------------------------- 2000 PRINT.MESSAGE 2010 CLC 2020 LDA MSG CHANGE RELATIVE ADDRESS TO 2030 ADC INDEX AN ABSOLUTE ADDRESS, BY 2040 STA MSG ADDING THE OFFSET 2050 LDA MSG+1 2060 ADC INDEX+1 2070 STA MSG+1 2080 LDY #0 POINT AT FIRST CHAR OF MSG 2090 .1 LDA (MSG),Y GET NEXT CHAR OF MSG 2100 BMI .2 IT IS LAST CHAR 2110 ORA #$80 MAKE APPLE VIDEO FORM 2120 JSR COUT PRINT IT 2130 INY ADVANCE POINTER 2140 BNE .1 ...ALWAYS 2150 .2 JMP COUT PRINT AND RETURN 2160 *-------------------------------- 2170 * 256 BYTES TO JUMP OVER, JUST FOR ILLUSTRATION 2180 2190 .BS $100 2200 *-------------------------------- 2210 * TOGGLE INVERSE FLAG, AND HOME CURSOR 2220 2230 FORWRD LDA INVFLG 2240 EOR #$C0 2250 STA INVFLG 2260 LDA #0 2270 STA CH 2280 STA CV 2290 JSR VTABZ 2300 >JMP MAIN.LOOP 2310 *-------------------------------- 2320 AALQT .AT /AAL / 2330 LONGQT .HS 0D0D 2340 .AS / A P P L E A S S E M B L Y L I N E / 2350 .HS 0D02 2360 .AT / S - C S O F T W A R E C O R P . / S-C Macro Assembler (the best there is!)...........................$80.00 S-C Macro Cross Assembler Modules 65C02 Version..................................................$20.00 6800/6801/6802 Version.........................................$32.50 6809 Version...................................................$32.50 Z-80 Version...................................................$32.50 68000 Version..................................................$50.00 Requires ownership of S-C Macro Assembler. Each disk includes regular and language card versions. Upgrade from Version 4.0 to MACRO..................................$27.50 Source code of Version 4.0 on disk.................................$95.00 Fully commented, easy to understand and modify to your own tastes. Applesoft Source Code on Disk......................................$50.00 Very heavily commented. Requires Applesoft and S-C Assembler. ES-CAPE: Extended S-C Applesoft Program Editor....................$60.00 AAL Quarterly Disks...........................................each $15.00 Each disk contains all the source code from three issues of "Apple Assembly Line", to save you lots of typing and testing time. QD#1: Oct-Dec 1980 QD#2: Jan-Mar 1981 QD#3: Apr-Jun 1981 QD#4: Jul-Sep 1981 QD#5: Oct-Dec 1981 QD#6: Jan-Mar 1982 QD#7: Apr-Jun 1982 QD#8: Jul-Sep 1982 QD#9: Oct-Dec 1982 Double Precision Floating Point for Applesoft......................$50.00 Provides 21-digit precision for Applesoft programs. Includes sample Applesoft subroutines for standard math functions. FLASH! Integer BASIC Compiler (Laumer Research)......(regular $79) $49.00 Special price to AAL readers only, until 12/31/82! Source Code for FLASH! Runtime Package.............................$39.00 Super Disk Copy III (Sensible Software).............(reg. $30.00) $27.00 Amper-Magic (Anthro-Digital)........................(reg. $75.00) $67.50 Quick-Trace (Anthro-Digital)........................(reg. $50.00) $45.00 Cross-Reference and Dis-Assembler (Rak-Ware).......................$45.00 Apple White Line Trace (Lone Star Industrial Computing)............$50.00 (A unique learning tool) Blank Diskettes (with hub rings).................package of 20 for $50.00 Small 3-ring binder with 10 vinyl disk pages and disks.............$36.00 Vinyl disk pages, 6"x8.5", hold one disk each................10 for $4.50 Reload your own NEC PC-8023 ribbon cartridges...........each ribbon $5.00 Diskette Mailing Protectors.........................10-99: 40 cents each 100 or more: 25 cents each Ashby Shift-Key Mod................................................$15.00 Paymar Lower-Case Adapter..........................................$37.50 For Apples before Revision 7 only Lower-Case Display Encoder ROM.....................................$25.00 Works only Revision level 7 Apples. Replaces the encoder ROM. Books, Books, Books..........................compare our discount prices! "Enhancing Your Apple II, vol. 1", Lancaster.........($15.95) $15.00 "Incredible Secret Money Machine", Lancaster..........($7.95) $7.50 "Micro Cookbook, vol. 1", Lancaster..................($15.95) $15.00 "Beneath Apple DOS", Worth & Lechner.................($19.95) $18.00 "Bag of Tricks", Worth & Lechner, with diskette......($39.95) $36.00 "Apple Graphics & Arcade Game Design", Stanton.......($19.95) $18.00 "Assembly Lines: The Book", Roger Wagner.............($19.95) $18.00 "What's Where in the Apple", Second Edition..........($24.95) $23.00 "6502 Assembly Language Programming", Leventhal......($16.99) $16.00 "6502 Subroutines", Leventhal........................($12.99) $12.00 "MICRO on the Apple--1", includes diskette...........($24.95) $23.00 "MICRO on the Apple--2", includes diskette...........($24.95) $23.00 "MICRO on the Apple--3", includes diskette...........($24.95) $23.00 *** S-C SOFTWARE, P. O. BOX 280300, Dallas, TX 75228 *** *** (214) 324-2050 *** *** We take Master Charge, VISA and American Express *** Add Bit-Control to Apple Monitor...........Bob Sander-Cederlof -------------------------------------------------------------- The other day someone sent me a disk with an article for AAL on it as a binary file. The codes in the file were all ASCII characters, but they were nevertheless not compatible with any word processors I had around. All blanks were coded as $A0 (hi-bit on), and all other characters were coded in the range $00-$7F (hi-bit off). Otherwise, everything was compatible with my favorite word processor (the one I am still in the process of finishing). I need to have all the hi-bits set to one in the file, or in the memory image after BLOADing the file. That's the motivation for the following neat enhancement to the Apple monitor. The enhancement hooks in through the control-Y user command vector. By merely typing: *80FF<2000.3FFF^Y (^Y means control-Y) I set all the hi-bits between $2000 and $3FFF. The "80FF" in the command line above is the magic part of this enhancement. The last two digits are ANDed with every byte in the specified range, clearing every bit which is zero in those two digits. By using $FF, no bits are cleared. Other values for these two digits will clear whatever bits you wish. The first two digits are ORed into every byte in the specified range, setting every bit which is one in the two digits. $80 in my example sets the top bit in every byte. The code is designed to be BRUN from a binary file, and it is completely relocatable. You can BRUN it anywhere in memory that you have room for 36 bytes. That is why the SETUP code is longer than the actual control-Y code! The SETUP routine first discovers where in memory it is running, and then sets up the control-Y vector in page 3 to point at the BITS code. The discovery is done in the usual way, by JSRing to a guaranteed RTS in the monitor ROM, at $FF58. This leaves a return address just below the stack pointer. I pick up that address and add the difference between that and BITS to get the appropriate control-Y vector pointer. Line 1200 needs a little explanation. My assembler automatically switches to page zero addressing mode if the address is less than $100. STACK-1 is less than $100, so "ADC STACK-1,X" would assemble as though I wrote "ADC $FF,X". Indexed addressing in page zero mode stays in page zero, wrapping around. If X=3, "ADC $FF,X" would reference location $02 in page zero rather than $102. Therefore I had to use the ".DA #$7D" to force the assembler to use a full 16-bit address mode. (Some assemblers have a special way of forcing 16-bit addressing in cases like this; others require special marks to get zero-page modes.) BITS itself is very straightforward code. The monitor leaves the starting address of the specified range in A1 ($3C,3D), the ending address in A2 ($3E,3F), and the mask in A4 ($42,43). The subroutine at $FCBA increments A1 and compares it to A2, leaving carry clear if the range is not yet complete. 1000 *-------------------------------- 1010 * MONITOR CTRL-Y COMMAND 1020 * 1030 * TO SET AND CLEAR ANY COMBINATION 1040 * OF BITS IN A RANGE OF MEMORY 1050 * 1060 * *MASK "" THEN 1005 1025 PRINT 1030 RETURN Call SPLIT with three parameters. The first (A$ above) is the source string, which will be split. After SPLITting, the remainder string will be left in A$. The second parameter, B$ above, will receive the left part, including the last complete word, up to N (the 3rd parameter) characters. If there is no space in the left N characters, exactly N characters will be split. Here are some of the printouts from the test program: N=5 N=11 N=20 ----- ----------- -------------------- NOW NOW IS THE NOW IS THE TIME FOR IS TIME FOR ALL GOOD MEN TO COME THE ALL GOOD TO THE AID OF THEIR TIME MEN TO COME PARTY. ...etc. ...etc. 1000 *SAVE S.SPLIT 1010 *-------------------------------- 1020 * & SPLIT,A$,B$,W 1030 * 1040 * A$ -- SOURCE STRING 1050 * W -- MAXIMUM WIDTH OF SPLIT 1060 * 1070 * B$ -- LEFT W CHARS OF A$ 1080 * A$ -- REST OF A$ 1090 * 1100 *-------------------------------- 1110 .OR $300 1120 .TF B.SPLIT 1130 *-------------------------------- 1140 LINNUM .EQ $50,51 1150 DPTRA .EQ $06,07 1160 DPTRB .EQ $08,09 1170 SPTRA .EQ $FE,FF 1180 *-------------------------------- 1190 AS.CHKCOM .EQ $DEBE 1200 AS.PTRGET .EQ $DFE3 1210 AS.GETADR .EQ $E752 1220 AS.FRMNUM .EQ $DD67 1230 *-------------------------------- 1240 SPLIT JSR AS.CHKCOM GET COMMA 1250 JSR AS.PTRGET GET SOURCE STRING 1260 STA DPTRA 1270 STY DPTRA+1 1280 JSR AS.CHKCOM ANOTHER COMMA 1290 JSR AS.PTRGET GET TARGET STRING 1300 STA DPTRB 1310 STY DPTRB+1 1320 JSR AS.CHKCOM ANOTHER COMMA 1330 JSR AS.FRMNUM 1340 JSR AS.GETADR GET MAXIMUM WIDTH 1350 LDY #2 1360 LDA (DPTRA),Y 1370 STA SPTRA+1 1380 STA (DPTRB),Y 1390 DEY 1400 LDA (DPTRA),Y 1410 STA SPTRA 1420 STA (DPTRB),Y 1430 DEY 1440 LDA LINNUM 1450 CMP (DPTRA),Y 1460 BCC .1 1470 LDA (DPTRA),Y A$ SHORTER THAN OR SAME AS W 1480 STA (DPTRB),Y 1490 LDA #0 1500 STA (DPTRA),Y 1510 RTS 1520 *-------------------------------- 1530 .1 TAY 1540 .2 LDA (SPTRA),Y LOOK AT SPLIT BOUNDARY 1550 CMP #$20 FOR A BLANK 1560 BEQ .3 FOUND ONE 1570 DEY 1580 BNE .2 BACK UP THE SPLIT 1590 *---NO BLANK IN W CHARS---------- 1600 LDA LINNUM 1610 BNE .4 ...ALWAYS 1620 *-------------------------------- 1630 .3 TYA 1640 INY SKIP OVER BLANK 1650 STY LINNUM 1660 .4 LDY #0 LENGTH OF B$ 1670 STA (DPTRB),Y 1680 SEC 1690 LDA (DPTRA),Y LENGTH OF A$ 1700 SBC LINNUM 1710 STA (DPTRA),Y 1720 INY 1730 CLC 1740 LDA (DPTRA),Y 1750 ADC LINNUM 1760 STA (DPTRA),Y 1770 INY 1780 LDA (DPTRA),Y 1790 ADC #0 1800 STA (DPTRA),Y 1810 RTS 1820 *-------------------------------- Enhancing Your Apple II (A Review)..................Bill Morgan --------------------------------------------------------------- Don Lancaster, the well-known author of electronics books for the hobbyist (and a subscriber to AAL), has now entered the Apple arena in a big way. His latest book, "Enhancing Your Apple II, Vol. 1", promises to be the start of a long series of easy-to-use guides to the important internal workings of the Apple. The main enhancements he offers in this volume are simple modifications to the Apple's video circuitry, to allow EXACT software access to the video timing. This permits your program to play all sorts of tricks with the display modes. There is also a wealth of information on the Apple's techniques of video storage and output. The basic hardware modification is a single wire from an IC in the video circuitry to either the cassette or the game input. With this wire and a little bit of code, it is easy to switch display modes between screen scans, avoiding a lot of messy glitches on the screen. With more code, and careful timing, you can lock the processor to the display timing and switch between text and graphic modes (hi-res or lo-res) in mid-line. There is also a very good 60-page chapter on disassembling and understanding other people's programs. Don presents a novel technique of color-coding a printout of a monitor disassembly, to bring out the structure of a program and the function of each routine. The example program is Apple's High-Res Character Generator, from the DOS Toolkit. He later uses the information discovered about the character generator and the Hi-Res display to develop a slower and smoother scrolling routine for Hi-Res text. He shows us other enhancements, as well. There are two different ways to attach a modulator's output line to your TV set, avoiding that clumsy little switch box that the manufacture gives us. How about a programmable color-killer circuit? With this one you can have software control of color vs. black-and-white display. There are sections about generating extra colors, in both Hi-Res and Lo-Res graphics. In the back of the book are postcards for sending feedback and ordering other materials. All the code in the book (26 programs) can be ordered on diskette, for $14.95. He uses the DOS Toolkit Assembler, but we plan to talk to him about providing the programs in S-C format. You can also order a kit of the parts for all of the hardware modifications he describes. That kit costs only $11.95 + shipping, from a dealer in Oklahoma. Future plans include more volumes of enhancements and a possible bulletin board system for updates to the books. All in all, "Enhancing Your Apple II" looks to be an important and useful book. Like all of Lancaster's books, it is published by Howard W. Sams. It is 232 pages long, size 8 1/2 X 11 inches, and sells for $15.95. We have ordered a stock here at S-C, and will sell them for $15.00 + postage. For Volume 2 of the "Enhancing" series, he has promised us more video techniques, a keyboard enhancer, something called an "Adventure Emergency Toolkit", graphics software for daisy-wheel printers, a two-dollar interface for the BSR controller, and much more. I'm looking forward to it! This is a good time to mention another of Don's books, which has received too little attention. I am speaking of "The Incredible Secret Money Machine". Despite the title, it is not a get-rich-quick pamphlet, but rather a very, very useful guide to starting and operating a free-lance technical or craft business. "Money Machine" is 160 pages of tightly packed information on strategy and tactics, getting started, and dealing with customers, suppliers, and the government. There is enough practical advice on communication, both verbal and graphic, to make up several courses in advertising and technical writing. Bob and I refer to this book regularly, and have long felt that it is one of the best books around for the budding entrepeneur. We have also ordered "Money Machine", and will sell it for $7.50 + postage. Last minute addition: We just received a review copy of another new book from Don Lancaster, Micro Cookbook Vol. 1 - Fundamentals. This one is a very basic introduction to microcomputer principles. He talks about how to learn and what to learn, and introduces some hardware fundamentals. He also promises Vol. 2, about Machine-Language Programming. It looks very good; I'll have more details next month. We especially like this sentence at the end of the Preface: This book is dedicated to the 6502. Quickie No. 4..............................Bob Sander-Cederlof -------------------------------------------------------------- To print a two byte value in hexadecimal: LDA HI.BYTE LDX LO.BYTE JSR $F941 Clarification on Loading the RAM Card...........Paul Schlyter ------------------------------------------------------------- Last month Bob S-C told how to use an EXEC command file without ENDing an Applesoft program. His example may have obfuscated the process of loading a file into a RAM card, because it really is not necessary to use an EXEC file for this purpose. You can BLOAD into the RAM card without leaving Applesoft, contrary to Bob's information, by merely write-enabling it. The soft-switches $C081 and $C089 write-enable the RAM card (with bank 2 or bank 1 at $D000, respectively), leaving the motherboard ROMs read-enabled. This means everything you write goes into the RAM card, and everything you read comes from the motherboard ROMs. Thus you can simply BLOAD into the RAM card, and BLOAD will write to those addresses. Here is a short program that loads the whole 16K RAM card, all from within a running Applesoft program, without EXEC files. 100 D$ = CHR$ (4) 110 B2 = 49281 : REM $C081 -- SELECT BANK TWO 120 B1 = 49289 : REM $C089 -- SELECT BANK ONE 130 P = PEEK(B2) + PEEK(B2) : REM WRITE ENABLE BANK TWO 140 PRINT D$"BLOAD LC.BANK 2" 150 P = PEEK(B1) + PEEK(B1) : REM WRITE ENABLE BANK ONE 160 PRINT D$"BLOAD LC.BANK 1" [ Note from Bob S-C: My face is red! Paul will note that I modified his program above in lines 130 and 150. He wrote "130 POKE B2, PEEK(B2)" and similarly for line 150. However, some RAM cards, such as my Andromeda board, will disable write-enable if the soft-switches are addressed during a write-cycle. The POKE does just that; therefore, I changed 130 and 150 to do two PEEKs in a row. Further, I recall when working with a Corvus drive last year that BLOADing from a Corvus into the RAM card did not work unless a monitor had already been copied into the space from $F800-$FFFF. ]