In This Issue...
Mailing AAL
Let's review how AAL is mailed, when you should expect to receive it, and what to do about it when you don't. Most of you get your newletter by Bulk Mail, which is a little erratic. You should receive your issue around the third week of each month, but don't start worrying until the end of the month. If you haven't received an issue by the end of the month, call or write and we'll send a replacement. The Post Office does not forward Bulk Mail, so make certain to tell us if you move. Those of you who have First Class Mail subscriptions should receive your issue around the tenth of the month, and certainly before the twentieth.
The number in the upper right corner of your mailing label is the expiration date of your subscription. If that number is 8308, you're holding your last issue and better renew now. We send out postcards when your subscription is about to expire, and when it has expired. All you have to do is send us a check, or phone with a charge card number, and we'll keep your AAL coming.
When I bought my Apple //e (3 days after they became available!), I also got the Extended 80-Column Text Card. I wanted it both to have 80 column text capability and a full complement of Apple Computer Inc. supported memory. However, Apple only supplied two small subroutines in ROM and incomplete (but otherwise excellent) documentation in their manuals, in "support" of the auxiliary memory.
I say "incomplete" because two I/O locations that I used in my program are not mentioned (in English anyway) anywhere in the manuals except in the listings of the 80-column firmware. The two I/O locations are $C011 & $C012 which I call READ.BSR.BANK & READ.BSR.RAM.READ. Apple evidently intends to let software developers determine how the auxiliary memory is to be used.
Well here goes: my program is called "USE.AUXMEM". This program allows you to access the "other" 64K in a manner most Apple users should already be familiar with: monitor commands.
The simplest way to see what I mean is to type in & assemble the program (not so simple), type :"MGO G", :"PR#3" and then :"$^Y" (that is control-Y). You will get a bell and the monitor's prompt. Any monitor commands you type now will "use" the auxiliary memory. Try these now:
*3D0:55 *3D0 (double nickels, right?) *^Y (back to SCASM!) :$3D0 (a $4C!)
You should note that control-Y while using the auxiliary memory returns to main memory with everything as it was. Now try these:
:$^Y 3D0 *3D0 ^Y
After the second control-Y returned to main memory, SCASM finished the first command line!
The reason I had you type :"PR#3" before is quite simple: things don't all work right without the 80 column firmware active; specifically, right-arrow & escape functions. You can also type "escape 4" if you don't want 80 columns.
But wait a minute, if you read the 80-column firmware listing (carefully), you know that it does NOT work with the auxiliary memory enabled (as doesn't the regular 40-column firmware), so how is this all working? Well, the I/O hooks in the auxiliary memory zero page point to routines in USE.AUXMEM which switch to main memory, perform the I/O, switch back to auxiliary memory, and return to the monitor. The monitor executes its commands between I/O calls while auxiliary memory is enabled. These switchings also change the bank switched memory state.
The USE.AUXMEM program has two other control-Y commands. They implement the crossbank subroutines AUXMOVE & XFER (supplied in ROM) as monitor commands. See the comments at the top of the source listing for their syntax.
About Some //e Monitor Bugs...
One routine, USE.AUXMEM.CONTROL.Y.HANDLER, deserves a special note. It compensates for a bug in the Apple //e version of the monitor: when parsing a control-Y command the ASCII string "Bryan" at $FEC5 is executed as instructions prior to JMPing to USRADR ($03F8). This bug has a long history.
In the original Apple monitor the CHRSRCH loop ($FF78 - $FF81) scans the CHRTBL ($FFCC - $FFE2) from end to beginning, which matches the $B2 at $FFCD causing TOSUB ($FFBE - $FFCB) to load the $C9 at $FFE4 and RTS to USR ($FECA) which is a JMP USRADR ($03F8).
Things started to go astray when the autostart ROM was created, and the Apple II Plus. To make room for new features, (like printing "APPLE ][" at the top of the screen on power up, and like the escape-IJKM cursor motion), the TRACE and STEP commands were removed. To disable the entries for Trace and Step in CHRTBL, the bytes for "T" and "S" were changed: ($FFCF:B2 & $FFD2:B2, also $FFE9:C4). Locations $FEC5 - $FEC9, immediately prior to USR, were changed to NOPs.
Unfortunately, someone forgot that CHRTBL is searched from end to beginning, causing a control-Y command to be matched with the $B2 at $FFD2, corresponding to the branch address in SUBTBL at $FFE9. So when you type a control-Y command the monitor branches to $FFC5 and executes the 5 NOPs. If $FFE9 had been changed to $C9 instead of $C4, everything would have still been fine.
Executing 5 NOPs is not a bad bug. But when the Apple //e monitor was created those 5 NOPs were replaced by the string "Bryan". In hex it is C2 F2 F9 E1 EE. The 6502 instruction set does not include a definition for $C2, but after a little investigation, or after reading Bob Sander-Cederlof's article in AAL March 1981, you find out that $C2 acts like a two-byte NOP. The "r" is skipped over. The "yan", however, is a SBC $EEE1,Y instruction.
The USE.AUXMEM.CONTROL.Y.HANDLER uses the passed contents of the A & X registers to decide which of the three control-Y commands you've typed. The SBC $EEE1,Y changes the A register so its contents must be reconstructed. The reconstruction is further complicated by the fact that the monitor leaves the carry flag set when it RTS's to $FEC5, while the S-C Assembler and Mini-Assembler leave the carry flag clear.
To restore the A register to its proper value you must set the carry to the complement of the value that it was set to prior to the SBC $EEE1,Y then execute ADC $EEE1,Y.
The Apple //e 80 column firmware also contains a bug. Because of the $11 at $C92A, the key sequence "ESCape ^L" causes a RTS to $4CCE. Location $C92A should contain a $10. This bug can be used to advantage if you feel like adding a secret command to your own software. Just be certain you have the code for your command starting at $4CCE, and that you are running in 80-column mode. Then whenever you type control-L in the escape mode (cursor is an inverse plus) your code will be executed.
I hope all of you enjoy using your auxiliary memory as much as I do.
Last Minute Note: David just called to report yet another oddity in the //e ROMs. In 40-column ESCape mode the (, 5, *, and + keys duplicate the arrow keys. That is, "ESC 5" moves the cursor right one space, just like ESC right arrow. This is a little bit weird, but it doesn't seem to hurt anything. The effect is caused by an unnecessary AND #$DF instruction at $C26E.
1000 *SAVE JOHNSON'S USE AUXMEM 1010 *-------------------------------- 1020 * SWITCH.MIND Command: ^Y 1030 * 1040 * When in main bank, enters monitor in 1050 * auxmem BSR (hooks I/O through main 1060 * and brings USE.AUXMEM to auxmem too) 1070 * When in aux bank, returns to main bank 1080 * Best used w/80 column firmware active 1090 *-------------------------------- 1100 * USE.AUXMOVE Command: DEST<SOURCE.END^Y{CARRY} 1110 * 1120 * DEST = Destination in one bank 1130 * SOURCE = Start in other bank 1140 * END = End in other bank 1150 * CARRY = Direction of move 1160 * (1 = Main Ram-->Card Ram) 1170 * (0 = Card Ram-->Main Ram) 1180 * DEST, SOURCE, & END must be: >=$0200 & <=$BFFF 1190 *-------------------------------- 1200 * USE.XFER Command: ADDRESS^Y{CARRY}{OVERFLOW} 1210 * 1220 * ADDRESS = Transfer address 1230 * CARRY = Desired 48K Bank ($0200 - $BFFF) 1240 * (1 = Use 48K in Card Ram) 1250 * (0 = Use 48K in Main Ram) 1260 * OVERFLOW = Desired ZP/STK/BSR 1270 * (1 = Use ZP/STK/BSR in Card Ram) 1280 * (0 = Use ZP/STK/BSR in Main Ram) 1290 * If using USE.XFER from auxmem, routine in main mem 1300 * MUST LDX BANK.SP.SAVE, TXS if it uses the stack at all 1310 *-------------------------------- 1320 MON.BASL .EQ $28,$29 1330 MON.YSAV .EQ $34 1340 MON.CSWL .EQ $36,$37 1350 MON.KSWL .EQ $38,$39 1360 MON.A1 .EQ $3C,$3D Source,Address 1370 MON.A2 .EQ $3E,$3F End 1380 MON.A4 .EQ $42,$43 Dest 1390 MON.STATUS .EQ $48 1400 *-------------------------------- 1410 IN .EQ $0200 - $02FF 1420 BANK.X.SAVE .EQ $03CC 1430 BANK.BSR.BANK.SAVE .EQ $03CD 1440 BANK.BSR.RAM.READ.SAVE .EQ $03CE 1450 BANK.SP.SAVE .EQ $03CF 1460 TRANSFER .EQ $03ED,$03EE 1470 MON.BRKV .EQ $03F0,$03F1 1480 USRADR .EQ $03F8 - $03FA 1490 NMI .EQ $03FB - $03FD 1500 MON.IRQLOC .EQ $03FE,$03FF 1510 *-------------------------------- 1520 READ.MAIN.RAM .EQ $C002 1530 READ.AUX.RAM .EQ $C003 1540 WRITE.MAIN.RAM .EQ $C004 1550 WRITE.AUX.RAM .EQ $C005 1560 USE.MAIN.ZP.STK.BSR .EQ $C008 1570 USE.AUX.ZP.STK.BSR .EQ $C009 1580 READ.BSR.BANK .EQ $C011 1590 READ.BSR.RAM.READ .EQ $C012 1600 READ.RAM.READ.STATUS .EQ $C013 1610 READ.RAM.WRITE.STATUS .EQ $C014 1620 READ.ZP.STK.BSR.STATUS .EQ $C016 1630 BSR.2.RAM.READ.ONLY .EQ $C080 1640 BSR.2.ROM.READ.RAM.WRITE .EQ $C081 1650 BSR.2.ROM.READ.ONLY .EQ $C082 1660 BSR.2.RAM.READ.RAM.WRITE .EQ $C083 1670 BSR.1.RAM.READ.ONLY .EQ $C088 1680 BSR.1.ROM.READ.RAM.WRITE .EQ $C089 1690 BSR.1.ROM.READ.ONLY .EQ $C08A 1700 BSR.1.RAM.READ.RAM.WRITE .EQ $C08B 1710 *-------------------------------- 1720 AUXMOVE .EQ $C311 1730 XFER .EQ $C314 1740 MONITOR .EQ $F800 - $FFFF 1750 MON.OLDBRK .EQ $FA59 1760 BEEP .EQ $FBDD 1770 MON.RDKEY .EQ $FD0C 1780 MON.JSR.CLREOL .EQ $FD8B - $FD8D 1790 MON.COUT .EQ $FDED 1800 MON .EQ $FF65 1810 *-------------------------------- 1820 .OR $0803 1830 USE.AUXMEM 1840 G 1850 JMP CONNECT.CONTROL.Y 1860 JMP.TO.RETURN.TO.MAIN 1870 JMP RETURN.TO.MAIN 1880 JMP.TO.RETURN.TO.AUX 1890 JMP RETURN.TO.AUX 1900 JMP.TO.SAVE.BSR.STATE 1910 JMP SAVE.BSR.STATE 1920 JMP.TO.RESTORE.BSR.STATE 1930 JMP RESTORE.BSR.STATE 1940 *-------------------------------- 1950 CONNECT.CONTROL.Y 1960 LDA /USE.AUXMEM.CONTROL.Y.HANDLER 1970 STA USRADR+2 1980 LDA #USE.AUXMEM.CONTROL.Y.HANDLER 1990 STA USRADR+1 2000 LDA #$4C JMP 2010 STA USRADR 2020 RTS 2030 *-------------------------------- 2040 USE.AUXMEM.CONTROL.Y.HANDLER 2050 * Reconstruct monitor mode byte 2060 * after "Bryan" messed with it 2070 * ("Br" is NOPish) 2080 PHA 2090 LDA IN 2100 CMP #"$" 2110 * Branch w/Carry set causa S-C or Mini-Asm 2120 BEQ .1 2130 CLC 2140 .1 PLA 2150 * These lines are for you Bryan 2160 .DA #'y' 2170 .AS -'an' Builds SBC $EEE1,Y 2180 * Check for user specified address 2190 CPX #$01 2200 BNE SWITCH.MIND 2210 TAY 2220 * Lesser complex is USE.XFER 2230 BEQ USE.XFER 2240 * Most complex is USE.AUXMOVE 2250 *-------------------------------- 2260 USE.AUXMOVE 2270 * Fetch what should be a "0" 2280 * or "1" to be AUXMOVE's carry 2290 LDY MON.YSAV 2300 LDA IN,Y 2310 * Shift what we fetched to carry 2320 LSR 2330 * Save carry while comparing 2340 PHP 2350 * This is a "0" or "1" after a LSR 2360 CMP #"0"/2 2370 BNE INVALID.CARRY 2380 INC MON.YSAV 2390 * Recover Carry 2400 PLP 2410 CALL.AUXMOVE.WITH.CARRY 2420 JSR AUXMOVE 2430 RTS 2440 *-------------------------------- 2450 USE.XFER 2460 * Set XFER Transfer address 2470 * from monitor parameter 2480 LDA MON.A1,X 2490 STA TRANSFER,X 2500 DEX 2510 BPL USE.XFER 2520 * Fetch what should be a "0" 2530 * or "1" to be XFER's carry 2540 LDY MON.YSAV 2550 LDA IN,Y 2560 * Shift what we fetched to carry 2570 LSR 2580 * Save carry for a while 2590 PHP 2600 * This is a "0" or "1" after a LSR 2610 CMP #"0"/2 2620 BNE INVALID.CARRY 2630 INC MON.YSAV 2640 * Fetch what should be a "0" 2650 * or a "1" to be XFER's overflow 2660 INY 2670 LDA IN,Y 2680 * Shift what we fetched to carry 2690 LSR 2700 * Save this carry too, while we compare 2710 PHP 2720 * This is a "0" or "1" after a LSR 2730 CMP #"0"/2 2740 BNE INVALID.OVERFLOW 2750 INC MON.YSAV 2760 * Recovered carry is valid overflow 2770 PLP 2780 * Move it back to bit 0 2790 ROL 2800 * Recover carry 2810 PLP 2820 * Construct overflow 2830 CLV 2840 AND #%0000.0001 2850 BEQ .1 2860 BIT SEV 2870 * Save BSR bank, BSR ram read, and SP 2880 * for any calls or returns to main/auxmem 2890 .1 JSR SAVE.BSR.STATE 2900 TSX 2910 STX BANK.SP.SAVE 2920 JMP.XFER.WITH.CARRY.AND.OVERFLOW 2930 * Routines in aux/main bank may jmp 2940 * to RETURN.TO.MAIN/AUX when done 2950 SEV JMP XFER 2960 *-------------------------------- 2970 INVALID.OVERFLOW 2980 PLP 2990 INVALID.CARRY 3000 PLP 3010 * Let's not process rest of line 3020 LDY MON.YSAV 3030 LDA #$8D 3040 STA IN,Y 3050 JMP BEEP 3060 *-------------------------------- 3070 SWITCH.MIND 3080 * Check in main or aux now 3090 LDA READ.RAM.READ.STATUS 3100 BPL ENTER.AUX.MON 3110 JMP RETURN.TO.MAIN 3120 ENTER.AUX.MON 3130 * Move USE.AUXMEM to auxmem too 3140 LDA #USE.AUXMEM 3150 STA MON.A1 3160 STA MON.A4 3170 LDA /USE.AUXMEM 3180 STA MON.A1+1 3190 STA MON.A4+1 3200 LDA #USE.AUXMEM.END 3210 STA MON.A2 3220 LDA /USE.AUXMEM.END 3230 STA MON.A2+1 3240 SEC 3250 JSR AUXMOVE 3260 * Save BSR bank, BSR ram read, and SP 3270 * for calls and return to main mem 3280 JSR SAVE.BSR.STATE 3290 TSX 3300 STX BANK.SP.SAVE 3310 * Continue in auxmem w/rom 3320 STA READ.AUX.RAM 3330 STA WRITE.AUX.RAM 3340 STA USE.AUX.ZP.STK.BSR 3350 LDA BSR.2.ROM.READ.RAM.WRITE 3360 LDA BSR.2.ROM.READ.RAM.WRITE 3370 * What else but this too 3380 LDX #$FF 3390 TXS 3400 * Copy rom monitor to auxmem BSR 3410 LDY #MONITOR 3420 STY MON.A1 3430 STY MON.STATUS 3440 LDA /MONITOR 3450 STA MON.A1+1 3460 .1 LDA (MON.A1),Y 3470 STA (MON.A1),Y 3480 INY 3490 BNE .1 3500 INC MON.A1+1 3510 BNE .1 3520 * Now use auxmem BSR 3530 LDA BSR.2.RAM.READ.RAM.WRITE 3540 LDA BSR.2.RAM.READ.RAM.WRITE 3550 * Fix monitor in BSR 3560 LDA /DO.CLREOL 3570 STA MON.JSR.CLREOL+2 3580 LDA #DO.CLREOL 3590 STA MON.JSR.CLREOL+1 3600 * Hook I/O through main 3610 LDA #COUT.TO.MAIN 3620 STA MON.CSWL 3630 LDA #RDKEY.FROM.MAIN 3640 STA MON.KSWL 3650 LDA /COUT.TO.MAIN 3660 STA MON.CSWL+1 3670 * LDA /RDKEY.FROM.MAIN 3680 STA MON.KSWL+1 3690 * USE.AUXMEM in auxmem too 3700 JSR CONNECT.CONTROL.Y 3710 * Do page 3 locs 3720 STA NMI 3730 LDA #MON 3740 STA NMI+1 3750 STA MON.IRQLOC 3760 LDA /MON 3770 STA NMI+2 3780 STA MON.IRQLOC+1 3790 LDA #MON.OLDBRK 3800 STA MON.BRKV 3810 LDA /MON.OLDBRK 3820 STA MON.BRKV+1 3830 * Enter monitor in auxmem BSR 3840 JMP MON 3850 *-------------------------------- 3860 RETURN.TO.AUX 3870 * Continue in aux ram 3880 STA READ.AUX.RAM 3890 STA WRITE.AUX.RAM 3900 STA USE.AUX.ZP.STK.BSR 3910 JMP RETURN.COMMON 3920 RETURN.TO.MAIN 3930 * Continue in main ram 3940 STA READ.MAIN.RAM 3950 STA WRITE.MAIN.RAM 3960 STA USE.MAIN.ZP.STK.BSR 3970 RETURN.COMMON 3980 * Recover SP 3990 LDX BANK.SP.SAVE 4000 TXS 4010 RESTORE.BSR.STATE 4020 CLV 4030 LDX BANK.BSR.BANK.SAVE 4040 BPL .2 4050 LDX BANK.BSR.RAM.READ.SAVE 4060 BPL .1 4070 LDX BSR.2.RAM.READ.RAM.WRITE 4080 LDX BSR.2.RAM.READ.RAM.WRITE 4090 BVC .4 4100 .1 LDX BSR.2.ROM.READ.RAM.WRITE 4110 LDX BSR.2.ROM.READ.RAM.WRITE 4120 BVC .4 4130 .2 LDX BANK.BSR.RAM.READ.SAVE 4140 BPL .3 4150 LDX BSR.1.RAM.READ.RAM.WRITE 4160 LDX BSR.1.RAM.READ.RAM.WRITE 4170 BVC .4 4180 .3 LDX BSR.1.ROM.READ.RAM.WRITE 4190 LDX BSR.1.ROM.READ.RAM.WRITE 4200 .4 RTS 4210 *-------------------------------- 4220 SAVE.BSR.STATE 4230 LDX READ.BSR.BANK 4240 STX BANK.BSR.BANK.SAVE 4250 LDX READ.BSR.RAM.READ 4260 STX BANK.BSR.RAM.READ.SAVE 4270 RTS 4280 *-------------------------------- 4290 DO.CLREOL 4300 LDA #"]"-'@' 4310 COUT.TO.MAIN 4320 * Save auxmem's X 4330 STX BANK.X.SAVE 4340 * Save BSR bank, BSR ram read, and SP 4350 * over call to main ram 4360 JSR SAVE.BSR.STATE 4370 TSX 4380 STX BANK.SP.SAVE 4390 * Continue in main ram 4400 STA READ.MAIN.RAM 4410 STA WRITE.MAIN.RAM 4420 STA USE.MAIN.ZP.STK.BSR 4430 * Recover SP 4440 LDX BANK.SP.SAVE 4450 TXS 4460 JSR RESTORE.BSR.STATE 4470 JSR MON.COUT 4480 JMP IO.COMMON 4490 *-------------------------------- 4500 RDKEY.FROM.MAIN 4510 * Repair monitor's sillier attempt 4520 STA (MON.BASL),Y 4530 * Save auxmem's X 4540 STX BANK.X.SAVE 4550 * Save BSR bank, BSR ram read, and SP 4560 * over call to main ram 4570 JSR SAVE.BSR.STATE 4580 TSX 4590 STX BANK.SP.SAVE 4600 * Continue in main ram 4610 STA READ.MAIN.RAM 4620 STA WRITE.MAIN.RAM 4630 STA USE.MAIN.ZP.STK.BSR 4640 LDX BANK.SP.SAVE Recover SP 4650 TXS 4660 JSR RESTORE.BSR.STATE 4670 JSR MON.RDKEY 4680 *-------------------------------- 4690 IO.COMMON 4700 STA READ.AUX.RAM Continue in Aux RAM 4710 STA WRITE.AUX.RAM 4720 STA USE.AUX.ZP.STK.BSR 4730 LDX BANK.SP.SAVE Recover SP 4740 TXS 4750 JSR RESTORE.BSR.STATE 4760 LDX BANK.X.SAVE Recover X 4770 RTS 4780 *-------------------------------- 4790 USE.AUXMEM.END .EQ *-1 |
People who have started reading AAL since last December have asked what is all this 65C02 business, anyway? Well the 65C02 is a new CMOS version of the 6502 microprocessor. (CMOS stands for Complementary Metal Oxide Semiconductor. That's a different way of making chips. CMOS circuits are noted for extremely low power consumption and extremely high sensitivity to static electricity.) To us Apple owners, the important thing is that the designers of the new chip corrected the bugs in the 6502 and added several new instructions and addressing modes.
The new instructions include PHX, PLX, PHY, and PLY (push and pull the X and Y registers from the stack), BRA (branch always), STZ (store zero), TSB and TRB (test and set or reset bits), and SMB, RMB, BBR and BBS (set, reset and branch on single bits). The main new addressing mode is true indirect without indexing, LDA ($12). This mode is now available for ORA, AND, EOR, ADC, STA, LDA, CMP, and SBC. There are also new modes for the BIT and JMP instructions. INC and DEC can now work on the A register.
There are some problems, though. Rockwell, GTE, NCR, and Synertek (maybe) are manufacturing 65C02 processors, but they are not all the same. The SMB, RMB, BBS, and BBR instructions are only available in the Rockwell chip. The NCR chip works in the Apple //e, but not in older Apples. The GTE processor does work in all Apples (this is being written on an Apple ][+ with a GTE 65C02). I haven't yet received a sample of the Rockwell processor, so I don't personally know if it works in older Apples. Some people say yes, others no.
That's a summary of what we know so far. The confusion is beginning to clear up, but there are still questions about what will or won't work in which Apples, and why. Stay tuned...
Several have written to us about Roger Keating's Spiral Screen Clear (AAL June 1983). Charles Putney, who you may remember as the first one to double the speed of the prime number program in AAL several years ago, has now applied his talent to unwinding the screen.
Roger's program ran in 55 seconds, my table-lookup for BASCALC shortened it to 40 seconds. Charlie wrote the whole thing out as one long string of LDA-STA pairs, and trimmed the time to only 7 seconds!
Let's see...there are 960 characters on the screen. If I write a LDA-STA pair to move each byte ahead one position along the spiral path, I will have 959 such pairs. Each LDA and each STA will take 3 bytes, so the program to shift the whole screen one step around the spiral path will take 2x3x959 = 5754 bytes. Add another 5 bytes to LDA #$A0 and store it in the center of the screen before the first rotation. Then add some code to re- run the 959 steps 959 more times, so that the whole screen clears, and you get Charlie's program, 5777 bytes.
Now try to type it all in! Don't worry, we aren't even going to list it here. It will be on the next Quarterly disk, though.
Charlie decided to use five macros, to decrease the amount of manual labor involved. He defined a macro named MOVE which builds the LDA-STA pair for a pair of arguments:
.MA MOVE LDA ]1 STA ]2 .EM
Then he defined one macro for each leg of the spiral: MOVED, MOVEL, MOVEU, and MOVER for down, left, up, and right respec- tively. With a few comment lines, the macro definitions take a mere 488 lines! The macros are each called with three parameters:
>MOVED col,low.row,high.row >MOVEL row,low.col,high.col >MOVEU col,low.row,high.row >MOVER row,low.col,high.col
The definitions out of the way, it only remains to write 12 sets of 4 macro calls, or 48 lines, and a driving loop to do it all 960 times. Here is a condensed listing of the actual code part of Charlie's program:
1000 *SAVE S.PUTNEY'S SPIRAL 1010 * 1020 * 1030 * FAST SPIRAL SCREEN CLEAR 1040 * 1050 * CHARLES H. PUTNEY 1060 * 18 QUINNS ROAD 1070 * SHANKILL 1080 * CO. DUBLIN 1090 * IRELAND 1100 * 1110 * 1120 * 1130 * 1140 *-------------------------------- 1150 * 1160 * TEXT PAGE BASE ADDRESSES 1170 * 1180 * 1190 R0 .EQ $400 1200 R1 .EQ $480 1210 R2 .EQ $500 1220 R3 .EQ $580 1230 R4 .EQ $600 1240 R5 .EQ $680 1250 R6 .EQ $700 1260 R7 .EQ $780 1270 R8 .EQ $428 1280 R9 .EQ $4A8 1290 R10 .EQ $528 1300 R11 .EQ $5A8 1310 R12 .EQ $628 1320 R13 .EQ $6A8 1330 R14 .EQ $728 1340 R15 .EQ $7A8 1350 R16 .EQ $450 1360 R17 .EQ $4D0 1370 R18 .EQ $550 1380 R19 .EQ $5D0 1390 R20 .EQ $650 1400 R21 .EQ $6D0 1410 R22 .EQ $750 1420 R23 .EQ $7D0 1430 * 1440 * 1450 *-------------------------------- 1460 * 1470 * MACRO DEFINITIONS 1480 * 1490 * 1500 .MA MOVE 1510 LDA ]1 1520 STA ]2 1530 .EM 1540 * 1550 * 1560 * 1570 .MA MOVER MOVE RIGHT ROW,COLLOW,COLHIGH FROM 0-39 1580 .DO ]3>]2 1590 >MOVE ]1+]3-1,]1+]3 1600 .FIN 1610 .DO ]3-1>]2 1620 >MOVE ]1+]3-2,]1+]3-1 1630 .FIN 1640 .DO ]3-2>]2 1650 >MOVE ]1+]3-3,]1+]3-2 1660 .FIN 1670 .DO ]3-3>]2 1680 >MOVE ]1+]3-4,]1+]3-3 1690 .FIN 1700 .DO ]3-4>]2 1710 >MOVE ]1+]3-5,]1+]3-4 1720 .FIN 1730 .DO ]3-5>]2 1740 >MOVE ]1+]3-6,]1+]3-5 1750 .FIN 1760 .DO ]3-6>]2 1770 >MOVE ]1+]3-7,]1+]3-6 1780 .FIN 1790 .DO ]3-7>]2 1800 >MOVE ]1+]3-8,]1+]3-7 1810 .FIN 1820 .DO ]3-8>]2 1830 >MOVE ]1+]3-9,]1+]3-8 1840 .FIN 1850 .DO ]3-9>]2 1860 >MOVE ]1+]3-10,]1+]3-9 1870 .FIN 1880 .DO ]3-10>]2 1890 >MOVE ]1+]3-11,]1+]3-10 1900 .FIN 1910 .DO ]3-11>]2 1920 >MOVE ]1+]3-12,]1+]3-11 1930 .FIN 1940 .DO ]3-12>]2 1950 >MOVE ]1+]3-13,]1+]3-12 1960 .FIN 1970 .DO ]3-13>]2 1980 >MOVE ]1+]3-14,]1+]3-13 1990 .FIN 2000 .DO ]3-14>]2 2010 >MOVE ]1+]3-15,]1+]3-14 2020 .FIN 2030 .DO ]3-15>]2 2040 >MOVE ]1+]3-16,]1+]3-15 2050 .FIN 2060 .DO ]3-16>]2 2070 >MOVE ]1+]3-17,]1+]3-16 2080 .FIN 2090 .DO ]3-17>]2 2100 >MOVE ]1+]3-18,]1+]3-17 2110 .FIN 2120 .DO ]3-18>]2 2130 >MOVE ]1+]3-19,]1+]3-18 2140 .FIN 2150 .DO ]3-19>]2 2160 >MOVE ]1+]3-20,]1+]3-19 2170 .FIN 2180 .DO ]3-20>]2 2190 >MOVE ]1+]3-21,]1+]3-20 2200 .FIN 2210 .DO ]3-21>]2 2220 >MOVE ]1+]3-22,]1+]3-21 2230 .FIN 2240 .DO ]3-22>]2 2250 >MOVE ]1+]3-23,]1+]3-22 2260 .FIN 2270 .DO ]3-23>]2 2280 >MOVE ]1+]3-24,]1+]3-23 2290 .FIN 2300 .DO ]3-24>]2 2310 >MOVE ]1+]3-25,]1+]3-24 2320 .FIN 2330 .DO ]3-25>]2 2340 >MOVE ]1+]3-26,]1+]3-25 2350 .FIN 2360 .DO ]3-26>]2 2370 >MOVE ]1+]3-27,]1+]3-26 2380 .FIN 2390 .DO ]3-27>]2 2400 >MOVE ]1+]3-28,]1+]3-27 2410 .FIN 2420 .DO ]3-28>]2 2430 >MOVE ]1+]3-29,]1+]3-28 2440 .FIN 2450 .DO ]3-29>]2 2460 >MOVE ]1+]3-30,]1+]3-29 2470 .FIN 2480 .DO ]3-30>]2 2490 >MOVE ]1+]3-31,]1+]3-30 2500 .FIN 2510 .DO ]3-31>]2 2520 >MOVE ]1+]3-32,]1+]3-31 2530 .FIN 2540 .DO ]3-32>]2 2550 >MOVE ]1+]3-33,]1+]3-32 2560 .FIN 2570 .DO ]3-33>]2 2580 >MOVE ]1+]3-34,]1+]3-33 2590 .FIN 2600 .DO ]3-34>]2 2610 >MOVE ]1+]3-35,]1+]3-34 2620 .FIN 2630 .DO ]3-35>]2 2640 >MOVE ]1+]3-36,]1+]3-35 2650 .FIN 2660 .DO ]3-36>]2 2670 >MOVE ]1+]3-37,]1+]3-36 2680 .FIN 2690 .DO ]3-37>]2 2700 >MOVE ]1+]3-38,]1+]3-37 2710 .FIN 2720 .DO ]3-38>]2 2730 >MOVE ]1+]3-39,]1+]3-38 2740 .FIN 2750 .EM 2760 * 2770 * 2780 * 2790 .MA MOVEL MOVE LEFT ROW,COLLOW,COLHIGH FROM 0-39 2800 .DO ]3>]2 2810 >MOVE ]1+]2+1,]1+]2 2820 .FIN 2830 .DO ]3-1>]2 2840 >MOVE ]1+]2+2,]1+]2+1 2850 .FIN 2860 .DO ]3-2>]2 2870 >MOVE ]1+]2+3,]1+]2+2 2880 .FIN 2890 .DO ]3-3>]2 2900 >MOVE ]1+]2+4,]1+]2+3 2910 .FIN 2920 .DO ]3-4>]2 2930 >MOVE ]1+]2+5,]1+]2+4 2940 .FIN 2950 .DO ]3-5>]2 2960 >MOVE ]1+]2+6,]1+]2+5 2970 .FIN 2980 .DO ]3-6>]2 2990 >MOVE ]1+]2+7,]1+]2+6 3000 .FIN 3010 .DO ]3-7>]2 3020 >MOVE ]1+]2+8,]1+]2+7 3030 .FIN 3040 .DO ]3-8>]2 3050 >MOVE ]1+]2+9,]1+]2+8 3060 .FIN 3070 .DO ]3-9>]2 3080 >MOVE ]1+]2+10,]1+]2+9 3090 .FIN 3100 .DO ]3-10>]2 3110 >MOVE ]1+]2+11,]1+]2+10 3120 .FIN 3130 .DO ]3-11>]2 3140 >MOVE ]1+]2+12,]1+]2+11 3150 .FIN 3160 .DO ]3-12>]2 3170 >MOVE ]1+]2+13,]1+]2+12 3180 .FIN 3190 .DO ]3-13>]2 3200 >MOVE ]1+]2+14,]1+]2+13 3210 .FIN 3220 .DO ]3-14>]2 3230 >MOVE ]1+]2+15,]1+]2+14 3240 .FIN 3250 .DO ]3-15>]2 3260 >MOVE ]1+]2+16,]1+]2+15 3270 .FIN 3280 .DO ]3-16>]2 3290 >MOVE ]1+]2+17,]1+]2+16 3300 .FIN 3310 .DO ]3-17>]2 3320 >MOVE ]1+]2+18,]1+]2+17 3330 .FIN 3340 .DO ]3-18>]2 3350 >MOVE ]1+]2+19,]1+]2+18 3360 .FIN 3370 .DO ]3-19>]2 3380 >MOVE ]1+]2+20,]1+]2+19 3390 .FIN 3400 .DO ]3-20>]2 3410 >MOVE ]1+]2+21,]1+]2+20 3420 .FIN 3430 .DO ]3-21>]2 3440 >MOVE ]1+]2+22,]1+]2+21 3450 .FIN 3460 .DO ]3-22>]2 3470 >MOVE ]1+]2+23,]1+]2+22 3480 .FIN 3490 .DO ]3-23>]2 3500 >MOVE ]1+]2+24,]1+]2+23 3510 .FIN 3520 .DO ]3-24>]2 3530 >MOVE ]1+]2+25,]1+]2+24 3540 .FIN 3550 .DO ]3-25>]2 3560 >MOVE ]1+]2+26,]1+]2+25 3570 .FIN 3580 .DO ]3-26>]2 3590 >MOVE ]1+]2+27,]1+]2+26 3600 .FIN 3610 .DO ]3-27>]2 3620 >MOVE ]1+]2+28,]1+]2+27 3630 .FIN 3640 .DO ]3-28>]2 3650 >MOVE ]1+]2+29,]1+]2+28 3660 .FIN 3670 .DO ]3-29>]2 3680 >MOVE ]1+]2+30,]1+]2+29 3690 .FIN 3700 .DO ]3-30>]2 3710 >MOVE ]1+]2+31,]1+]2+30 3720 .FIN 3730 .DO ]3-31>]2 3740 >MOVE ]1+]2+32,]1+]2+31 3750 .FIN 3760 .DO ]3-32>]2 3770 >MOVE ]1+]2+33,]1+]2+32 3780 .FIN 3790 .DO ]3-33>]2 3800 >MOVE ]1+]2+34,]1+]2+33 3810 .FIN 3820 .DO ]3-34>]2 3830 >MOVE ]1+]2+35,]1+]2+34 3840 .FIN 3850 .DO ]3-35>]2 3860 >MOVE ]1+]2+36,]1+]2+35 3870 .FIN 3880 .DO ]3-36>]2 3890 >MOVE ]1+]2+37,]1+]2+36 3900 .FIN 3910 .DO ]3-37>]2 3920 >MOVE ]1+]2+38,]1+]2+37 3930 .FIN 3940 .DO ]3-38>]2 3950 >MOVE ]1+]2+39,]1+]2+38 3960 .FIN 3970 .EM 3980 * 3990 * 4000 * 4010 .MA MOVEU MOVE UP COL,ROWLOW,ROWHIGH FROM 0-23 4020 .DO ]2<1 4030 .DO ]3+1>1 4040 >MOVE ]1+R1,]1+R0 4050 .FIN 4060 .FIN 4070 .DO ]2<2 4080 .DO ]3+1>2 4090 >MOVE ]1+R2,]1+R1 4100 .FIN 4110 .FIN 4120 .DO ]2<3 4130 .DO ]3+1>3 4140 >MOVE ]1+R3,]1+R2 4150 .FIN 4160 .FIN 4170 .DO ]2<4 4180 .DO ]3+1>4 4190 >MOVE ]1+R4,]1+R3 4200 .FIN 4210 .FIN 4220 .DO ]2<5 4230 .DO ]3+1>5 4240 >MOVE ]1+R5,]1+R4 4250 .FIN 4260 .FIN 4270 .DO ]2<6 4280 .DO ]3+1>6 4290 >MOVE ]1+R6,]1+R5 4300 .FIN 4310 .FIN 4320 .DO ]2<7 4330 .DO ]3+1>7 4340 >MOVE ]1+R7,]1+R6 4350 .FIN 4360 .FIN 4370 .DO ]2<8 4380 .DO ]3+1>8 4390 >MOVE ]1+R8,]1+R7 4400 .FIN 4410 .FIN 4420 .DO ]2<9 4430 .DO ]3+1>9 4440 >MOVE ]1+R9,]1+R8 4450 .FIN 4460 .FIN 4470 .DO ]2<10 4480 .DO ]3+1>10 4490 >MOVE ]1+R10,]1+R9 4500 .FIN 4510 .FIN 4520 .DO ]2<11 4530 .DO ]3+1>11 4540 >MOVE ]1+R11,]1+R10 4550 .FIN 4560 .FIN 4570 .DO ]2<12 4580 .DO ]3+1>12 4590 >MOVE ]1+R12,]1+R11 4600 .FIN 4610 .FIN 4620 .DO ]2<13 4630 .DO ]3+1>13 4640 >MOVE ]1+R13,]1+R12 4650 .FIN 4660 .FIN 4670 .DO ]2<14 4680 .DO ]3+1>14 4690 >MOVE ]1+R14,]1+R13 4700 .FIN 4710 .FIN 4720 .DO ]2<15 4730 .DO ]3+1>15 4740 >MOVE ]1+R15,]1+R14 4750 .FIN 4760 .FIN 4770 .DO ]2<16 4780 .DO ]3+1>16 4790 >MOVE ]1+R16,]1+R15 4800 .FIN 4810 .FIN 4820 .DO ]2<17 4830 .DO ]3+1>17 4840 >MOVE ]1+R17,]1+R16 4850 .FIN 4860 .FIN 4870 .DO ]2<18 4880 .DO ]3+1>18 4890 >MOVE ]1+R18,]1+R17 4900 .FIN 4910 .FIN 4920 .DO ]2<19 4930 .DO ]3+1>19 4940 >MOVE ]1+R19,]1+R18 4950 .FIN 4960 .FIN 4970 .DO ]2<20 4980 .DO ]3+1>20 4990 >MOVE ]1+R20,]1+R19 5000 .FIN 5010 .FIN 5020 .DO ]2<21 5030 .DO ]3+1>21 5040 >MOVE ]1+R21,]1+R20 5050 .FIN 5060 .FIN 5070 .DO ]2<22 5080 .DO ]3+1>22 5090 >MOVE ]1+R22,]1+R21 5100 .FIN 5110 .FIN 5120 .DO ]2<23 5130 .DO ]3+1>23 5140 >MOVE ]1+R23,]1+R22 5150 .FIN 5160 .FIN 5170 .EM 5180 * 5190 * 5200 * 5210 .MA MOVED MOVE DOWN COL,ROWLOW,ROWHIGH FROM 0-23 5220 .DO ]2<23 5230 .DO ]3+1>23 5240 >MOVE ]1+R22,]1+R23 5250 .FIN 5260 .FIN 5270 .DO ]2<22 5280 .DO ]3+1>22 5290 >MOVE ]1+R21,]1+R22 5300 .FIN 5310 .FIN 5320 .DO ]2<21 5330 .DO ]3+1>21 5340 >MOVE ]1+R20,]1+R21 5350 .FIN 5360 .FIN 5370 .DO ]2<20 5380 .DO ]3+1>20 5390 >MOVE ]1+R19,]1+R20 5400 .FIN 5410 .FIN 5420 .DO ]2<19 5430 .DO ]3+1>19 5440 >MOVE ]1+R18,]1+R19 5450 .FIN 5460 .FIN 5470 .DO ]2<18 5480 .DO ]3+1>18 5490 >MOVE ]1+R17,]1+R18 5500 .FIN 5510 .FIN 5520 .DO ]2<17 5530 .DO ]3+1>17 5540 >MOVE ]1+R16,]1+R17 5550 .FIN 5560 .FIN 5570 .DO ]2<16 5580 .DO ]3+1>16 5590 >MOVE ]1+R15,]1+R16 5600 .FIN 5610 .FIN 5620 .DO ]2<15 5630 .DO ]3+1>15 5640 >MOVE ]1+R14,]1+R15 5650 .FIN 5660 .FIN 5670 .DO ]2<14 5680 .DO ]3+1>14 5690 >MOVE ]1+R13,]1+R14 5700 .FIN 5710 .FIN 5720 .DO ]2<13 5730 .DO ]3+1>13 5740 >MOVE ]1+R12,]1+R13 5750 .FIN 5760 .FIN 5770 .DO ]2<12 5780 .DO ]3+1>12 5790 >MOVE ]1+R11,]1+R12 5800 .FIN 5810 .FIN 5820 .DO ]2<11 5830 .DO ]3+1>11 5840 >MOVE ]1+R10,]1+R11 5850 .FIN 5860 .FIN 5870 .DO ]2<10 5880 .DO ]3+1>10 5890 >MOVE ]1+R9,]1+R10 5900 .FIN 5910 .FIN 5920 .DO ]2<9 5930 .DO ]3+1>9 5940 >MOVE ]1+R8,]1+R9 5950 .FIN 5960 .FIN 5970 .DO ]2<8 5980 .DO ]3+1>8 5990 >MOVE ]1+R7,]1+R8 6000 .FIN 6010 .FIN 6020 .DO ]2<7 6030 .DO ]3+1>7 6040 >MOVE ]1+R6,]1+R7 6050 .FIN 6060 .FIN 6070 .DO ]2<6 6080 .DO ]3+1>6 6090 >MOVE ]1+R5,]1+R6 6100 .FIN 6110 .FIN 6120 .DO ]2<5 6130 .DO ]3+1>5 6140 >MOVE ]1+R4,]1+R5 6150 .FIN 6160 .FIN 6170 .DO ]2<4 6180 .DO ]3+1>4 6190 >MOVE ]1+R3,]1+R4 6200 .FIN 6210 .FIN 6220 .DO ]2<3 6230 .DO ]3+1>3 6240 >MOVE ]1+R2,]1+R3 6250 .FIN 6260 .FIN 6270 .DO ]2<2 6280 .DO ]3+1>2 6290 >MOVE ]1+R1,]1+R2 6300 .FIN 6310 .FIN 6320 .DO ]2<1 6330 .DO ]3+1>1 6340 >MOVE ]1+R0,]1+R1 6350 .FIN 6360 .FIN 6370 .EM 6380 * 6390 * 6400 *-------------------------------- 6410 * 6420 * SPIRAL PROGRAM 6430 .OR $6000 OUT OF THE WAY 6440 .TF SPIRAL.OBJ 6450 * 6460 * 6470 SPIRAL LDA #' '+$80 GET A SPACE 6480 STA R12+12 PUT IT IN CENTER 6490 LDX #960 HOW MANY TIMES ? 6500 LDY /960 HIGH ORDER 6510 * 6520 SPI1 >MOVED 0,0,23 6530 >MOVEL R0,0,39 6540 >MOVEU 39,0,23 6550 >MOVER R23,1,39 6560 * 6570 >MOVED 1,1,23 6580 >MOVEL R1,1,38 6590 >MOVEU 38,1,22 6600 >MOVER R22,2,38 6610 * 6620 >MOVED 2,2,22 6630 >MOVEL R2,2,37 6640 >MOVEU 37,2,21 6650 >MOVER R21,3,37 6660 * 6670 >MOVED 3,3,21 6680 >MOVEL R3,3,36 6690 >MOVEU 36,3,20 6700 >MOVER R20,4,36 6710 * 6720 >MOVED 4,4,20 6730 >MOVEL R4,4,35 6740 >MOVEU 35,4,19 6750 >MOVER R19,5,35 6760 * 6770 >MOVED 5,5,19 6780 >MOVEL R5,5,34 6790 >MOVEU 34,5,18 6800 >MOVER R18,6,34 6810 * 6820 >MOVED 6,6,18 6830 >MOVEL R6,6,33 6840 >MOVEU 33,6,17 6850 >MOVER R17,7,33 6860 * 6870 >MOVED 7,7,17 6880 >MOVEL R7,7,32 6890 >MOVEU 32,7,16 6900 >MOVER R16,8,32 6910 * 6920 >MOVED 8,8,16 6930 >MOVEL R8,8,31 6940 >MOVEU 31,8,15 6950 >MOVER R15,9,31 6960 * 6970 >MOVED 9,9,15 6980 >MOVEL R9,9,30 6990 >MOVEU 30,9,14 7000 >MOVER R14,10,30 7010 * 7020 >MOVED 10,10,14 7030 >MOVEL R10,10,29 7040 >MOVEU 29,10,13 7050 >MOVER R13,11,29 7060 * 7070 >MOVED 11,11,13 7080 >MOVEL R11,11,28 7090 >MOVEU 28,11,12 7100 >MOVER R12,12,28 7110 * 7120 DEX 7130 CPX #$FF 7140 BNE SPI2 7150 DEY 7160 CPY #$FF 7170 BNE SPI2 7180 RTS 7190 SPI2 JMP SPI1 7200 * 7210 ZZSIZE .EQ *-SPIRAL |
Remember, the whole source with the full macro definitions will be on the next quarterly disk ($15, for all source code in issues July-August-September 1983).
Because Charlie's program makes such heavy use of macros, it takes considerable time to assemble. He timed it at nearly two minutes. If the program were written out the long way, without macros, it would take only about 20 seconds to assemble.
Charlie pointed out that we are needlessly moving the center of the spiral, which is already blank. As the blanked portion grows, this becomes very significant. In fact, by eliminating moving the cleared portion, the time could be further reduced to only 3 1/2 seconds. Each LDA-STA takes 8 cycles. The long way takes 959*960 pairs, plus some overhead. Ignoring the overhead, we get 7365120 cycles, or about 7.2 seconds. Forgetting the blanked stuff makes it 3.6 seconds. Any takers?
And I was just wondering...how about an Applesoft program which writes the 959 LDA-STA pairs as assembly language source on a text file? Or POKEs the actual object code, by computing the addresses necessary, into a binary buffer area. Again, any takers?
I am a tinkerer! Yes I love to take programs and add features to improve them. Sometimes the "improved" version even works! Usually I learn a lot about humility, and occasionally a bit about programming.
A case in point is the program for doing an Applesoft Variable Cross Reference (from the November 1980 issue of Apple Assembly Line). I just recently got Quarterly Disk #1 with its source code, and so it became "tinker-time".
VCR works just fine, and is fast! But it only produces 40- column output, and I wanted both 40-column screen and 80-column printer hardcopy. Here are some patches which will do the job. It makes a good short example of changing output hooks in the middle of a program without goofing up DOS.
1060 .TF B.VCRP "P" FOR PRINTER VERSION 4534 LDA #0 RESET COUNTER TO 0 4538 STA $6 FOR EACH VARIABLE 4821 INC $6 COUNT THE SCREEN LINE 4822 LDA $6 4823 AND #1 LOOK AT ODD-EVEN BIT 4824 BEQ TAB.NEW.LINE BOTH SCRN AND PRINTER 4825 LDA #$FDF0 ONLY SCRN GETS NEW LINE 4826 STA $36 SO DISCONNECT PRINTER 4827 LDA /$FDF0 4828 STA $37 4829 JSR $3EA PASS TO DOS 4830 JSR MON.CROUT SCREEN ONLY 4831 LDA #$C100 REHOOK PRINTER 4832 STA $36 4833 LDA /$C100 4834 STA $37 4835 JSR $3EA PASS TO DOS 4836 BNE .1 ...ALWAYS
To use the printer version of VCR, BRUN B.VCRP. This sets up the ampersand vector. Then LOAD your Applesoft program. Use PR#1 to turn on your printer. Then type "&" and RETURN, and watch the cross reference.
If your printer is in some slot other than 1, change lines 4831 and 4833 to the correct value ($Cs00, where s=slot#).
In the process of de-crypting a large data base, I needed to reverse the nybbles in each of roughly 32000 bytes. There are probably a lot of ways to do this, but I found one which takes only 12 bytes to reverse the nybbles in the A-register.
Just to be sure we agree on what I am talking about, here is a little diagram:
a b c d e f g h e f g h a b c d
One way, sort of brute force, involves breaking the nybbles out and remerging them:
LDA (PNTR),Y ASL SHIFT EFGH LEFT ASL ASL ASL STA TEMP LDA (PNTR),Y LSR SHIFT ABCD RIGHT LSR LSR LSR ORA TEMP RE-MERGE NYBBLES STA (PNTR),Y
From another perspective, I am trying to rotate the data byte half-way around. But if I try to do it with ROL or ROR instructions, one bit gets left in CARRY, and an extra bit gets inserted in the middle. Here is how I finally did it:
LDA (PNTR),Y abcd efgh ASL bcde fgh0 ADC #0 bcde fgha ASL cdef gha0 ADC #0 cdef ghab ASL defg hab0 ADC #0 defg habc ASL efgh abc0 ADC #0 efgh abcd STA (PNTR),Y
Each ASL-ADC pair shifts the byte around one bit. The ASL shifts the leftmost bit into the CARRY bit, and a zero into the right end. The ADC #0 adds CARRY into the rightmost bit.
Naturally, curiosity forces me to look at the possibility of shifting right one bit also. We have LSR and ROR, of course, but both of these leave the shifted out bit in CARRY. I want that bit back in the sign position, like this:
ABCDEFGH should become HABCDEFG
Two similar methods come to mind, depending on how I might use it. If the byte to be shifted is in A-reg, and needs to remain there, and I don't want to upset any other registers, I can do it like this:
PHA save unshifted value LSR get rightmost bit in CARRY PLA restore unshifted value ROR shift again, putting right bit on left
If the byte to be shifted is in memory, and I want the results to be in memory, I might do it like this:
LDA FLAG LSR RIGHTMOST BIT INTO CARRY ROR FLAG SHIFT BYTE, PUTTING RIGHT INTO LEFT
Note that I can branch according to the value of the bit which moved around by using BMI or BPL, because that bit is the new sign bit.
The last method above can be useful when you have a program that needs to alternate between two paths. For example, suppose I write a program to pick up the "next nybble" from a data area. The first time I call it, I want to get the left nybble of the first byte. Next time, the right nybble of the same byte. Next time the left nybble of the next byte. And so on.
I might store the value $55 in FLAG initially, and then use LDA FLAG, LSR, ROR FLAG, to shift it around. FLAG will alternate between $55 and $AA. My subroutine can alternate between left and right nybbles.
Not to leave you hanging, I wrote "get next nybble" and "put next nybble" subroutines. By the time I finished polishing, yet another technique had surfaced for rotating the $55/$AA flag. I used this new method so as not disturb the contents of the A-register.
To set up either routine, the address of the beginning of the data area must be put into PNTR and PNTR+1, and $55 must be put into FLAG.
1000 *SAVE NYBBLE GET & PUT 1010 *-------------------------------- 1020 PNTR .EQ 0 AND 1 1030 FLAG .EQ 2 1040 *-------------------------------- 1050 * PUT NEXT NYBBLE AT (PNTR) 1060 * IF FLAG = $55, PUT LEFT NYBBLE 1070 * = $AA, PUT RIGHT NYBBLE 1080 *-------------------------------- 1090 PUT.NEXT.NYBBLE 1100 LDX #0 1110 LSR FLAG $55 OR $AA 1120 BCS .1 ...IT WAS $AA, NOW $54 1130 *---STORE IN LEFT NYBBLE--------- 1140 ASL FLAG NOW $AA 1150 ASL 1160 ASL 1170 ASL 1180 STA (PNTR,X) 1190 RTS 1200 *---STORE IN RIGHT NYBBLE-------- 1210 .1 ORA (PNTR,X) MERGE WITH LEFT NYBBLE 1220 STA (PNTR,X) 1230 INC FLAG MAKE $54 INTO $55 1240 INC PNTR MOVE PNTR TO NEXT BYTE 1250 BNE .2 1260 INC PNTR+1 1270 .2 RTS 1280 *-------------------------------- 1290 * GET NEXT NYBBLE 1300 * IF FLAG = $55, GET LEFT NYBBLE 1310 * = $AA, GET RIGHT NYBBLE 1320 *-------------------------------- 1330 GET.NEXT.NYBBLE 1340 LDX #0 1350 LSR FLAG WAS $55 OR $AA 1360 LDA (PNTR,X) GET BYTE WITH NYBBLES 1370 BCS .1 ...WAS $AA, NOW $54 1380 *---GET LEFT NYBBLE-------------- 1390 LSR 1400 LSR 1410 LSR 1420 LSR 1430 RTS 1440 *---GET RIGHT NYBBLE-------------- 1450 .1 INC FLAG MAKE $54 INTO $55 1460 INC PNTR ADVANCE TO NEXT BYTE 1470 BNE .2 1480 INC PNTR+1 1490 .2 AND #$0F ISOLATE NYBBLE 1500 RTS 1510 *-------------------------------- |
Grappler Interfaces
There should be a leaflet included with this issue describing the Grappler printer interfaces. We now have three of them "in the family" here, and have been very pleased with their performance. Check the brochure for features, the ad on page three for our prices, and let us hear from you.
WICO Track Ball
Several of you have inquired about or ordered the WICO Track Ball that I reviewed a couple of months ago, so we've decided to carry them regularly. WICO has since raised their price from $79.95 to $89.95, so we're going from $75 to $80.
Diskettes
There's getting to be a lot more competition in the diskette business, so prices are falling. After seeing so many ads at such attractive prices, Bob called Verbatim and told them that we had to have a better price, or we would have to change brands. That paid off, so we can now offer the same high- quality Verbatim Datalife diskettes at $45.00 for a package of 20. That's $2.25 each for the best diskettes we've found.
Whatever You Want
If you're shopping for a new peripheral, accessory, or program, give us a call and ask for a quote. We can get nearly anything you might want, and we'd love the chance to serve you.
We've had several calls requesting the patch addresses for a couple of features in the S-C Macro Assemblers.
Ansert?
In Version 1.1 of the Macro Assembler, Bob changed the CTRL-I (Insert) command in the EDIT mode to CTRL-A (for ADD). This was done because the Apple //e keyboard has the TAB key, which generates a CTRL-I code. It didn't seem to make much sense to have the TAB key do an insert operation, so he added a clear- to-next-tab-stop function for CTRL-I.
Well, a lot of people don't have //e's, or don't much care about the TAB key. A lot of us are used to CTRL-I for Insert, and would like to keep it that way.
The CTRL-A character ($81) is at $1C87 in the $1000 version, and at $DCB7 in the $D000 version. Just change that byte to a $89, and you'll have your good old CTRL-I back. If you want to keep the clear-to-tab-stop function, you can change the $89 at $1CC6 ($DCC6) to a $81. That will make CTRL-A do the clear-to- tab.
.BS Filler Byte
The directive .BS <expr> skips over <expr> bytes when you are assembling to memory, and sends <expr> zero bytes to the target file when you are assembling to disk. Several people have asked how to change the zero to some other value.
For example, a freshly-erased EPROM contains all $FF bytes. When you burn data into the chip, you actually write in just the zero bits. If you are assembling code to be written into an EPROM, you want any fill bytes to be $FF, so you can add patches later without having to erase and re-write the whole chip.
The following table shows the addresses of the zero byte in the various versions of the Macro Assembler. Just change the indicated byte to the value you want to use for filler.
Version 1.0 | 1.1 | 40-col //e Videx STB $1000 2D43 | 2D62 2D48 2E37 2E60 $D000 EE8F | EE86 EE62 EF5A EF83
First let me apologize for an erroneous statement in the May '83 issue, in which I juxtaposed two unrelated facts in a cause-effect sentence. Many readers have sent corrections: I am told that grounding the DTACK signal has nothing to do with how much memory you can add. How did I ever get the idea that it did? If you want the straight scoop on this, subscribe to Digital Acoustics' newsletter "DTACK Grounded".
Digital Acoustics has announced a new board, called the "DTACK Grande". Almost sounds like "grounded", but this time it isn't. You get one megabyte of RAM and a 12.5 MHz 68000. RAM refresh is handled by an interrupt routine, with software. The overhead is only 4%, giving an effective speed of 10 MHz. Expansion connectors on the card can connect to another 15.7 megabytes. I'd say Saybrook has been passed by, but Hal Hardenburg beat me to it! (Digital Acoustics, 1415 E. McFadden, Suite F, Santa Ana, CA 92705. (714) 835-4884)
Mike Heckman at Anthro-Digital sent me some literature on another new 68000 board. Enhancement Technology Corporation calls it the "PDQ//". Specs include: 10 MHZ, 256K RAM, UCSD p-system, Applesoft-compatible BASIC. The price will be $1495, available by the end of August. We may be able to make you a deal on one of these. (ETC, P.O.Box 1267, Pittsfield, MA 01202. (413) 445-4219)
Earlier this year I decided to break down and finally buy an 80-column card for my Apple II+. After all, it's cheaper than a IIe. I was just about to type in the Videx patches from AAL Volume 2, No.11, when Bob announced Version 1.1. Well with the Videx patches and all the new features I just couldn't pass up his offer. After a call to Bob and a three day wait I had version 1.1 of the S-C Macro Assembler.
While testing out the new version I soon discovered most of the patches I had applied to version 1.0 would not work properly. The addresses of the routines/tables had all moved. After a few hours work and a lot of dis-assembling I would like to share the new locations with AAL readers and bring some of the patches together.
First I will describe the new addresses and then show how I used them.
The Escape Function Table is now located at $14AB-$14C6 <ESC-@ thru ESC-M>. This is a group of two-byte addresses (minus 1, because they are of the PHA-PHA-RTS variety) of the routines to handle the escape functions.
The Edit Function Table is now located at $1CB4-$1CE3 <ctrl-@ thru ctrl-X>. This table is somewhat different. Each entry is three bytes long and it contains the control character and the address-minus-1 of the routine to handle the function.
Location $14D3 contains the dash count <$26> for the ESC-L function.
Location $13FF contains a JSR to the monitor Bell routine. This is the end of the input checker, the JSR BELL is executed when an invalid character is entered, and a good place to put a JSR to an extended input processor.
These locations are valid for the regular version and the Videx version which load at $1000. For language card users just add $C000 to the address. My hat is off to Bob for adding all the features of Videx and still keeping the assembler looking the same. I have not checked the STB or the IIe versions for compatibility but, with a little bit of work and knowing what to look for it should be an easy process.
Now, what can you do with this information? I have modified Bob's language card loader to show you (figure 1). With the exception of the REM statements, lines 1000-1140 of the file are as Bob supplied; after that the changes begin. I will not spend a lot of time explaining the routines themselves because they are all well documented in the referenced AAL articles.
The first thing I do is load in my extended input processor (figure 2) at $F600. There appears to be about two free pages after the assembler and before monitor in the language card version. For standard version users just move the symbol table up as described AAL Vol. 2, No. 9. My input processor is a combination of Auto Catalog (AAL 2.9) and Toggling Upper/Lower Case (AAL 3.3). Next I modify the JSR BELL to JSR CONTROL.A.
Once you have control you can add any routines you wish (such as R. F. O'Brien's Auto/Manual Toggle AAL 2.11). For now I am only interested in an upper/lower case toggle.
Line 1170 modifies the ESC-C function to JSR to my routine for auto Catalog. Remember this should be the address of the routine - 1. Lines 1180-1190 change the cursor to a blinking underline (as described in AAL 3.5) along with line 1200 which changes the number of "-"'s from 38 to 64 (I found 68 to be too many).
Last but not least is an answer to Steve Mann's request for a upper/lower case toggle in EDIT mode. In version 1.1 Bob changed the ctrl-I key function in EDIT mode and added a ctrl-A key function in its place. He did it so that the //e TAB key, which generates control-I, would really mean TAB.
Well Bob, I like mnemonic commands (like ctrl-I for Insert), and think the older Apples should still take precedence. Line 1210 changes the ctrl-A key to branch to my upper/lower case toggle routine, just past the character check, and line 1220 changes the ctrl-I routine back to its proper function (this was the address found in the ctrl-A area).
I hope these patches will be useful to other AAL readers not only for what they do, but for how they do it.
1000 REM LOAD S-C MACRO ASSEMBLER (VIDEX) 1010 REM INTO RAM AT $D000 1020 REM LOAD PATCHES AT $F600 1030 REM PATCH INPUT TEST TO CHECK FOR MY COMMANDS BEFORE ERROR 1040 REM PATCH ESCAPE TABLE ($D4AB-) FOR ESCAPE-C 1050 REM CHANGE CURSOR TO BLINKING UNDERLINE 1060 REM PATCH ESC-L DASH LINE COUNT 1070 REM PATCH EDIT CNTL-A TO MY ROUTINE 1080 REM PATCH EDIT CNTL-I BACK TO INSERT FUNCTION 1090 CALL-151 1100 C081 C081 1110 F800<F800.FFFFM 1120 BLOAD S-C.ASM.MACRO.D000.VIDEX 1130 300:A9 4C CD 00 E0 F0 12 8D 00 E0 A9 00 8D 01 E0 A9 D0 8D 02 E0 A9 CB 8D D1 03 60 1140 300G 1150 BLOAD SCM.PATCH 1160 D3FF:20 00 F6 1170 D4B1:19 F6 1180 C0B0:0A 68 1190 C0B0:0B 08 1200 D4D3:40 1210 DCB8:03 F6 1220 DCC7:0B DC 1230 C080 1240 3D3G 1000 *SAVE WETZEL'S PATCHES TO 1.1 1010 .OR $F600 1020 .TF SCM.PATCH 1030 *---------------------------------------------------------- 1040 CH .EQ $24 1050 BASL .EQ $28 1060 YSAVE .EQ $40 1070 WBUF .EQ $200 1080 LCPROT .EQ $C080 LC Protect 1090 LCWRT .EQ $C083 LC Write enable 1100 UCFLAG .EQ $D016 UC/LC Flag 1110 BELL .EQ $FF3A Monitor Bell 1120 *---------------------------------------------------------- 1130 CONTROL.A 1140 CMP #$81 Was a CNTL-A entered 1150 BNE ERROR No - then signal error 1160 LDA LCWRT Write enable Language card 1170 LDA LCWRT 1180 LDA UCFLAG Get upper case flag 1190 EOR #$FF Reverse it 1200 STA UCFLAG Put it back 1210 LDA LCPROT Write protect Language card 1220 RTS 1230 ERROR 1240 JSR BELL Ring bell to signal error 1250 RTS Return 1260 *---------------------------------------------------------- 1270 ESCAPE.C 1280 CPX #0 Start of line? 1290 BNE .2 No, rtn 1300 LDY #0 1310 .1 LDA MSG,Y Get message 1320 STA WBUF,Y Put in buffer 1330 STA (BASL),Y Put on screen (40-column) 1340 INY 1350 CPY #7 Finished ? 1360 BNE .1 Not yet 1370 STY YSAVE 1380 INY 1390 STY CH Tell assembler 1400 TSX this was an 1410 LDA #$CC ESC-L so it will 1420 STA $103,X exec command 1430 LDX YSAVE 1440 .2 RTS 1450 MSG .AS -/CATALOG/ |
We have uncovered another neat new Apple accessory: a volume control for the speaker! If other people within earshot of your computer are trying to sleep, or just can't take another five minutes of bells, beeps, and buzzes, the WHISPER VOLUME CONTROL is for you. The Apple version works with II, II Plus, //e, or ///. All you have to do to install it is take the case off your Apple, unplug the speaker wire from the board, plug in the WVC cable, and plug the speaker wire into the other end of the WVC connector. You can also get WVC for the IBM/PC. The retail price is $22.95 for the standard version, or $25.95 with a headphone jack, from Information Dynamics Corp., 1251 Exchange Drive, Richardson, TX 75081. Phone (214)783-8090. Or if you like, buy them from us at $21 and $24, respectively.
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 $15 per year in the USA, sent Bulk Mail; add $3 for First Class postage in USA, Canada, and Mexico; add $13 postage for other countries. Back issues are available for $1.50 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.)