histcomp:apple_ii

Apple ][

The bulk of this page will focus on the Enhanced IIe, both because it was the most popular of the line and because it is the model we have.

Despite the 6502's 64K address space, an Apple II could have significantly more RAM and ROM than that. The IIe came standard with 64K built into the motherboard, which could be doubled with an extended 80-column text card. Other peripheral cards tended to contain their own onboard RAM/ROM. All of this extra memory is accessible through bank switching.

  • \$0000–\$00FF: zero page
  • \$0100–\$01FF: stack, Applesoft temporary storage
  • \$0200–\$02FF: keyboard/diskette input buffer
  • \$0300–\$03CF: user assembly programs
  • \$03D0–\$03FF: subroutine vectors for DOS, Applesoft, and system monitor
  • \$0400–\$07FF: text/low-res page 1
  • \$0800–\$0BFF: text/low-res page 2; more commonly used for Applesoft program storage
  • \$0C00–\$1FFF: free for use
  • \$2000–\$3FFF: high-res page 1
  • \$4000–\$5FFF: high-res page 2
  • \$6000–\$BFFF: normally free for use; \$9600 and above is used by DOS
  • \$C000–\$C0FF: I/O
  • \$C100–\$C1FF: slot 1 ROM
  • \$C200–\$C2FF: slot 2 ROM
  • \$C300–\$C3FF: slot 3 ROM
  • \$C400–\$C4FF: slot 4 ROM
  • \$C500–\$C5FF: slot 5 ROM
  • \$C600–\$C6FF: slot 6 ROM
  • \$C700–\$C7FF: slot 7 ROM
Table 1: Soft switches, status, and I/O addresses [1]
Address Direction Symbolic name Description
\$C000 W 80STOREOFF Allow PAGE2 to switch between video page 1 and page 2
R KBD Keyboard data (bits 0–6)
R7 KBD 1 = keyboard stroke is on
0 = keyboard stroke is off
\$C001 W 80STOREON Allow PAGE2 to switch between main and aux video memory
\$C002 W RAMRDOFF Read-enable main memory from \$0200–\$BFFF
\$C003 W RAMRDON Read-enable aux memory from \$0200–\$BFFF
\$C004 W RAMWRTOFF Write-enable main memory from \$0200–\$BFFF
\$C005 w RAMWRTON Write-enable aux memory from \$0200–\$BFFF
\$C006 W INTCXROMOFF Enable slot ROM from \$C100–\$CFFF
\$C007 W INTCXROMON Enable main ROM from \$C100–\$CFFF
\$C008 W ALTZPOFF Enable main memory from \$0000–\$01FF and make main BSR available
\$C009 W ALTZPON Enable aux memory from \$0000–\$01FF and make aux BSR available
\$C00A W SLOTC3ROMOFF Enable main ROM from \$C300–\$C3FF
\$C00B W SLOTC3ROMON Enable slot ROM from \$C300–\$C3FF
\$C00C W 80COLOFF Turn off 80-column display
\$C00D W 80COLON Turn on 80-column display
\$C00E W ALTCHARSETOFF Turn off alternate characters
\$C00F W ALTCHARSETON Turn on alternate characters
\$C010 R7 AKD 1 = a key is being pressed
0 = all keys are released
RW KBDSTRB Clear keyboard strobe
\$C011 R7 BSRBANK2 1 = bank 2 of BSR is available
0 = bank 1 of BSR is available
\$C012 R7 BSRREADRAM 1 = BSR is active for read operations
0 = \$D000–\$FFFF ROM is active for read operations
\$C013 R7 RAMRD 0 = main \$0200–\$BFFF is active for read operations
1 = aux \$0200–\$BFFF is active for read operations
\$C014 R7 RAMWRT 0 = main \$0200–\$BFFF is active for write operations
1 = aux \$0200–\$BFFF is active for write operations
\$C015 R7 INTCXROM 1 = main \$C100–\$CFFF ROM is active
0 = slot \$C100–\$C1FF ROM is active
\$C016 R7 ALTZP 1 = aux zero page & stack are active; aux BSR is available
0 = main zero page & stack is active; main BSR is available
\$C017 R7 SLOTC3ROM 1 = slot \$C3 ROM is active
0 = main \$C3 ROM is active
\$C018 R7 80STORE 1 = PAGE2 switches main/aux
0 = PAGE2 switches video pages
\$C019 R7 VERTBLANK 1 = vertical retrace is on
0 = vertical retrace is off
\$C01A R7 TEXT 1 = a text mode is active
0 = a graphics mode is active
\$C01B R7 MIXED 1 = mixed graphics and text
0 = full-screen graphics
\$C01C R7 PAGE2 1 = video page 2 selected OR aux video page selected
\$C01D R7 HIRES 1 = high-res graphics
0 = low-res graphics
\$C01E R7 ALTCHARSET 1 - alternate character set is on
0 = primary character set is on
\$C01F R7 80COL 1 = 80-column display is on
0 = 40-column display is on
\$C020 R CASSOUT Toggle the state of the cassette output port
\$C021
\$C022
\$C023
\$C024
\$C025
\$C026
\$C027
\$C028
\$C029
\$C02A
\$C02B
\$C02C
\$C02D
\$C02E
\$C02F
\$C030 R SPEAKER Toggle the state of the speaker
\$C031
\$C032
\$C033
\$C034
\$C035
\$C036
\$C037
\$C038
\$C039
\$C03A
\$C03B
\$C03C
\$C03D
\$C03E
\$C03F
\$C040 R GCSTROBE Generate a game I/O connector strobe signal
\$C041
\$C042
\$C043
\$C044
\$C045
\$C046
\$C047
\$C048
\$C049
\$C04A
\$C04B
\$C04C
\$C04D
\$C04E
\$C04F
\$C050 RW TEXTOFF Select graphics mode
\$C051 RW TEXTON Select text mode
\$C052 RW MIXEDOFF Use full screen for graphics
\$C053 RW MIXEDON User graphics with four lines of text
\$C054 RW PAGE2OFF Select page 1 display (or main video memory)
\$C055 RW PAGE2ON Select page 2 display (or aux video memory)
\$C056 RW HIRESOFF Select low-res graphics
\$C057 RW HIRESON Select high-res graphics
\$C058 RW CLRAN0 Turn off annunciator 0
\$C059 RW SETAN0 Turn on annunciator 0
\$C05A RW CLRAN1 Turn off annunciator 1
\$C05B RW SETAN1 Turn on annunciator 1
\$C05C RW CLRAN2 Turn off annunciator 2
\$C05D RW SETAN1 Turn on annunciator 2
\$C05E RW CLRAN3 Turn off annunciator 3
\$C05F RW SETAN1 Turn on annunciator 3
\$C060 R7 CASSIN 1 = cassette input is on
\$C061 R7 PB0 1 = push button 0 is on
\$C062 R7 PB1 1 = push button 1 is on
\$C063 R7 PB2 1 = push button 2 is on
\$C064 R7 GC0 0 = game controller 0 timed out
\$C065 R7 GC1 0 = game controller 1 timed out
\$C066 R7 GC2 0 = game controller 2 timed out
\$C067 R7 GC3 0 = game controller 3 timed out
\$C068 R GCRESET Reset the game controllers
\$C069
\$C06A
\$C06B
\$C06C
\$C06D
\$C06E
\$C06F
\$C070
\$C071
\$C072
\$C073
\$C074
\$C075
\$C076
\$C077
\$C078
\$C079
\$C07A
\$C07B
\$C07C
\$C07D
\$C07E
\$C07F
\$C080 R READBSR2 Select bank 2, read BSR, write-protect BSR
\$C081 RR WRITEBSR2 Select bank 2, read ROM, write-enable BSR
\$C082 R OFFBSR2 Select bank 2, read ROM, write-protect BSR
\$C083 RR RDWRBSR2 Select bank 2, read BSR, write-enable BSR
\$C084
\$C085
\$C086
\$C087
\$C088 R READBSR1 Select bank 1, read BSR, write-protect BSR
\$C089 RR WRITEBSR1 Select bank 1, read ROM, write-enable BSR
\$C08A R OFFBSR1 Select bank 1, read ROM, write-protect BSR
\$C08B RR RDWRBSR1 Select bank 1, read BSR, write-enable BSR
\$C08C
\$C08D
\$C08E
\$C08F
\$C090–\$C09F Reserved for use by slot 1
\$C0A0–\$C0AF Reserved for use by slot 2
\$C0B0–\$C0BF Reserved for use by slot 3
\$C0C0–\$C0CF Reserved for use by slot 4
\$C0D0–\$C0DF Reserved for use by slot 5
\$C0E0–\$C0EF Reserved for use by slot 6
\$C0F0–\$C0FF Reserved for use by slot 7

To determine the exact model and version, examine \$FBB3 and \$FBC0. If \$FBB3 contains \$06, the computer is a IIe or IIc. \$FBC0 can contain the following values: [2]

  • \$EA: IIe with original ROMs
  • \$E0: IIe with enhanced ROMs
  • \$00: IIc
Table 2: Monitor commands [3]

In order to run CP/M, a Z80 soft card is required. While we do not currently possess one, it should be possible to find one online — or we may be able to assemble our own from scratch using available schematics [4].

As with the rest of this page, we will focus on cards our machine has installed.

The Apple IIe has eight expansion slots (7 regular and 1 auxiliary). This alone is indicative of a completely different era of Apple's history, one in which the engineering team held more sway than the marketing team.

A RAM disk/memory expansion. ProDOS automatically registers it as a volume named /RAMs (where s is the slot number where the card is installed), and AppleWorks appears to relocate some of itself onto the card. Because the card uses volatile RAM, anything saved to the card will be lost when the computer is switched off unless external power is applied to the card. Applied Engineering sold a device to do just that, but we do not have one, nor do we particularly wish to.

The particular revision we have contains a total of 1 MB of RAM.

This snippet is particularly useful for writing peripheral card ROM, where the code needs to function irrespective of its installed slot. It works by calling a “subroutine” consisting entirely of an RTS (\$FF58 is one of a handful of addresses that Apple guaranteed will contain an RTS instruction). Upon returning, $100+S contains the high byte of the return (calling) address.

If calling from a peripheral card, the slot number can be identified by ANDing the result with 0F.

; stores the high byte of the execution address in the A register
; clobbers: A, X
getpage:
    JSR $FF58    ; push the return address to the stack
    TSX          ; use stack pointer as index to stack page
    LDA $100,X   ; get high byte of return address
    RTS

We don't have to reinvent the wheel for this one — the system monitor includes a handy routine called PRBYTE (\$FDDA) for just this task, shown below [5]:

PRBYTE:    PHA
           LSR A
           LSR A
           LSR A
           LSR A
           JSR PRHEXZ    ; =$FDE5
           PLA
PRHEX:     AND #$0F
PRHEXZ:    ORA #$B0
           CMP #$BA
           BCC COUT      ; =$FDED 
           ADC #$06
COUT:      JMP (CSWL)    ; =$0036, user output routine

To make use of it from Applesoft, load the following anywhere into memory:

JSR $DEBE      ; CHKCOM - skips comma in Applesoft parsing
JSR $DFE3      ; GETPNT - get pointer to variable data, put it in $83...$84
LDY #$00
LDA ($83),Y    ; get high byte from VARPNT
JSR $FDDA      ; PRBYTE
INY
LDA ($83),Y    ; get low byte from VARPNT
JMP $FDDA      ; PRBYTE (will RTS for us)

Then it can be called from Applesoft like so (assuming the program was loaded at \$0300):

10 LET X% = 69
20 CALL 768,X%

Useful as a benchmark. The computer must be in 80-column mode for it to display properly.

10 FOR Y=-12 TO 12
20 FOR X=-39 TO 39
30 CA=X*0.0458
40 CB=Y*.08333
50 A=CA
60 B=CB
70 FOR I = 0 TO 15
80 T=A*A-B*B+CA
90 B=2*A*B+CB
100 A=T
110 IF(A*A+B*B)>4 GOTO 200
120 NEXT I
130 PRINT " ";
140 GOTO 210
200 IF I>9 THEN I=I+7
205 PRINT CHR$(48+I);
210 NEXT X
220 PRINT
230 NEXT Y

  • histcomp/apple_ii.txt
  • Last modified: 2024-10-01 06:15
  • by asdf