Apple Assembly Line
Volume 7 -- Issue 1 October 1986

In This Issue...

Updated Supplement to "Beneath Apple ProDOS"

I visited Bob Christiansen at Quality Software last month, and he handed me a copy of the new supplement for "Beneath Apple ProDOS". This is the line-by-line comments for the entire BASIC.SYSTEM and PRODOS package, updated to version 1.1.1. The previous edition covered version 1.0.1 and version 1.0.2, and was obsolete by the time it was available. The new edition also is updated to version 1.1 of BASIC.SYSTEM. The price for the latest supplement is $12.50, and you must order it directly from Quality Software. As far as I know, you also must include the order page from your copy of "Beneath Apple ProDOS", or from your copy of the first edition of the Supplement.

New Version of 6805 Cross Assembler

We have now upgraded the S-C Macro 6805 Cross Assembler to Version 2.0, and it is available now for both DOS 3.3 and ProDOS. Owners of version 1.0 of this cross assembler may upgrade to the new DOS version for $20. The purchase price for either DOS or ProDOS Version 2.0 is $50, or for both is $70; if you already have one you may add the other for only $20.


Apple Finally Lifts the Lid on the IIgs Bob Sander-Cederlof

Late in September the secrecy ended. Hopefully in time for the Christmas buying binge, Apple announced the long-awaited new member of the Apple II family. The IIgs, for only $999, sports 256K RAM, a 65816 cpu running at 2.8 MHz, and greatly enhanced graphics and sound capability.

Within moments of Apple's momentous announcement, newspapers and magazines all over the world detailed the features of the new machine. Readers sent me clippings from as far away as France. Even our local Dallas Morning News was excited. By now most of you have probably visited a nearby dealer to see a demonstration, in full color and stereo sound. You have also read about the IIgs in Byte, II Computing, InCider, A+, and Nibble. Or their counterparts in other parts of the world.

With all these great sources of information, what can I add? Maybe just the personal touch, because I have a machine. We are among the lucky few picked by Apple to receive a prototype several months ago. (Apple swore us to secrecy until the great day of revelation.) What they sent us looks just like a //e from the outside, but inside there is a different motherboard. This is probably the way an upgraded //e will look. Apple has promised an upgrade kit for the //e, which involves a dealer-performed motherboard swap, for about $500. The dealer will also have to mount a new back panel, because there are a lot of built-in connectors for the built-in I/O ports.

The new motherboard looks distinctly different from any older Apples. There are still seven slots plus an auxiliary slot, but now the aux-slot is on the right side rather than the left. There is only one 28-pin ROM socket, apparently designed to hold a megabit ROM (128K bytes) but not an EPROM. That is not entirely clear, because claims are made that the ROM is expandable to 1024K bytes. Maybe they are using one of the new page-mode EPROMs. Or, more likely, Apple expects expansion ROM to be mounted on a card in the same slot that holds expansion RAM. (That slot is going to be a little crowded!) Most of the chips are soldered to the board, and many of them are "surface-mount-devices".

The RAM on the motherboard is quite different from older versions. Four 4-by-64Kbit dynamic RAM chips are soldered down on the right hand side, called "fast RAM". There are four more chips soldered on the front left side, called "slow RAM". Together, these eight chips give 256K bytes of RAM. There are also two of the same kind of chips in sockets, giving another 64K RAM, which is dedicated to the built-in music synthesizer.

The 65816 uses a 24-bit address bus. Since the chip only has 40 pins, the high byte of the address (called the "bank") is multiplexed on the data lines. There are 256 banks of 65536 bytes, giving a total of 16,777,216 bytes -- this is what we commonly call 16 megabytes. The 128K ROM on the motherboard maps into banks $FE and $FF. Expansion ROM, up to a total of one megabyte, would fill banks $F0 through $FD.

The 128K bytes of "fast RAM" occupy banks $00 and $01. The 128K bytes of "slow RAM" occupy banks $E0 and $E1. Slow RAM is synchronized to the video output, running at about 1 MHz. When bytes are read from or written into these banks, the processor slows down to a 1MHz rate during the store cycle. During Apple II emulation, these banks act as "shadow" RAM, with the program actually running in "fast RAM" in banks $00 and $01. Any time a byte is stored into one of the video areas ($400-BFF or $2000-5FFF of either bank $00 or $01), the process slows down and the byte is also stored in the shadow RAM. When a byte is read from one of these areas, it is read only from the fast RAM copy and the processor does not have to slow down. All of the I/O addresses are in bank $E0, from $E0C000 through $E0CFFF. I assume that when you are in Apple II emulation mode these must be mapped also into bank $00, and I assume the processor slows down when these addresses are accessed.

Apple says that expansion RAM will map into banks $02 through $7F. Since several manufacturers have already announced 8 Megabyte expansion cards, I assume there are two more banks used at $80 and $81. But maybe not: perhaps the 8Meg cards leave 128K not addressable.

The memory map, the way Apple tells it, leaves two big sections unused, probably considered by Apple to be reserved. Banks $80-$DF and banks $E2-EF add up to almost seven megabytes still not taken.

There is also some battery-backed-up RAM in there somewhere, possibly inside the clock-calendar chip. The IIgs remembers how you have configured all the serial ports, what colors you want to use for text (letters, background, and border), how loud to ring the bell, and other interesting parameters.

Speaking of those configuration parameters reminds me of the Closed-Apple-Control-Reset. On a //e or //c, this does a self test. On the //gs it enters a menu-driven system-configuration program. You can set the time of day and the date, define the serial ports, allocate the slots, pick the screen colors, and so on. It is all done with just the four arrow keys, RETURN, and ESCAPE. Very nice! By the way, on a REAL IIgs, there is no closed-Apple key. Instead, there is an "option" key, between the case-lock and the open-Apple keys.

Yes, there are seven I/O slots, just like in the //e. Most cards that you now have in a II, II+, or //e will work in the //gs. However, not all. For example, Phil Wershba told me the quikLoader does not work. Not surprising, since the quikLoade tries to take control of the bus after a reset. The slots will probably not be used much, at least for a while, since so much I/O is already built-in. The IIgs comes already equipped with a clock/calendar, two serial ports (printer and modem, or two printers, or printer and AppleTalk, or whatever), disk controller (called the SmartPort, for up to six drives, mixing 3.5 and 5.25 sizes), music/speech synthesizer, RGB video, and the FrontDesk Bus (more on this later). I can see only one serious omission here, a SCSI port; Apple is supposedly offering a card for that purpose, so there goes one slot. In my work I use things like the PromGramer to burn EPROMs, and a custom-made EPROM-emulator, and I frequently am testing new boards, so I need two or three more of the slots.

There is a catch here. Most of the built-in I/O ports have to be allocated a slot, even though they are really on the mother-board. Slot 1 is either a built-in serial port, or your card. Slot 2 is the other serial port, or your card. Slot 3 is the built-in text display, or your card. Slot 4 is the Mouse port, or your card. Slot 5 is the SmartPort, or your card. Slot 6 is the built-in disk port, or your card. Slot 7 is the built-in AppleTalk port, or your card. It all appears very rigid. I presume we will have to find ways to use the slots both ways at once, with tricky hardware and tricky software.

By the way, the game port is still there. There is an external 9-pin jack like on the //c, and an internal 16-pin socket like all the other members of the II-family. On the other hand, the cassette I/O is gone.

The FrontDesk Bus is a low-speed serial port to which the keyboard and the mouse are attached. Various sources say a total of from 4 to 16 devices can be connected to this bus, including such items as trackballs, graphics tablets, and so on. The FrontDesk Bus has its own computer, a Mitsubishi 50740. The 50740 is a complete microcontroller based on the 6502, with opcode enhancements completely different from those in the 65C02 and 65816. I described it in the February 1986 AAL.

The various reports in other magazines and newspapers say that Apple will be selling a SCSI controller card and a 20-Megabyte hard disk. Some claim the hard disk will be partitionable so it can be shared by several operating systems on the IIgs, and also be shared by a Macintosh. For some reason I am a little skeptical about this one. In any case, whether Apple has one or not, I am certain that several 3rd-party drive sellers will. I expect a Sider, and I expect something from those who make SCSI-based Macintosh drives now. I haven't tried plugging my Sider into a IIgs slot yet; I am afraid. If it doesn't work, it could still wreak havoc (remember Murphy's law).

Everyone is talking about the new graphics and sound features. Apple encourages this by naming it "GS", which is supposed to mean Graphics and Sound. (I think it means "GaSsee", or "Gassee & Sculley".) If you hook it up to an RGB monitor, you get greatly enhanced grpahics capability. If you have only a normal NTSC color monitor, or a monochrome monitor, or a TV set with a modulator, you will only get standard Apple II graphics. The new feature I like best is the ability to choose colors for normal text displays: you choose the text color, the background color, and the border color. The new feature most liked by the magazines, and all you graphics buffs, is the super hi-res graphics. You can display 200 lines, with either 320 pixels/line or 640 pixels/line. Each pixel has either two bits (640/line) or four bits (320/line). The pixel's value selects a color-entry from a palette. There are 4096 different colors available, of which up to 256 may be used on one screen. Any one line can display up to 16 different colors. With a hi-res character generator in firmware, you can display multi-colored 80-column text mixed with graphics in the 640-pixel mode.

The IIgs includes a lot of firmware, well beyond the normal monitor, Applesoft, and I/O drivers. There is also a mini-assembler and a disassembler supporting the entire 65816 instruction set. The ToolBox ROM includes graphics routines and all the stuff you find in a Macintosh toolbox. Many Macintosh-based products will probably be translated to the IIgs, like Filevision. And then they can add color, too! Electronic Arts Inc. announced a color graphics tool for creation, editing, and animation. Is that the same as Paintworks? Anyway, have you played with Paintworks? Wow!

The IIgs still has the single-bit speaker-toggling sound generator, so your old programs can still make noises, though they might sound different because of the faster speed of the processor. But that is like saying that the latest Mercedes still has a steering wheel. There is a lot more! The Ensoniq synthesizer can play 15 simultaneous channels, with each one's voice defined by actual waveform data stored in a dedicated 64Kbyte RAM. Appropriate software makes it talk, better than any computers you ever heard before. Other software makes REAL music. The Ensoniq chip was designed for and is used in professional music synthesizers. It can also be used to sample actual sounds, to create your own synthetic instruments.

How fast is the IIgs? Well, it is faster than a //e, but slower than a //e with an accelerator card like Transwarp. The system clock runs at 2.8 MHz, but the processor slows down when writing "slow RAM" and when accessing I/O addresses. Memory refresh in fast RAM is done by using the internal refresh capability of the RAM chips triggered by reversed RAS and CAS signals. Whenever possible, these cycles are done without slowing down the processor: during a ROM read cycle, and during a cycle in which no memory access takes place. But if that were the only times, someone could put a JMP $800 at $800 and wipe out all the RAM! Therefore some more cycles are stolen periodically for refresh. The net result is that the processor runs closer to an average of 2.5 million cycles per second. The Transwarp, on the other hand, runs at 3.58 MHz whenever it can, so the //e so-equipped can outrun a IIgs. So far. But I will not be surprised if Applied Engineering, Checkmate Technology, or some other group comes out with an accelerator for the IIgs. Simply going up to 3.58 MHz would not be significant. But how about 7 MHz? Western Design Center plans to make 8 MHz chips someday, so....

The expanded instruction set in the 65816 makes it possible to write code that takes fewer cycles than an equivalent program in the 6502 or even 65C02. However, that advantage is probably offset by the additional overhead of accessing memory beyond 64K (because it takes an extra byte for the long addresses). There is also extra overhead in the firmware and in the operating system to handle the extra space and all the other new features.

Applied Engineering has already announced two different RAM expansion cards for the IIgs. GS-RAM can grow to 1.5M. GS-RAM Plus can grow to 6M, or to 8M with an optional piggy-back card. A newcomer, MDIdeas, has announced a card called OctoRam, which can support from 256K to 8M expansion RAM. Apple themselves offer a 1M card. AST also has a 1 Mbyte card. Orange Micro has one which can grow from 512K to 4M.

MDIdeas also announced a $130 combination cooling fan and surge-supressing power strip, and a $60 sound boosting amplifer which splits the Ensoniq's output into left and right stereo channels. AST claims a new board called Vision Plus which can digitize black and white pictures. Orange Micro has an updated printer interface called the ProGrappler, with lots of graphic-handling firmware.

A salesman in our local Heath/Zenith store (they are now Apple dealers) asked me what kind of printers might be on the horizon for printing the IIgs color graphics. I wonder. Could someone figure out a way to connect a color Xerox machine to a personal computer? For under $5000? Polaroid might be a less expensive approach, just taking a photograph of the screen.

I am planning to buy a IIgs. How will I use it? I see it as a whole new world to explore, orders-of-magnitude larger in every dimension than was my 1977-vintage Apple II. I also see it as a software development engine, with the 65816 and gobs of RAM allowing much bigger projects to be tackled. Once the software tools are available, we should see lots of new applications.

	ROM history

	Apple II             8K
	Apple IIPlus        12K
	Apple //e           16K
	Apple //c           16K
	Enhanced //e        16K
	Unidisk 3.5 //c     32K
	Apple //gs         128K

Convert Hi-Res Pictures to Double Hi-Res David C. Johnson

I had a normal hi-res picture that I wanted to animate using the greater resolution of double hi-res. It was a monochrome picture (that is, it looked best when viewed on a monochrome monitor), but SOME of the bytes had the color bit set. This moved their 7 pixels over half position. If the color bit of the previous byte was NOT set, then its last bit extends into the half pixel left by the shifted byte. At the other end of a shifted byte, if the subsequent byte is UNSHIFTED, the shifted byte's last pixel is only half width.

One interesting sourec of monochrome pictures with some color bits on is the Apple Hi-Res Character Generator. Some of the character sets used by HRCG use shifted bytes for prettier slopes on letters like "A". Of course you never know what kind of bytes you may find after using a fancy picture-drawing program.

The following program performs a "perfect" translation, assuming a monochrome image. I also wrote a color converter, but it is not so "perfect". (I don't think a perfect color conversion is possible.)

My program assumes the picture to be converted is already in hi-res page 1, from $2000 through $3FFF. The pixels are shuffled around so that each original byte forms two bytes, one in main RAM and the other in auxiliary RAM. When the translation is done, a tone will beep at you until you type any key. Then I switch the double hi-res graphics on, and again beep until you hit any key. When you tire either of the beep or of viewing the double hi-res picture, type any key and it will stop. Text mode will be restored. I also copy the auxiliary half of the picture into main RAM at $4000 through $5FFF, and prepare it for being saved as a "foto-file".

I do the translation of a byte-ful of pixels into two double hi-res bytes by table lookup. The tables are generated by a subroutine in lines 2230-2480. You can make some interesting variations by changing either line 2310 or line 2340 (or both) from "ROL" to "ASL" instructions.

The subroutine in lines 2500-2670 waits for any key to be typed, while making an annoying beep. (Blame this one on Bob S-C, he wrote it.)

  1000 *SAVE HIRES.2.DBLHIRES
  1010 *--------------------------------
  1020 PTR1                .EQ $00,01
  1030 PTR2                .EQ $02,03
  1040 BIT6.AS.LSB         .EQ $04
  1050 *--------------------------------
  1060 PAGE.1              .EQ $2000 - 3FFF
  1070 PAGE.2              .EQ $4000 - 5FFF
  1080 *--------------------------------
  1090 KEYBOARD            .EQ $C000
  1100 STROBE              .EQ $C010
  1110 SPEAKER             .EQ $C030
  1120 *--------------------------------
  1130 STORE.80.OFF        .EQ $C000
  1140 STORE.80.ON         .EQ $C001
  1150 COLUMN.80.OFF       .EQ $C00C
  1160 COLUMN.80.ON        .EQ $C00D
  1170 READ.COLUMN.80      .EQ $C01F
  1180 GRAPHICS.ON         .EQ $C050
  1190 GRAPHICS.OFF        .EQ $C051
  1200 MIXED.OFF           .EQ $C052
  1210 MAIN.PAGE           .EQ $C054
  1220 AUX.PAGE            .EQ $C055
  1230 HIRES.GRAPHICS      .EQ $C057
  1240 AN3.OFF             .EQ $C05E
  1250 AN3.ON              .EQ $C05F
  1260 IOU.DIS.ON          .EQ $C07E
  1270 *--------------------------------
  1280 DAVID.C.JOHNSON
  1290        JSR GEN.XLATE.MONO.TABLES
  1300        STX IOU.DIS.ON
  1310 *---Set up the screen mode-------
  1320        LDA READ.COLUMN.80   REMEMBER 40/80 STATE
  1330        PHA
  1340        STA STORE.80.ON
  1350        BIT MAIN.PAGE        VIEW AS REGULAR HI-RES
  1360        BIT HIRES.GRAPHICS
  1370        BIT MIXED.OFF        FULL 192 LINES
  1380        STA AN3.ON           (DOUBLE HI-RES OFF)
  1390        BIT GRAPHICS.ON
  1400 *---Build pointer----------------
  1410        LDA /PAGE.1
  1420        STA PTR1+1
  1430        LDY #0
  1440        STY PTR1
  1450 *---Process six lines of pixels---
  1460 .1     LDA #0            CLEAR BIT6 FLAG
  1470        STA BIT6.AS.LSB
  1480 .2     LDA (PTR1),Y
  1490        TAX               SAVE BYTE OF PIXELS
  1500        BPL .3            ...NO HALF-PIXEL HERE
  1510        LDA BIT6.AS.LSB   GET PREVIOUS BIT6
  1520        BPL .4            ...ALWAYS
  1530 .3     LDA #0
  1540 .4     BIT AUX.PAGE
  1550        ORA XLATE.MONO.AUX,X
  1560        STA (PTR1),Y
  1570        BIT MAIN.PAGE
  1580        LDA XLATE.MONO.MAIN,X
  1590        STA (PTR1),Y
  1600        TXA               GET BYTE OF PIXELS
  1610        ROL               FIND BIT 6
  1620        ROL
  1630        LDA #0
  1640        ROL
  1650        STA BIT6.AS.LSB
  1660        INY
  1670        TYA
  1680        AND #$7F
  1690        CMP #$28
  1700        BEQ .1       START A NEW LINE
  1710        CMP #$50
  1720        BEQ .1       START A NEW LINE
  1730        CMP #$78
  1740        BCC .2       ...IN SAME LINE
  1750        TYA
  1760        ADC #7       HOP OVER 8 BYTES
  1770        TAY
  1780        BNE .1       START A NEW LINE
  1790        INC PTR1+1   START A NEW 6-LINE GROUP
  1800        LDA PTR1+1
  1810        AND #$1F
  1820        BNE .1       ...UNLESS END OF SCREEN
  1830 *---View the results-------------
  1840        JSR WAIT.FOR.ANY.KEY
  1850        STA COLUMN.80.OFF
  1860        STA AN3.OFF  DOUBLE HIRES ON
  1870        STA AN3.ON
  1880        STA AN3.OFF
  1890        STA AN3.ON
  1900        STA COLUMN.80.ON
  1910        STA AN3.OFF
  1920        JSR WAIT.FOR.ANY.KEY
  1930        STY PTR2
  1940        LDX /PAGE.2
  1950        STX PTR2+1
  1960        LDA /PAGE.1
  1970        STX PTR1+1
  1980 *------------------------------------
  1990 *   Setup for BSAVE:     After BLOAD:
  2000 .6     LDA (PTR1),Y      lda (ptr1),y
  2010        STA (PTR2),Y      bit aux.page
  2020        BIT AUX.PAGE      sta (ptr1),y
  2030        LDA (PTR1),Y      lda (ptr2),y
  2040        BIT MAIN.PAGE     bit main.page
  2050        STA (PTR1),Y      sta (ptr1),y
  2060        INY
  2070        BNE .6
  2080        INC PTR1+1
  2090        INC PTR2+1
  2100        DEX
  2110        BNE .6
  2120        LDA #$02     (/PIXEL) MARK AS DBLHIRES
  2130        STA PAGE.1+$78               FOTO-FILE
  2140 *--------------------------------
  2150        STA AN3.ON
  2160        BIT GRAPHICS.OFF
  2170        PLA          RESTORE 40/80 STATE
  2180        BMI .7
  2190        STA STORE.80.OFF
  2200        STA COLUMN.80.OFF
  2210 .7     RTS
  2220 *--------------------------------
  2230 *--------------------------------
  2240 GEN.XLATE.MONO.TABLES
  2250        LDX #0
  2260 .1     LDY #7
  2270        TXA
  2280        ASL
  2290 .2     ASL
  2300        PHP
  2310        ROL XLATE.MONO.AUX,X
  2320        ROL XLATE.MONO.MAIN,X
  2330        PLP
  2340        ROL XLATE.MONO.AUX,X
  2350        ROL XLATE.MONO.MAIN,X
  2360        DEY
  2370        BNE .2
  2380        TXA
  2390        BPL .3
  2400        ASL XLATE.MONO.AUX,X
  2410        ROL XLATE.MONO.MAIN,X
  2420 .3     ASL XLATE.MONO.AUX,X
  2430        ROL XLATE.MONO.MAIN,X
  2435        LSR XLATE.MONO.AUX,X
  2440        ASL XLATE.MONO.MAIN,X
  2450        LSR XLATE.MONO.MAIN,X
  2460        INX
  2470        BNE .1
  2480        RTS
  2490 *--------------------------------
  2500 WAIT.FOR.ANY.KEY
  2510        LDY #0
  2520 .1     LDA SPEAKER
  2530 .2     DEX
  2540        BNE .2
  2550        BIT KEYBOARD
  2560        BMI .3       GOT A KEY
  2570        DEY
  2580        BPL .1
  2590        BMI .2
  2600 .3     STA STROBE
  2610        RTS
  2620 *--------------------------------
  2630        .BS *+255/256*256-*
  2640 *--------------------------------
  2650 XLATE.MONO.AUX      .BS 256
  2660 XLATE.MONO.MAIN     .BS 256
  2670 *--------------------------------

Moore Screen Tricks Robert C. Moore

Here are two short routines that are easy to understand. The problem is this: what do they do? I think you readers will enjoy the challenge of finding out!

  1000 *SAVE S.MOORE'S CHALLENGE
  1010 *--------------------------------
  1020 MON.CV .EQ $25
  1030 BAS    .EQ $28,29
  1040 MON.VTAB            .EQ $FC22
  1050 COUT                .EQ $FDED
  1060 *--------------------------------
  1070        .OR $300
  1080 *--------------------------------
  1090 SUB1   LDY #39      For Y = 39 to 0
  1100 .1     LDA (BAS),Y
  1110        EOR #$E0
  1120        CLC
  1130        ADC #$E0
  1140        STA (BAS),Y
  1150        DEY
  1160        BPL .1
  1170        RTS
  1180 *--------------------------------
  1190 SUB2   LDY #39      For Y = 39 to 0
  1200 .1     LDA (BAS),Y
  1210        LSR
  1220        LSR
  1230        LSR
  1240        LSR
  1250        LSR
  1260        TAX
  1270        LDA TABLE,X
  1280        EOR (BAS),Y
  1290        STA (BAS),Y
  1300        DEY
  1310        BPL .1
  1320        RTS
  1330 *--------------------------------
  1340 TABLE  .HS C0.80.00.80.00.80.C0.80
  1350 *--------------------------------

Here is a little Applesoft routine that may be used to exercise either SUB1 or SUB2. Change line 120 as indicated to select which subroutine will be used.

     10  PRINT  CHR$ (4)"PR#3"
     20  PRINT  CHR$ (17);: REM  Set to 40-column
     30  PRINT  CHR$ (12);: REM  HOME and clear
     40  PRINT  CHR$ (27);
     50  GOSUB 200: REM  Lines 1 to 6
     60  PRINT 
     70  GOSUB 200: REM  Lines 8 to 13
     80  PRINT  CHR$ (24)
     90  GOSUB 200

     110  FOR V = 1 TO 6: VTAB V
     120  CALL 768: REM  768=SUB1 or 783=SUB2
     130  FOR I = 0 TO 999: NEXT 
     140  NEXT 
     150  GOTO 110

     200  FLASH : GOSUB 300
     210  INVERSE : GOSUB 300
     220  NORMAL : GOSUB 300
     230  RETURN 

     300  PRINT "0123456789 ABCDEFGHIJKLMNOPQRSTUVWXYZ"
     310  PRINT "0123456789 abcdefghijklmnopqrstuvwxyz"
     320  RETURN 

The following little Applesoft subroutine will put every possible value on the screen, in eight lines of 32 characters each. You might try running SUB1 and SUB2 with this information on the screen, too.

     500  FOR V = 0 TO 7: VTAB V + 1
     510 A =  PEEK (40) +  PEEK (41) * 256
     520  FOR H = 0 TO 31
     530  POKE A + H,V * 32 + H
     540  NEXT : NEXT 
     550  RETURN 

Text Window Inverter Bob Sander-Cederlof

Bob Moore's challenge prompted me to construct the following useful utility. This program lets you set up a table of screen windows, and then invert whatever is in any particular window at will.

The window table consists of a list of window descriptors. Each window descriptor is four bytes, giving the top line, the bottom line, the leftmost character, and the rightmost character. For example, a full-screen window would be 0, 23, 0, 39. My program as given handles only the 40-column screen. It would be a relatively minor modification to change it to handle the 80-column screen.

The routine can be thought of in two steps. The first problem is how to scan through every character inside the window. I do this with a pair of nested loops. The outer loop scans from line to line, and the inner loop scans the characters within a line. The second problem is how to "invert" a character.

After studying the Apple screen character set, I decided to do everything with MouseText switched on. This gives me inverse lower-case letters, which are not available when MouseText is switched off. I came up with the following inversion rules:

       Current        Inverted     EOR
        Value          Value      Value
       ------         --------
       $A0...BF       $20...3F    $80
       $C0...DF       $00...1F    $C0
       $E0...FF       $60...7F    $80

Values in the ranges $40...5F and $80...9F should not be changed, as doing so would make nonsense on the screen.

All of the changes can be made by using an EOR opcode with the proper mask. Bob Moore put these values in a table, but I did not want to use the X-register to index into a table, because I already was using it to slect which window I was using. Therefore I figured out a scheme that COMPUTES the proper EOR value. You can see it in lines 1120-1210 of the program.

Lines 1350-1530 are a sample driver, to let you play with the capabilities of the Window Inverter subroutine. Lines 1360-1370 print a control-Q to select the 40-column mode of Apple 80-column firmware. Line 1380 turns on the MouseText character set. Lines 1390-1410 wait until you type a key on the keyboard. If the key is <RETURN>, lines 1420-1460 will restore to 80-column mode and quit. Otherwise, the low-order three bits are used as an index to pick one of eight windows I set up in lines 1540-1620. (These are just sample windows, varying from one character to the whole screen.) It is fun to run this sample program, and then just type any sentence or data. The screen gets flipped every-which-a-way as you type.

A subroutine like this does have practical value. A long time ago I used one in a special program I wrote for the American Heart Association. The program ws menu-driven, but there was no keyboard! The user held a lightpen, and pointed it at the menu selection he wanted. The menu was arranged in a matrix, with varying numbers of items. One time it might be nine items, arranged like a tic-tac-toe matrix. Another time it might be two rows of four each, and so on. Whatever item the lightpen was pointing at would be displayed in inverse, while all the others were in normal mode. A switch on the pen barrel told the computer to go with the "high-lighted" selection.

To make it easier to write the menu on the screen, I had another program that used the same window table for printing messages. The whole thing operated so fast that it seemed instantaneous.

  1000 *SAVE S.WINDOW INVERTER
  1010 *--------------------------------
  1020 MON.CV    .EQ $25
  1030 BAS       .EQ $28,29
  1033 *--------------------------------
  1040 MON.VTAB  .EQ $FC22
  1050 COUT      .EQ $FDED
  1060 *--------------------------------
  1070 WINDOW.INVERT.40
  1080        LDA WINDOWS,X     Y-TOP
  1090        STA MON.CV
  1100 .1     JSR MON.VTAB
  1110        LDY WINDOWS+2,X   X-LEFT
  1120 .2     LDA (BAS),Y
  1130        ASL
  1140        BCS .4
  1150        BMI .5
  1160 .3     ORA #$BF
  1170        EOR #$7F
  1180        BMI .6       ...ALWAYS
  1190 .4     BMI .3
  1200 .5     ASL
  1210        AND #$80
  1220 .6     EOR (BAS),Y
  1230        STA (BAS),Y
  1240        TYA
  1250        INY
  1260        CMP WINDOWS+3,X   X-RIGHT
  1270        BCC .2
  1280        LDA MON.CV
  1290        INC MON.CV
  1300        CMP WINDOWS+1,X   Y-BOTTOM
  1310        BCC .1
  1320        DEC MON.CV
  1330        RTS
  1340 *--------------------------------
  1350 T
  1360        LDA #"Q"-$40
  1370        JSR COUT
  1380        STA $C00F    SELECT MOUSE TEXT
  1390 .1     LDA $C000
  1400        BPL .1
  1410        STA $C010
  1420        CMP #$8D
  1430        BNE .2
  1440        LDA #"R"-$40
  1450        JSR COUT
  1460        RTS
  1470 .2     AND #7
  1480        ASL
  1490        ASL
  1500        TAX
  1510        JSR WINDOW.INVERT.40
  1520        JMP .1
  1530 *--------------------------------
  1540 WINDOWS
  1550        .DA #00,#23,#00,#39     FULL SCREEN
  1560        .DA #05,#20,#05,#20
  1570        .DA #07,#17,#08,#16
  1580        .DA #15,#22,#15,#30
  1590        .DA #00,#10,#30,#39
  1600        .DA #04,#06,#32,#36
  1610        .DA #11,#13,#19,#21
  1620        .DA #12,#12,#20,#20
  1630 *--------------------------------

Woz's Five-digit Math Puzzler Bob Sander-Cederlof

Ten years ago, before Woz was well-known or wealthy, he published a 5-digit "Mastermind" puzzle in Dr. Dobbs Journal (Sept 1976). The program was written in 6502 assembly language, naturally, and would work as printed in an Apple I. Not long ago I was looking through some back issues and came across it.

Being overcome by nostalgia, I just had to type it in and make it work in an Apple II. I added a few minor things, such as the ability to stop playing by typing a <RETURN>. (I also put in a secret way to "cheat", so you can impress your friends with your ability to beat the computer.)

Woz has always displayed a knack for getting the most out of every byte. In fact, the salesman who sold me my first Apple II back in 1977 convinced me with the remark, "I don't know how they got so much stuff in there!" The following program is yet another example. He used a lot of coding tricks, including some that were new to me. I am not going to point them all out, but you will enjoy going on a treasure hunt: look for negative indexing in page-zero arrays, automatic initialization of loops, and other sort-of-sneaky tricks. But keep looking, because there are some even-sneakier tricks! I didn't see some of them until I tried my hand at "improving" the code.

  1000 *SAVE S.WOZNIAK
  1010 *--------------------------------
  1020 *   A Number Game for the 6502, by Steve Wozniak
  1030 *   Published in Dr. Dobb's Journal, September 1976.
  1040 *--------------------------------
  1050 *   Adapted for the Apple II by Bob Sander-Cederlof
  1060 *--------------------------------
  1070 KEYBOARD .EQ $C000
  1080 STROBE   .EQ $C010
  1090 *--------------------------------
  1100 MON.RDKEY  .EQ $FD0C
  1110 MON.PRBYTE .EQ $FDDA
  1120 MON.CROUT  .EQ $FD8E
  1130 MON.COUT   .EQ $FDED
  1140 *--------------------------------
  1150 TRIES  .EQ $00
  1160 RND2L  .EQ $03
  1170 N      .EQ $04 ...08
  1180 GUESS  .EQ $09 ...0D
  1190 *--------------------------------
  1200 RNDL   .EQ $4E
  1210 RNDH   .EQ $4F
  1220 *--------------------------------
  1230 T
  1240 MSTMND
  1250        LDX #Q.RDY   Print "READY?"
  1260 MSGLP  LDA MSG-1,X
  1270        JSR MON.COUT
  1280        DEX
  1290        BNE MSGLP
  1300 *---Clear TRY count--------------
  1310        STX TRIES    X = 0
  1320 *---Wait until player ready------
  1330 *   Creates random number in RNDH,RNDL
  1340        JSR MON.RDKEY
  1350        cmp #$8D     Stop if <RETURN>
  1360        bne NXTRY
  1370        rts
  1380 *---Count the try----------------
  1390 *   (X-reg is 0 now)
  1400 NXTRY  SEC
  1410        SED
  1420        TXA          X=0
  1430        ADC TRIES    Add 1 to tries in BCD mode
  1440        STA TRIES
  1450        CLD
  1460 *---Display the try count--------
  1470 NXTLIN JSR MON.CROUT
  1480        LDA TRIES    Print number of tries in BCD
  1490        JSR MON.PRBYTE
  1500        LDA #" "     BLANK
  1510        TAY          $A0, bits 43210 all clear
  1520        JSR MON.COUT Print the space
  1530 *---Build array of digits--------
  1540        LDA RNDL     Use the random number
  1550        STA RND2L       without changing it
  1560        LDA RNDH     x5554443 11122233
  1570 *                   (Remember that Y-reg holds $A0)
  1580        LDX #5       Do 5 digits
  1590 .1     STY N-1,X    Be sure bits 43210 are clear
  1600        LDY #3       Shift in next three bits from RND
  1610 .2     LSR
  1620        ROL RND2L
  1630        ROL N-1,X
  1640        DEY
  1650        BNE .2       Next bit
  1660        DEX
  1670        BNE .1       Next digit
  1680 *---Read player's guess----------
  1690 *   X- and Y-regs are 0 now
  1700        JSR GET.GUESS
  1710        BCC NXTLIN
  1720 *---Check digits in position-----
  1730 *   (X-reg is -5 now)
  1740        LDY #-5
  1750        LDA #" "     Print a space
  1760 .4     JSR MON.COUT   (or a "+")
  1770 .5     LDA GUESS+5,X
  1780        CMP N+5,X
  1790        BNE .6       ...not an exact match
  1800        STY N+5,X    ...matches, so clobber it
  1810        LDA #"+"        and print a "+"
  1820        STA GUESS+5,X   (clobber here too)
  1830        INY          Count the +
  1840        BNE .4       ...not 5 yet, try another
  1850        LDX #Q.WIN   All 5 correct!
  1860        BNE MSGLP    Say so, invite another game.
  1870 .6     INX          Next digit position
  1880        BNE .5
  1890 *---Check for digits out of position---
  1900        LDY #-5      For each digit in guess...
  1910 .7     LDX GUESS+5,Y     (Cannot use LDA GUESS+5,Y
  1920        TXA                because that would not wrap!)
  1930        LDX #-5         For each digit in puzzle...
  1940 .8     CMP N+5,X
  1950        BNE .9          ...different
  1960        STY N+5,X       ...same, clobber in puzzle
  1970        LDA #"-"           and print a "-"
  1980        JSR MON.COUT
  1990 .9     INX             Next puzzle digit
  2000        BNE .8
  2010        INY          Next guess digit
  2020        BNE .7
  2030        BEQ NXTRY    ...always, and X must = 0
  2040 *--------------------------------
  2050 MSG    .AS -/?YDAER/
  2060        .HS 8D
  2070        .HS 8D
  2080 Q.RDY  .EQ *-MSG
  2090        .AS -/NIW UOY +/
  2100 Q.WIN  .EQ *-MSG
  2110 *--------------------------------
  2120 GET.GUESS
  2130 .1     LDA KEYBOARD      Read char from keyboard
  2140        BPL .1
  2150        STA STROBE        Clear the strobe
  2160        CMP #"8"          <My little secret!>
  2170        BNE .2
  2180        LDA N+4,X         <Cheat!>
  2190        ORA #"0"
  2200 .2     JSR MON.COUT      Echo the character
  2210        EOR #"0"          Convert to binary if 0-7
  2220        CMP #8
  2230        BCS .3            ...Not digit, start try over
  2240        STA GUESS+4,X     Valid, save the guessed digit
  2250        DEX
  2260        CPX #-5
  2270        BNE .1            Input next digit
  2280        RTS
  2290 .3     CLC
  2300        RTS
  2310 *--------------------------------

Automatic SETUP Revised Bill Morgan

Last month we presented a modification to the ProDOS S-C Macro Assembler which automatically EXEC's a SETUP file when the assembler begins execution. It's very convenient to just boot up the assembler and have everything we need installed into /RAM, but after a few days of using the new code I started wanting improvements.

One error I made last month was stating that "-" doesn't work in this circumstance. It didn't work when I first tried it, but there must have been some other problem because it does just fine now.

Once Bob started using this routine he came up with several enhancements as well. Here's the SETUP file he uses:

     -PRODRIVE
     PREFIX/RAM
     BLOAD /HARD1/SCASM.SYSTEM,TSYS,A$2000
     BSAVE        SCASM.SYSTEM,TSYS,A$2000,L17920
     BLOAD /HARD1/UTIL.SYSTEM,TSYS,A$2000,L$4000
     BSAVE        UTIL.SYSTEM,TSYS,A$2000,L$4000
     BLOAD /HARD1/UTIL.SYSTEM,TSYS,A$2000,B$4000,L$26FB
     BSAVE        UTIL.SYSTEM,TSYS,A$2000,B$4000,L$26FB
     BLOAD /HARD1/BASIC.SYSTEM,TSYS,A$2000
     BSAVE        BASIC.SYSTEM,TSYS,A$2000,L10240
     BLOAD /HARD1/STARTUP,TBAS,A$801,L737
     BSAVE        STARTUP,TBAS,A$801,L737

There are a couple of interesting things in that file. UTIL.SYSTEM is too big to BLOAD in one piece under the assembler, so he handles it in two sections, using the L and B parameters to concatenate the second piece onto the end of the first one. Another thing that didn't occur to me was to transfer an Applesoft STARTUP program with the same technique I've been using for SYS files.

One problem we ran into was restarting the assembler from /RAM and having it unnecessarily reload everything. The solution to that is to check the Global Page DEVNUM byte to see if we're coming from /RAM, and if so skip SETUP. Another improvement is to avoid manually looking up the address of the SC.INIT routine inside the assembler. By JSRing to a JMP ($8001) we can automatically call that routine, wherever it might be. We do still need to confirm that the JMP $8000 instruction that starts the assembler is located at $206A, and that the space beginning at $21B0 is empty.

  1000 *SAVE S.STARTER.PLUS
  1010 *--------------------------------
  1020 WBUF         .EQ $200
  1030  
  1040 SC.COLDSTART .EQ $8000
  1050 SC.WARMSTART .EQ $8003
  1060  
  1070 DOSCMD       .EQ $BE03
  1080 DEVNUM       .EQ $BF30
  1090 *--------------------------------
  1100        .OR $206A
  1110        JMP STARTER
  1120  
  1130        .OR $21B0
  1140 STARTER
  1150        LDA DEVNUM   Slot/Drive of last device used
  1160        CMP #$B0     was it S3,D2 (/RAM)?
  1170        BEQ .3       ...yes, no need to redo SETUP
  1180  
  1190        JSR SCINIT   get assembler ready
  1200        LDX #0
  1210 .1     LDA COMMAND,X
  1220        BEQ .2
  1230        STA WBUF,X   stuff command into buffer
  1240        INX
  1250        BNE .1       always
  1260 .2     JSR DOSCMD   do it!
  1270        JMP SC.WARMSTART  just in case
  1280  
  1290 .3     JMP SC.COLDSTART
  1300  
  1310 SCINIT JMP (SC.COLDSTART+1)
  1320 *--------------------------------
  1330 COMMAND .AS -/-SETUP/
  1340         .HS 8D00
  1350        .lif

Another Selector Note Bill Morgan

It's been a long time since we published a program that has drawn as much enthusiastic response as Bob's new ProDOS Program Selector (AAL July 86). That program is a true how-did-I-ever-get-along-without-it?

Like several other readers, I have my own small improvement to suggest. When the list of volumes available is displayed the cursor bar always comes up on the first item, which is usually /RAM, because that's how the ProDOS ONLINE call returns the list. But I nearly always want to select something from the hard disk, which is always the second item in the list. Similarly, once I have chosen a volume the cursor bar appears on the first item in the list of SYS files, which is usually PRODOS. Well most of the time I'm switching to SCASM.SYSTEM, the second item in the list. How can I make the cursor start on my default choice?

The defaults are set by the STY SEL.LINE instructions at lines 1530 and 1840, with Y=0 from the previous instructions. Therefore all I have to do to start the cursor on the second line is add two lines:

     1525       INY
     1835       INY

If you want to begin on some other line, just make those into LDY #n-1, where n is line you want. Note that adding two two-byte instructions uses up almost all of the extra space available, so watch out if you've made other changes.


New Rak-Ware Utility "ScreenGen" Bob Kovacs

ScreenGen is a new utility for transfering hi-res graphics screens from the Macintosh to the Apple II. You can use the sophisticated tools of the Macintosh to easily create hi-res screens for the Apple II.

The ScreenGen program resides in the Apple II only. No special software is neede for the MAC. Any MAC screen or document that can be output to an Imagewriter printer can be transferred via ScreenGen. Since the normal Apple hi-res screen is only 280 by 192 dots, which is much smaller than the MAC screen, ScreenGen limits the amount of data transferred to fill one Apple II screen.

I am selling ScreenGen for $35, and the disk includes the commented source code in S-C Macro Assembler format. Since the source code is included, you will find it easy to adapt ScreenGen to a specific application.

Basically, ScreenGen is a developer's tool. I designed it to fulfill a specific need I had some time ago. I figure there must be a few more folks out there who could also use it.

My application involved the design of a computerized point-of-sale demonstration program used at a local Macy's department store. The program acted like a skilled musician/salesman to actively demonstrate the operation of a music keyboard. Since the keyboard had a MIDI interface it was relatively straight-forward to have it play music, change the voice settings, and perform more sophisticated operations to show off all the bells and whistles. The program was interactive and menu driven.

The program operated on an Apple //c (which they also sell at Macy's) and a number of hi-res screens were needed to show pictures of the keyboard and its function keys for each part of the demonstration. I started off using MousePaint on the Apple II and found it difficult to use (let's face it, I've been spoiled by MacPaint). And so ScreenGen was born!

To use ScreenGen, you need an Apple II, II+, or //e with a SuperSerial Card, or an Apple //c (which has the serial "card" built-in). You also need a Macintosh computer with an Imagewriter serial interface cable (or equivalent cable for Apple //c). Pictures are sent from the MAC as though they are going to the printer, at 9600 baud. A complete picture takes about 15 seconds.

If ScreenGen sounds like a utility you can use in your development, you can order it directly from Rak-Ware, or from Bob at S-C Software.


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 $14 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 CORPORATION, all rights reserved. (Apple is a registered trademark of Apple Computer, Inc.)