reorganize documentation

This commit is contained in:
mgcaret 2017-10-02 12:27:09 -07:00
parent df08db5fce
commit 7ed3e10a22
4 changed files with 356 additions and 376 deletions

347
README.md
View File

@ -1,7 +1,5 @@
# ROM 4X and 5X by MG
## This document is currently a bit disorganized, a bit out of date, and a bit long. Sorry.
ROM 4X and 5X are enhancements to the Apple //c version 4 and Apple IIc Plus firmware ROMs.
It adds the following features to the Apple //c and IIc Plus firmware:
@ -13,344 +11,31 @@ It adds the following features to the Apple //c and IIc Plus firmware:
- Zero the RAM card, in case it is corrupted.
- Execute the machine and RAM card diagnostics.
- Tell the machine to boot the SmartPort, the internal floppy drive, or an external floppy drive.
- IIc: The system drops to BASIC if no bootable device is found (this is the default behavior in the IIc Plus).
- IIc Plus: Optionally default the system to 1 MHz.
- IIc only:
- The system drops to BASIC if no bootable device is found (this is the default behavior in the IIc Plus).
- Configure default boot device by saving a file on the RAM Disk.
- IIc Plus only:
- Menu control the built-in accelerator.
- Accelerator settings persist across resets.
- Build option to default the system to 1 MHz.
The first feature listed above is the *raison d'etre* for this project. The larger story is down below but in short: The Apple //c memory card driver keeps certain information in the "screen holes" in main memory, which are required to use the memory card as a RAM disk. Should these screen hole values disappear, the card is re-initialized to empty when ProDOS boots. This happens even when the card is battery-backed and already has a RAM disk. The card data is not damaged until ProDOS boots, but if you attempt to manually boot the RAM disk it will say "UNABLE TO START FROM MEMORY CARD" because the screen hole values are not initialized.
This firmware enhancement identifies a ProDOS boot block on the RAM disk and, if found, restores the appropriate screen holes to make the RAM disk bootable and prevent ProDOS from re-initializing it.
This firmware enhancement identifies a ProDOS boot block on the RAM disk and, if found, restores the appropriate screen holes to make the RAM disk bootable and prevent firmware or ProDOS from re-initializing it.
# User Guide
## Build / Install / Documentation
## Installation
### ROM 4X
### Real System
See the [ROM 4X README.md](rom4x/README.md).
Assuming you already have it burned onto a chip (I use SST27SF512s flash chips which hold 64K and Atmel 27C256, which hold 32K, and program with a TL866), generally the instructions [here](http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Computers/Apple%20II/Apple%20IIc/Manuals/Apple%20IIc%20v4%20ROM%20Upgrade%20Installation.pdf) are relevant. You won't need to cut any traces or solder a jumper unless, you are installing this ROM in an original //c. I don't recommend installing it on a non-memory expansion //c unless you have expansion memory that looks like the 'slinky' memory of the later models. ROM 4X/5X doesn't know about RAMWorks-style expansions.
### ROM 5X
Cards known to work with ROM 4X include the Apple Memory Expansion Card (but no battery!), and the A2Heaven [RAM Express II](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=146) for the original //c, and the [RAM Express II+](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=144) for the memory-expandable //c and IIc Plus.
See the [ROM 5X README.md](rom5x/README.md).
### Emulator
#### //c
## The Whole Story
Copy the ROM into the appropriate location for your emulator. At the time of writing the only emulator I am aware of that can emulate the //c with memory expansion is [Catakig](http://catakig.sourceforge.net/) for MacOS. It's a bit older of an emulator but it runs fine on newer MacOSes.
#### IIc Plus
Unfortunatly the current IIc Plus emulators out there are incomplete.
## Operation
Power on your machine. Everything should look and work *almost* like it did before. If there is a bootable device somewhere, the machine will boot it. If there is not (and this is one of the noticable changes), you will get dropped to BASIC without the need to press ctrl+reset. If things don't go well, revisit your installation.
If you don't have an initialized RAM disk, format the card RAM disk with something like Copy II Plus. Put ProDOS and BASIC.SYSTEM on it. Power off the machine, and power it on after a few minutes. You should boot off of the RAM disk. You might notice an "R" flash on the screen for an instant before ProDOS loads.
Now, press Control+Closed-Apple+Reset, holding down Closed-Apple after releasing reset. You should see the following menu appear (on a //c, IIc Plus menu is more compact to save firmware space):
```
0 Monitor
1 Reboot
2 Zero RAM Card and Reboot
3 Diagnostics
4 RAM Card Diagnostics
5 Boot SmartPort
6 Boot Int. 5.25
7 Boot Ext. 5.25
```
Picking any of the menu options besides 0 results in the menu being cleared, but the bottom line 'ROM 4X mm/dd/yy' immediately reappears to confirm that the new code is taking action.
What each option does is detailed below.
### 0 Monitor
This drops you unconditionally into the monitor.
### 1 Reboot
This carries out the normal boot sequence, which is to try the RAM disk first, then the internal 5.25 floppy drive, then the first connected smartport device. Some of the other options let you skip over one or more of this ordering.
### 2 Zero RAM Card and Reboot
This zeros out the RAM card memory and the screen holes. This is a nuclear option if the RAM disk is corrupt and the system fails to boot. After selecting 2 the word "SURE?" appears on the screen. At this point you must type `Y` or `y` to continue with the zeroing, or any other key to cancel.
If there is no card RAM, you are immediately rebooted. Otherwise an 'A' will appear in the upper left corner of the screen and will follow the alphabet as each 64K of the card is cleared. After it completes the letter will disappear and the machine will try booting.
### 3 Diagnostics
This jumps to the //c internal diagnostics that are also run when you press control+both-apples+reset.
### 4 RAM Card Diagnostics
This runs the RAM card diagnostics. When the diagnostics are finished either by user cancel or error, you are dropped into the monitor.
Since the test may damage data on the card, you are asked to confirm as per option 2 above.
### 5 Boot SmartPort
This attempts to boot the first smartport device, such as a UniDisk 3.5.
### 6 Boot Internal 5.25
This skips the RAM disk and starts booting with the internal 5.25 drive.
**IIc Plus**: There is no interal 5.25 drive, so this option boots an external 5.25 drive and the option to boot an external 5.25 drive is removed.
### 7 Boot External 5.25
This is like option 6, but using an external 5.25 drive. The only OS I am aware of that supports booting this way is ProDOS.
This destructively copies a short routine to $800 so if you need to preserve what's there don't use this option.
*This option is not available on the IIc Plus per the above comment.*
# Build/Develop Guide
## Build
To build the new firmware, you must start with a copy of the repository containing this file, and obtain a copy of the Apple //c version 4 or IIc Plus version 5 ROM. The patches to the firmware work with the ROM dump that has sha256sums:
//c:
```
8ad5e6c4ed15d09b62183965b6c04762610d4b26510afc1896bdb4ecc55da883
```
IIc Plus:
```
5a62070f6a0b07784681d4df4bf2ce88b2809bec0cbaa65fcb963e804ed60374
```
It may work with other ROM dumps, it will *not* work with any other ROM version, including ROM 3 and earlier.
Place the ROM dump in the directory with the other files and name it `iic_rom4.bin` for ROM 4X and `iic+_rom5.bin` for ROM 5X.
Now you will need a 65C02 cross assembler. The current codebase is developed using ca65 from the [cc65](http://www.cc65.org/) project. (Note: The code was developed originally using [xa](http://www.floodgap.com/retrotech/xa/)).
Finally you will need [Ruby](https://www.ruby-lang.org/en/) and [Rake](https://github.com/ruby/rake).
Once you have it all together change to the directory with the source files and original ROM image and type `rake`.
If all goes well, you will have a shiny new `iic_rom4x.bin` or `iic+_rom5x.bin`.
If you intend to build an image for a 512-kbit chip such as the SST27SF512, do `rake sf512`.
## Develop
### First Thing's First
First and foremost, it is most helpful to have an emulator. The only one that I have found that can be used for (almost) thorough testing is [Catakig](http://catakig.sourceforge.net/) for MacOS. It can emulate the //c and the Expansion Card (though not battery-backed).
If you plan to test on a real machine, be aware that the ROM socket is not rated for a large number of insertions and you *will* break something after a while. You may consider putting a machine-pin DIP socket or a ZIF socket into the CPU socket position. This can be done by desoldering the original socket if you have the skills, or by plugging the new socket into the existing CPU socket. If you do do the latter you should consider the new socket permanent as the socket pins are thicker than a ROM chip's and removing it may leave the socket in such a state as to not be able to make good contact with a subsequent chip.
As for me, I just use the emulator and then I am very careful with changing the ROM when I want to test on the real hardware. For heavy development/testing I insert a low-profile solder-tail ZIF socket into the existing chip socket..
### Apple //c Technical Reference and other Documentation
You need this.
The Apple //c Technical Reference Manual that is available on the internet has the firmware listing for ROM 3. ROM 4 fixes a few bugs that were in ROM 3, including with the memory card driver. The changes are minor and affect some of the offsets of routines in the RAM card support, but it is easy to figure them out.
[This](http://www.1000bit.it/support/manuali/apple/technotes/memx/tn.memx.1.html) tech note is also helpful as it documents the screen holes and some of the card behavior including under what conditions it reformats. Though the power2 byte is *not* used by the Apple //c code -- it is commented out in the firmware listings in the Technical Reference. ROM 4X uses it for the menu function.
[This](http://www.1000bit.it/support/manuali/apple/technotes/aiic/tn.aiic.5.html) technical note is a little less helpful for this project.
### Magic File Names
The main source files are named after a pattern, `B#_####_something.s` where the first # represents the bank number (0 = main, 1 = aux), and #### is the location in the bank to patch the code into. E.G. the `B1_E000_rom4.bin`'s object code is loaded into bank 1 at E000. Generally the origin address of the code in the file matches the #### portion of the file name.
The Rakefile uses this information to patch the original ROM 4 and produce the ROM 4X version.
### Defs
One file, `iic.defs` is included by all of the other source files. This has entry points, origins, and various RAM locations defined in it for use by the other source code.
### Test Scenarios
#### Basic Functional Tests
1. Boot ProDOS from power off. Run SlotScan 1.62 and confirm that the slots are identified as expected, see below.
2. With no bootable ProDOS RAMdisk, boot the system from power off or ctrl-oa-reset.
1. With the drop-to-basic patch:
- Expected: The system says "No bootable device" and drops to BASIC.
2. Without to drop-to-basic patch:
- Expected: The system boots the same as an unmodified ROM 4.
3. With a bootable ProDOS RAMdisk containing ProDOS, boot the system from power off or ctrl-oa-reset.
- Expected: The system boots from RAM disk, an inverse or flashing R may appear on the left of line 24 of the display.
4. Power on the system with the ca key pressed or use ctrl-ca-reset.
- Expected: The menu is displayed.
5. RAM disk recovery:
1. Battery-backed RAM present with bootable RAM disk: Power off the machine and leave it for 1 hr. Power on.
- Expected: The system boots from RAM disk.
2. Non-battery-backed RAM present with bootable RAM disk: Erase main RAM from 0300 up (e.g. in monitor: `300:00` then `301<300.BFFEM`) and press ctrl-reset.
- Expected: The system boots from RAM disk.
Expected SlotScan output:
```
SlotScan Version 1.62 Copyright 1989-1994 by Robert S. Claney
--------------------------------------------------------------------------------
Apple Computer Type: //c, ROM Ver 4 (Newer Mem. Exp.)
Processor type: 65c02
Total RAM: 128K
-----Scanning for peripherals-----
Port 1: Serial Port (#1)
Port 2: Serial Port (#1)
Port 3: 80-Column Port (#8)
Port 4: RamCard SmartPort: 1 device found
Manufacturer #0 (Unknown)
Device 1: "RAMCARD", Size: 2048 Blocks (1024K, 1 Meg)
Type: Mem. expansion Version: 0.102
Addl. info: (None)
Port 5: SmartPort: 0 devices found
Port 6: Disk ][ Port
Device Size: 280 Blocks (140K)
Port 7: Mouse Port (#0)
Done. Press any key to continue, or Control-P to get a printout
```
#### Menu Item Functional Tests
All cases: When any menu option is selected, the "ROM 4X MM/DD/YY" message is displayed on the bottom of the screen.
0. Monitor
- Expected: We are dropped into the monitor immediately.
1. Reboot
- Expected: System boots as normal.
2. Zero RAM Card and Reboot
- Expected: Reboot if no card RAM present. Otherwise, counter appears in upper left corner and card RAM is cleared.
3. Diagnostics
- Expected: System enters built-in diagnostics as if ctrl-oa-ca-reset was pressed.
4. RAM Card Diagnostics
- Expected: System enters RAM card diagnostics if card RAM present, then/or (no mem) drops to monitor when exited by failure or user escape key.
5. Boot SmartPort
- Expected: The system boots from a SmartPort device, skipping the RAM card and 5.25 floppy drives.
6. Boot Internal 5.25
- Expected: The system boots from the internal 5.25 drive, skipping the RAM card. The system may proceed to the SmartPort if no disk is found.
7. Boot External 5.25
- Expected: The system boots from the external 5.25 drive, skipping the RAM card. The system may proceed to the SmartPort if no disk is found.
### Ideas for Future
- Replace Apple Slinky code with RamFactor code. (Difficulty: Hard)
# The Whole Story
The Apple II Plus was the first computer my family owned. It's what I learned to program on. We spent hours at the keyboard typing in programs from magazines, and eventually I learned to modify them and write my own. As technology progressed, I switched to PCs like almost everyone else and largely forgot about the Apple II after the 90s. I still had an interest in my Apple IIs and managed to get hold of some more gear, including a //c and a couple of IIgs machines. The prices bottomed out a few years after Apple discontinued the line. Eventually I moved on and boxed it all up, sold a bit, but I held on to most of the interesting stuff I'd acquired.
## The Beginning and the New Old
I got back into the Apple II a few months ago after I read [this story](http://www.osnews.com/story/29400/Why_the_Apple_II_ProDOS_2_4_release_is_the_OS_news_of_the_year). What? A new ProDOS? I must try it! So I dusted off some of my old Apple II gear and the next thing you know I had ProDOS 2.4.1 running on my Apple //c.
So then I go searching around the net only to discover that not only is there a pretty active user community, but that people had been making *new hardware* for it, the coolest of which emulate floppy and hard drives. There are Ethernet cards, memory expansions, VGA adapters, FPGA cards, and all kinds of other hardware.
Jumping into this new hardware for old computers craze, I bought a [Ram Express II+](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=144#review) from [A2 Heaven](http://www.a2heaven.com/) and was excited to try out the whopping (really!) 1 MB of battery-backed memory in it, as well as the clock. I formatted the card, loaded up ProDOS, and rebooted... Instant-on! Much fast!
Then I powered down for a while to do non-hobby things. Upon return, instead of a super fast boot to ProDOS, I got the the familiar clunking of the Apple 5 1/4 floppy drive recalibrating. I thought to myself that surely I was doing something wrong, so I rebooted ProDOS and found the card in its initial state without what I had copied on it.
Bummer.
## Resetting My Expectations
Assuming the worst - that the battery wasn't working for the memory, I replaced the battery and checked that the clock had been working. Still the same results.
I emailed the maker, Plamen, and asked about it. He told me that something about the //c causes the card to reformat after power off. To prove it, he had me write some values to the card manually and then read them back after powering off for an hour.
Turns out my expectations were wrong. I followed up with a thanks and a "maybe I can find out in the firmware where that happens and fix it." Another user got a card a few days later, and we discussed the matter over FaceBook, where I joked that it would be a "few NOPs" and when another user suggested adding boot from external drive back to the firmware I said that that would be much harder. The exact opposite of what it was.
## Down the Rabbit Hole
I am a reasonably competent 8-bit assembly language programmer, always had been since I was a kid working on my Apple II Plus. But I know the Z80 better these days, it'd been a long time since I touched the 6502.
Armed with a copy of Apple //c Technical Reference in PDF format, I printed out the firmware listings (computers used to have schematics and firmware listings available!) and started to look for where the few NOPs would have to go.
## pwerdup <> pwrbyte and numbanks == 0
After looking through the firmware listing, it was clear that the reason that the RAM disk was being reinitialized was because certain memory locations did not contain the contents needed to tell the firmware that it was already initialized.
These memory locations are in what are called "screen holes" in the Apple II. Veteran Apple II users know what these are, but if you are unaware: These are areas of the text screen that do not result in display output. The Apple II text screen is not linearly organized and there are 8-byte "holes" after each 120 displayable locations. Each of these holes is allocated to one of the card slots for slotted Apple IIs, or to the various ports of the unslotted Apple IIs.
In particular the firmware checks $77c (pwerdup) for the value $a5 (pwrbyte), and $47c for the number of banks detected on the card. After some experimenting I determined that it is enough to set both of these to the proper values and the card will be recovered. Setting these on an uninitialized card can result in all kinds of bad behavior, from crashes to perpetual "UNABLE TO LOAD PRODOS" depending on what is in the boot block. Changing the firmware to ignore them is not possible because we cannot assume the user is using the card as a RAM disk.
That means that instead of disabling code that purposely trashed the RAM disk, I had to add code to find an existing RAM disk and prevent re-initialization.
## From NOP codes to opcodes
Well, as we know, adding new code to existing firmware is a lot harder than disabling existing code. We can't change where things already are, and any patches have to be at places that wouldn't break existing software.
But now I at least have some initial requirements:
> 1: Identify an existing, hopefully bootable RAM disk.
> 2: If it exists, prevent it from being re-initialized by setting the two screen holes to the proper values.
> 3: If no special action is taken, everything should "look normal."
The Apple II RAM card code is more simple than, say, the Applied Engineering RamFactor card, and I haven't seen anything that documents being able to boot DOS 3.3 or Pascal from it, so I decided that I only needed to see if the RAM disk was ProDOS and bootable. So I would solve the first requirement by checking for a ProDOS boot block, conveniently starting at location zero on the card.
The second requirement we already sorted out above. The third is that if you don't have a bootable RAM disk, booting the system should look and work just like it did before. That's just good practice to not change things for the sake of change.
## Feature Creep
Then I thought to myself... what if the RAM disk is screwed up, and we keep re-initializing it and attempting to boot? That's kind of a pain, but could be solved with documentation. "Hit ctrl+reset and then pr#6 to boot a disk, then format the card with a program."
Nah. Why not detect if the closed-apple key is pressed with ctrl+reset and clear out the RAM disk?
> 4: Provide a way to erase a messed up RAM disk.
Well, that wasn't so bad. But what if the user doesn't want to erase it outright? Perhaps they want to try to recover some data. Maybe we can leave it corrupted and just boot something else.
> 5: Provide a way to skip booting the RAM disk.
Well that's at least two options, and between the two apple key+reset combinations, no room for more than one additional action, so maybe that action should be a menu.
> 6: Present a menu to the user to decide what action to take.
Well since we are doing that, it's probably easy to get the IIc to try to boot whatever device you want, and maybe the user doesn't want to do any of the things on the menu.
> 7: Let the user select a variety of boot devices.
Hell, while we are at it, let's give some easy access to internal functionality that requires more keys to be held down or calling routines in memory with BASIC or monitor commands.
> 8: Let the user get access to the internal diagnostic routines.
Then, there was that guy that wanted to be able to boot an external 5.25 drive like the original //c firmware had. This turned out to be fairly easy to do.
> 9: Let the user boot an external 5.25 drive.
Well, I coded all the above up over the course of two days (short story, keep reading for longer version) and then I had another feature:
> 10: Don't make it too easy to trash the RAM disk accidentally by picking menu option 2 and 4.
Sigh. Now it's a real software project.
## Banking on It
After examining the //c ROM, it was clear that there was not any room in the main ROM bank to implement the above code, so the code had to run in the alternate bank.
When switching the ROM bank from ROM, you have to pull some tricks to make the switch safely and continue execution on the right code path. The most compact way is to have a free place in both banks, which we have in the //c. The less compact ways are to make use of subroutines already in the ROMs that can switch based on a memory location in RAM or by pushing the address to jump to on the stack and making use of the routine that switches banks and then does an RTS instruction (this is known as the 'RTS trick'). The latter are more useful for one-way jumps.
The second bank is also missing features that we take for granted, such as the various routines for displaying characters on the screen, clearing the screen, etc. so we need to find out which of these we should write ourselves and which ones to make available via a bank switch.
In the end the most difficult routine we might need from the firmware that we have to call and get back from is to clear the screen, since it has to be done without overwriting the screen holes. Putting stuff on the screen is easy and there are compact ways of doing it. The other functionality is pretty much one-way and for the common functions like jumping to an address for booting, the main needed functionality is in the firmware already.
In the end, I only needed the two-way switchers to enter and exit the reset handler (detects closed-apple and shows the menu), the boot handler (which handles the function selected by the user), and clearing the screen. I decided to use the banner screen clear that prints 'Apple //c' at the top for me. That meant that I needed 22 bytes of common unused address space in both banks for these, which I found.
The remaining switcher is one-way from alt bank to main bank, and I use the RTS trick.
## Patching Pants that Don't Have Holes
So now we have to patch the boot process to recover the RAM disk, and the reset process to capture the closed apple key and present the menu.
Well, firmware programmers for resource-limited machines don't exactly leave a bunch of space available for inserting your own routines, so I had to figure out where I could replace existing code with jumps and no-op padding. Ideally you patch instructons in a 1:1 manner, a 3 byte instruction is replaced by another 3-byte instruction so that code that makes assumptions about where it can jump or call can continue to rely on those assumptions.
With the //c firmware I did not have that luxury for one of the patches, so hopefully it does not break things. I think the chances are pretty low.
I searched over the course of an hour to figure out the best place to put the patches, and ROM 4X is the result.
## Conclusion
So now you have it and you know how it got here. Enjoy ROM 4X.
See [story.md](story.md).

View File

@ -2,32 +2,47 @@
ROM 4X is a collection of enhancements to the Apple //c version 4. See the top level [README.md](../README.md) for more general information on ROM 4X and ROM 5X.
It adds the following features to the Apple //c and IIc Plus firmware:
It adds the following features to the Apple //c:
- Identifies and reinstates a *bootable* (it must have something that looks like a boot block!) RAM disk from battery-backed expansion memory (see below), such as the [RAM Express II+](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=144) from A2Heaven.
- Provides a menu of various tools upon pressing Ctrl+Closed-Apple+Reset (or holding Closed-Apple when powering up), that let you:
- Enter the monitor unconditionally.
- Reboot the machine (enter standard boot sequence).
- Zero the RAM card, in case it is corrupted.
- Execute the machine and RAM card diagnostics.
- Tell the machine to boot the SmartPort, the internal floppy drive, or an external floppy drive.
- *New as of 04/25/2017*: By saving a file on the RAM card, control the way the system boots by default.
- The system drops to BASIC if no bootable device is found (this is the default behavior in the IIc Plus).
- The system drops to BASIC if no bootable device is found (this is the default behavior in the IIc Plus).
- Configure default boot device by saving a file on the RAM Disk.
RAM expansion cards known to work with ROM 4X include the Apple Memory Expansion Card (but no battery!), and the A2Heaven [RAM Express II](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=146) for the original //c, and the [RAM Express II+](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=144) for the memory-expandable //c and IIc Plus.
# User Guide
## Obtaining
**Due to copyright law, I do NOT provide full ready-to-burn binaries at this time. Some assembly (but not necessarily an assembler) is required!**
You may either build it yourself which guarantees that you have the latest version and feature branch that you want, or you can check the [web site for ROM 4X/5X](http://apple2.guidero.us/doku.php?id=projects:rom_4x_and_5x) for binary releases.
### Binary Releases
The binary releases consist of a zip file with the assembled and linked patches, a checksum file, and a Bash script. You must have a unix-like system (MacOS, Linux, etc.) or, on Windows, Cygwin or the Windows Subsystem for Linux configured.
The shell script will perform the following:
* Download the original Apple ROM image from a well-known location.
* Apply the patches.
* Validate the checksums of both the original ROM image and the patched ROM image.
## Installation
### Real System
Assuming you already have it burned onto a chip (I use SST27SF512s flash chips which hold 64K and Atmel 27C256, which hold 32K, and program with a TL866), generally the instructions [here](http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Computers/Apple%20II/Apple%20IIc/Manuals/Apple%20IIc%20v4%20ROM%20Upgrade%20Installation.pdf) are relevant. You won't need to cut any traces or solder a jumper unless, you are installing this ROM in an original //c. I don't recommend installing it on a non-memory expansion //c unless you have expansion memory that looks like the 'slinky' memory of the later models. ROM 4X/5X doesn't know about RAMWorks-style expansions.
Burn the ROM image (generally named iic_rom4x.bin) onto a 27C256 chip, or burn twice (into the lower and upper halves) of a 27C512 chip. If you can obtain an SST27SF512 flash EEPROM, that is a great option.
Once you have a ROM chip, generally the instructions [here](http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Computers/Apple%20II/Apple%20IIc/Manuals/Apple%20IIc%20v4%20ROM%20Upgrade%20Installation.pdf) are relevant. You won't need to cut any traces or solder a jumper unless you are installing this ROM in an original //c.
Cards known to work with ROM 4X include the Apple Memory Expansion Card (but no battery!), and the A2Heaven [RAM Express II](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=146) for the original //c, and the [RAM Express II+](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=144) for the memory-expandable //c and IIc Plus.
### Emulator
#### //c
Copy the ROM into the appropriate location for your emulator. At the time of writing the only emulator I am aware of that can emulate the //c with memory expansion is [Catakig](http://catakig.sourceforge.net/) for MacOS. It's a bit older of an emulator but it runs fine on newer MacOSes.
MAME's Apple //c emulation may work, but I have not tried it.
@ -40,7 +55,7 @@ Power on your machine. Everything should look and work *almost* like it did bef
If you don't have an initialized RAM disk, format the card RAM disk with something like Copy II Plus. Put ProDOS and BASIC.SYSTEM on it. Power off the machine, and power it on after a few minutes. You should boot off of the RAM disk. You might notice an "R" flash on the screen for an instant before ProDOS loads.
Now, press Control+Closed-Apple+Reset, holding down Closed-Apple after releasing reset. You should see the following menu appear (on a //c, IIc Plus menu is more compact to save firmware space):
Now, press Control+Closed-Apple+Reset, holding down Closed-Apple after releasing reset. You should see the following menu appear:
```
0 Monitor
@ -97,8 +112,6 @@ This destructively copies a short routine to $800, which under most circumstance
### Configuration File
**EXPERIMENTAL**
If the RAM card is ProDOS-formatted, you can save a binary file in the volume directory called `BOOTX`. ROM 4X will find this file and use the Aux Type field (the load address) to set a default of the menu options above when no option has been selected using the menu. For example, `BSAVE /RAM4/BOOTX,A6,L0` will cause ROM 4X to skip booting the RAM card and go straight to booting the internal floppy drive (menu item 6). The contents of `BOOTX` are irrelevant, only the Aux Type is used. You cannot set it to jump into the monitor because that action happens before the boot code takes over.
You will know the configuration file is being used because the ROM 4X line will appear on the bottom of the screen and a flashing 'C' will appear in the lower-left corner.
@ -111,14 +124,13 @@ You will know the configuration file is being used because the ROM 4X line will
To build the new firmware, you must start with a copy of the repository, and obtain a copy of the Apple //c version 4 ROM. The patches to the firmware work with the ROM dump that has sha256sum:
```
8ad5e6c4ed15d09b62183965b6c04762610d4b26510afc1896bdb4ecc55da883
```
It may work with other ROM dumps, it will *not* work with any other ROM versions, including ROM 3 and earlier. You must build ROM 4X using a ROM 4 dump.
Place the ROM dump in the directory with the other files and name it `iic_rom4.bin`.
The Rakefile will download the file from a well-known location if it is not already present. It also verifies the checksum.
Now you will need a 65C02 cross assembler. The current codebase is developed using ca65 from the [cc65](http://www.cc65.org/) project. (Note: The code was developed originally using [xa](http://www.floodgap.com/retrotech/xa/)).
@ -126,7 +138,7 @@ Finally you will need [Ruby](https://www.ruby-lang.org/en/) and [Rake](https://g
Once you have it all together change to the directory with the source files and original ROM image and type `rake`.
If all goes well, you will have a shiny new `iic_rom4x.bin` or `iic+_rom5x.bin`.
If all goes well, you will have a shiny new `iic_rom4x.bin`.
If you intend to build an image for a 512-kbit chip such as the SST27SF512, do `rake sf512`.
@ -231,3 +243,4 @@ All cases: When any menu option is selected, the "ROM 4X MM/DD/YY" message is d
- Replace Apple Slinky code with RamFactor code. (Difficulty: Hard)

View File

@ -1,13 +1,149 @@
# ROM 5X by MG
## Consider it a step beyond beta :-)
ROM 5X is a collection of enhancements to the Apple //c version 4. See the top level [README.md](../README.md) for more general information on ROM 4X and ROM 5X.
*All of the functionality, including the RAM Disk recovery and other functions,
appear to work correctly, but I would appreciate any feedback if something isn't
workign for you.*
It adds the following features to the Apple //c:
- Enter the monitor unconditionally.
- Reboot the machine (enter standard boot sequence).
- Zero the RAM card, in case it is corrupted.
- Execute the machine and RAM card diagnostics.
- Tell the machine to boot the SmartPort, the internal floppy drive, or an external floppy drive.
- Menu control the built-in accelerator.
- Accelerator settings persist across resets.
- Build option to default the system to 1 MHz.
- Changes ctrl+esc+reset to toggle the accelerator rather than turn it off only.
RAM expansion cards known to work with ROM 4X include the AE RAM Express Cards (but no battery!), and the A2Heaven [RAM Express II](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=146) for the original //c, and the [RAM Express II+](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=144) for the memory-expandable //c and IIc Plus.
# User Guide
## Obtaining
**Due to copyright law, I do NOT provide full ready-to-burn binaries at this time. Some assembly (but not necessarily an assembler) is required!**
You may either build it yourself which guarantees that you have the latest version and feature branch that you want, or you can check the [web site for ROM 4X/5X](http://apple2.guidero.us/doku.php?id=projects:rom_4x_and_5x) for binary releases.
### Binary Releases
The binary releases consist of a zip file with the assembled and linked patches, a checksum file, and a Bash script. You must have a unix-like system (MacOS, Linux, etc.) or, on Windows, Cygwin or the Windows Subsystem for Linux configured.
The shell script will perform the following:
* Download the original Apple ROM image from a well-known location.
* Apply the patches.
* Validate the checksums of both the original ROM image and the patched ROM image.
## Installation
### Real System
Burn the ROM image (generally named iic_rom4x.bin) onto a 27C256 chip, or burn twice (into the lower and upper halves) of a 27C512 chip. If you can obtain an SST27SF512 flash EEPROM, that is a great option.
Once you have a ROM chip, generally the instructions [here](http://mirrors.apple2.org.za/Apple%20II%20Documentation%20Project/Computers/Apple%20II/Apple%20IIc/Manuals/Apple%20IIc%20v4%20ROM%20Upgrade%20Installation.pdf) are relevant. You won't need to cut any traces or solder a jumper unless you are installing this ROM in an original //c.
### Emulator
Copy the ROM into the appropriate location for your emulator. At the time of writing the only emulator I am aware of that can emulate the //c with memory expansion is [Catakig](http://catakig.sourceforge.net/) for MacOS. It's a bit older of an emulator but it runs fine on newer MacOSes.
MAME's Apple //c emulation may work, but I have not tried it.
## Operation
### Menu
Power on your machine. Everything should look and work *almost* like it did before. If there is a bootable device somewhere, the machine will boot it. If things don't go well, revisit your installation.
If you don't have an initialized RAM disk, format the card RAM disk with something like Copy II Plus. Put ProDOS and BASIC.SYSTEM on it. Power off the machine, and power it on after a few minutes. You should boot off of the RAM disk. You might notice an "R" flash on the screen for an instant before ProDOS loads.
Now, press Control+Option+Reset, holding down Option after releasing reset. You should see the following menu appear:
```
0 Monitor
1 Reboot
2 Zero RAM Card
3 Sys Diags
4 RAM Card Diags
5 Boot 3.5/SmartPort
6 Boot 5.25
7 Accelerator
```
Picking any of the menu options besides 0 results in the menu being cleared, but the bottom line 'ROM 5X mm/dd/yy' immediately reappears to confirm that the new code is taking action.
What each option does is detailed below. Note that the various device boot options will try that device and any remaining devices in the boot order, which for the Apple IIc Plus is RAM card, 3.5 or SmartPort, and finally the first 5.25 drive, if present.
#### 0 Monitor
This drops you unconditionally into the monitor.
#### 1 Reboot
This carries out the normal boot sequence, which is to try the RAM disk first, then the internal 5.25 floppy drive, then the first connected smartport device. Some of the other options let you skip over one or more of this ordering.
#### 2 Zero RAM Card
This zeros out the RAM card memory and the screen holes. This is a nuclear option if the RAM disk is corrupt and the system fails to boot. After selecting 2 the word "SURE?" appears on the screen. At this point you must type `Y` or `y` to continue with the zeroing, or any other key to cancel.
If there is no card RAM, you are immediately rebooted. Otherwise an 'A' will appear in the upper left corner of the screen and will follow the alphabet as each 64K of the card is cleared. After it completes the letter will disappear and the machine will try booting.
#### 3 Sys Diags
This jumps to the //c Plus internal diagnostics that are also run when you press control+apple+option+reset.
#### 4 RAM Card Diags
This runs the RAM card diagnostics. When the diagnostics are finished either by user cancel or error, you are dropped into the monitor.
Since the test may damage data on the card, you are asked to confirm as per option 2 above.
#### 5 Boot 3.5/SmartPort
This attempts to boot the first bootable smartport device, such as a the built-in 3.5" drive.
#### 6 Boot 5.25
This skips the RAM disk and starts an attached 5.25 drive.
#### 7 Accelerator
This opens the accelerator menu.
### Accelerator Menu
The Accelerator menu can be accessed by selecting "Accelerator" from the boot menu, or by pressing the tab key during or within 1 second of pressing ctrl+reset.
The accelerator menu will allow you to enable or disable the accelerator, set the speed, and control speaker and paddle delay.
The settings will persist through resets.
# Build/Develop Guide
## Build
To build the new firmware, you must start with a copy of the repository, and obtain a copy of the Apple IIc Plus version 5 ROM. The patches to the firmware work with the ROM dump that has sha256sum:
```
5a62070f6a0b07784681d4df4bf2ce88b2809bec0cbaa65fcb963e804ed60374
```
It may work with other ROM dumps, it will *not* work with any other ROM versions, including ROM 4 and earlier from the original //c. You must build ROM 4X using a ROM 5 dump.
The Rakefile will download the file from a well-known location if it is not already present. It also verifies the checksum.
Now you will need a 65C02 cross assembler. The current codebase is developed using ca65 from the [cc65](http://www.cc65.org/) project. (Note: The code was developed originally using [xa](http://www.floodgap.com/retrotech/xa/)).
Finally you will need [Ruby](https://www.ruby-lang.org/en/) and [Rake](https://github.com/ruby/rake).
Once you have it all together change to the directory with the source files and original ROM image and type `rake`.
If all goes well, you will have a shiny new `iic_rom5x.bin`.
If you intend to build an image for a 512-kbit chip such as the SST27SF512, do `rake sf512`.
### Build Options
This is ROM 5X, providing the ROM 4X functionality to the Apple IIc Plus ROM
version 5, plus some basic control functions for the Apple IIc Plus accelerator.
There are some build options in accel5x.s - some functional, others needing more
work, the most popular of which will no doubt be the option to reset the system
@ -15,41 +151,71 @@ with the accelerator in the disabled state. The "extra commands" option will
currently fail to build because the code gets too large, and is really only for
experimental purposes.
## Develop
### First Thing's First
Sadly, there are no working emulations of the IIc Plus at this time.
Sice you must test on a real machine, be aware that the ROM socket is not rated for a large number of insertions and you *will* break something after a while. You may consider putting a machine-pin DIP socket or a ZIF socket into the CPU socket position. This can be done by desoldering the original socket if you have the skills, or by plugging the new socket into the existing CPU socket. If you do do the latter you should consider the new socket permanent as the socket pins are thicker than a ROM chip's and removing it may leave the socket in such a state as to not be able to make good contact with a subsequent chip.
### Nitty Gritty
There are almost no free bytes in the main bank of the IIc Plus firmware, so
I had to get creative to get into the alternate bank, where I then had to split
the code up across multiple smaller free spaces due to the massive 3.5 drive
handling code. Ironically this makes the code larger as well.
There are almost no free bytes in the main bank of the IIc Plus firmware, so I had to get creative to get into the alternate bank, where I then had to split the code up across multiple smaller free spaces due to the massive 3.5 drive handling code. Ironically this makes the code larger as well.
For those interested, I hijack the monitor BEEP1 routine. The beep routine has
an LDA #$40 and then calls WAIT with this value for a .1 second delay,
presumably so that multiple beeps are distinct from each other.
For those interested, I hijack the monitor BEEP1 routine. The beep routine has an LDA #$40 and then calls WAIT with this value for a .1 second delay, presumably so that multiple beeps are distinct from each other.
I patch the JSR WAIT to be STA $C028, which switches to the other bank.
The code in the other bank checks the accumulator and for two values calls
either reset5x or boot5x, for a third value ($40 loaded by BEEP1) does the
classic Apple II "air raid" beep sound, and for any other value executes the WAIT
I patch the JSR WAIT to be STA $C028, which switches to the other bank. The code in the other bank checks the accumulator and for two values calls either reset5x or boot5x, for a third value ($40 loaded by BEEP1) does the classic Apple II "air raid" beep sound, and for any other value executes the WAIT
(assuming that we got there from BEEP1) and returns back to BEEP1.
Then, in only 6 bytes I can create two entry points that load the right values
into the A register that we need for the reset or boot routines, and then jump
to the above patch.
Then, in only 6 bytes I can create two entry points that load the right values into the A register that we need for the reset or boot routines, and then jump to the above patch.
## Options
### Apple //c Technical Reference and other Documentation
The options directory contains one or more subdirectories with optional patches
that change the default behavior of the Apple IIc Plus.
You need this.
Enable options by copying the files to the main directory. Disable the by removing
the copied files.
The Apple //c Technical Reference Manual that is available on the internet has the firmware listing for ROM 3. ROM 4 fixes a few bugs that were in ROM 3, including with the memory card driver. The changes are minor and affect some of the offsets of routines in the RAM card support, but it is easy to figure them out.
### (Obsolete) Accelerator Reverse
[This](http://www.1000bit.it/support/manuali/apple/technotes/memx/tn.memx.1.html) tech note is also helpful as it documents the screen holes and some of the card behavior including under what conditions it reformats. Though the power2 byte is *not* used by the Apple //c code -- it is commented out in the firmware listings in the Technical Reference. ROM 4X uses it for the menu function.
This option was obsoleted by the inclusion of Accel5X in the project.
[This](http://www.1000bit.it/support/manuali/apple/technotes/aiic/tn.aiic.5.html) technical note is a little less helpful for this project.
The accelerator reverse patch is a 1-byte patch that causes a IIc Plus with the
original Apple accelerator code to start at the "normal" 1 MHz speed.
### Magic File Names
The main source files are named after a pattern, `B#_####_something.s` where the first # represents the bank number (0 = main, 1 = aux), and #### is the location in the bank to patch the code into. E.G. the `B1_E000_rom4.bin`'s object code is loaded into bank 1 at E000. Generally the origin address of the code in the file matches the #### portion of the file name.
The Rakefile uses this information to patch the original ROM 5 and produce the ROM 5X version.
### Defs
One file, `iic+.defs` is included by all of the other source files. This has entry points, origins, and various RAM locations defined in it for use by the other source code.
### Test Scenarios
#### Basic Functional Tests
1. Boot ProDOS from power off. Run SlotScan 1.62 and confirm that the slots are identified as expected, see below.
2. With no bootable ProDOS RAMdisk, boot the system from power off or ctrl-oa-reset.
- Expected: The system says "No bootable device" and drops to BASIC.
3. With a bootable ProDOS RAMdisk containing ProDOS, boot the system from power off or ctrl-oa-reset.
- Expected: The system boots from RAM disk, an inverse or flashing R may appear on the left of line 24 of the display.
4. Power on the system with the ca key pressed or use ctrl-ca-reset.
- Expected: The menu is displayed.
5. RAM disk recovery:
1. Battery-backed RAM present with bootable RAM disk: Power off the machine and leave it for 1 hr. Power on.
- Expected: The system boots from RAM disk.
2. Non-battery-backed RAM present with bootable RAM disk: Erase main RAM from 0300 up (e.g. in monitor: `300:00` then `301<300.BFFEM`) and press ctrl-reset.
- Expected: The system boots from RAM disk.
#### Menu Item Functional Tests
All cases: When any menu option is selected, the "ROM 5X MM/DD/YY" message is displayed on the bottom of the screen.
Check each item, the expectation is that the sytem does what is listed in the menu.
### Ideas for Future
- Replace Apple Slinky code with RamFactor code. (Difficulty: Very Hard or Impossible)
Pressing ESC at reset time will make the machine run at 4 MHz.

116
story.md Normal file
View File

@ -0,0 +1,116 @@
# ROM 4X and 5X: The Whole Story
The Apple II Plus was the first computer my family owned. It's what I learned to program on. We spent hours at the keyboard typing in programs from magazines, and eventually I learned to modify them and write my own. As technology progressed, I switched to PCs like almost everyone else and largely forgot about the Apple II after the 90s. I still had an interest in my Apple IIs and managed to get hold of some more gear, including a //c and a couple of IIgs machines. The prices bottomed out a few years after Apple discontinued the line. Eventually I moved on and boxed it all up, sold a bit, but I held on to most of the interesting stuff I'd acquired.
## The Beginning and the New Old
I got back into the Apple II a few months ago after I read [this story](http://www.osnews.com/story/29400/Why_the_Apple_II_ProDOS_2_4_release_is_the_OS_news_of_the_year). What? A new ProDOS? I must try it! So I dusted off some of my old Apple II gear and the next thing you know I had ProDOS 2.4.1 running on my Apple //c.
So then I go searching around the net only to discover that not only is there a pretty active user community, but that people had been making *new hardware* for it, the coolest of which emulate floppy and hard drives. There are Ethernet cards, memory expansions, VGA adapters, FPGA cards, and all kinds of other hardware.
Jumping into this new hardware for old computers craze, I bought a [Ram Express II+](http://a2heaven.com/webshop/index.php?rt=product/product&product_id=144#review) from [A2 Heaven](http://www.a2heaven.com/) and was excited to try out the whopping (really!) 1 MB of battery-backed memory in it, as well as the clock. I formatted the card, loaded up ProDOS, and rebooted... Instant-on! Much fast!
Then I powered down for a while to do non-hobby things. Upon return, instead of a super fast boot to ProDOS, I got the the familiar clunking of the Apple 5 1/4 floppy drive recalibrating. I thought to myself that surely I was doing something wrong, so I rebooted ProDOS and found the card in its initial state without what I had copied on it.
Bummer.
## Resetting My Expectations
Assuming the worst - that the battery wasn't working for the memory, I replaced the battery and checked that the clock had been working. Still the same results.
I emailed the maker, Plamen, and asked about it. He told me that something about the //c causes the card to reformat after power off. To prove it, he had me write some values to the card manually and then read them back after powering off for an hour.
Turns out my expectations were wrong. I followed up with a thanks and a "maybe I can find out in the firmware where that happens and fix it." Another user got a card a few days later, and we discussed the matter over FaceBook, where I joked that it would be a "few NOPs" and when another user suggested adding boot from external drive back to the firmware I said that that would be much harder. The exact opposite of what it was.
## Down the Rabbit Hole
I am a reasonably competent 8-bit assembly language programmer, always had been since I was a kid working on my Apple II Plus. But I know the Z80 better these days, it'd been a long time since I touched the 6502.
Armed with a copy of Apple //c Technical Reference in PDF format, I printed out the firmware listings (computers used to have schematics and firmware listings available!) and started to look for where the few NOPs would have to go.
## pwerdup <> pwrbyte and numbanks == 0
After looking through the firmware listing, it was clear that the reason that the RAM disk was being reinitialized was because certain memory locations did not contain the contents needed to tell the firmware that it was already initialized.
These memory locations are in what are called "screen holes" in the Apple II. Veteran Apple II users know what these are, but if you are unaware: These are areas of the text screen that do not result in display output. The Apple II text screen is not linearly organized and there are 8-byte "holes" after each 120 displayable locations. Each of these holes is allocated to one of the card slots for slotted Apple IIs, or to the various ports of the unslotted Apple IIs.
In particular the firmware checks $77c (pwerdup) for the value $a5 (pwrbyte), and $47c for the number of banks detected on the card. After some experimenting I determined that it is enough to set both of these to the proper values and the card will be recovered. Setting these on an uninitialized card can result in all kinds of bad behavior, from crashes to perpetual "UNABLE TO LOAD PRODOS" depending on what is in the boot block. Changing the firmware to ignore them is not possible because we cannot assume the user is using the card as a RAM disk.
That means that instead of disabling code that purposely trashed the RAM disk, I had to add code to find an existing RAM disk and prevent re-initialization.
## From NOP codes to opcodes
Well, as we know, adding new code to existing firmware is a lot harder than disabling existing code. We can't change where things already are, and any patches have to be at places that wouldn't break existing software.
But now I at least have some initial requirements:
> 1: Identify an existing, hopefully bootable RAM disk.
> 2: If it exists, prevent it from being re-initialized by setting the two screen holes to the proper values.
> 3: If no special action is taken, everything should "look normal."
The Apple II RAM card code is more simple than, say, the Applied Engineering RamFactor card, and I haven't seen anything that documents being able to boot DOS 3.3 or Pascal from it, so I decided that I only needed to see if the RAM disk was ProDOS and bootable. So I would solve the first requirement by checking for a ProDOS boot block, conveniently starting at location zero on the card.
The second requirement we already sorted out above. The third is that if you don't have a bootable RAM disk, booting the system should look and work just like it did before. That's just good practice to not change things for the sake of change.
## Feature Creep
Then I thought to myself... what if the RAM disk is screwed up, and we keep re-initializing it and attempting to boot? That's kind of a pain, but could be solved with documentation. "Hit ctrl+reset and then pr#6 to boot a disk, then format the card with a program."
Nah. Why not detect if the closed-apple key is pressed with ctrl+reset and clear out the RAM disk?
> 4: Provide a way to erase a messed up RAM disk.
Well, that wasn't so bad. But what if the user doesn't want to erase it outright? Perhaps they want to try to recover some data. Maybe we can leave it corrupted and just boot something else.
> 5: Provide a way to skip booting the RAM disk.
Well that's at least two options, and between the two apple key+reset combinations, no room for more than one additional action, so maybe that action should be a menu.
> 6: Present a menu to the user to decide what action to take.
Well since we are doing that, it's probably easy to get the IIc to try to boot whatever device you want, and maybe the user doesn't want to do any of the things on the menu.
> 7: Let the user select a variety of boot devices.
Hell, while we are at it, let's give some easy access to internal functionality that requires more keys to be held down or calling routines in memory with BASIC or monitor commands.
> 8: Let the user get access to the internal diagnostic routines.
Then, there was that guy that wanted to be able to boot an external 5.25 drive like the original //c firmware had. This turned out to be fairly easy to do.
> 9: Let the user boot an external 5.25 drive.
Well, I coded all the above up over the course of two days (short story, keep reading for longer version) and then I had another feature:
> 10: Don't make it too easy to trash the RAM disk accidentally by picking menu option 2 and 4.
Sigh. Now it's a real software project.
## Banking on It
After examining the //c ROM, it was clear that there was not any room in the main ROM bank to implement the above code, so the code had to run in the alternate bank.
When switching the ROM bank from ROM, you have to pull some tricks to make the switch safely and continue execution on the right code path. The most compact way is to have a free place in both banks, which we have in the //c. The less compact ways are to make use of subroutines already in the ROMs that can switch based on a memory location in RAM or by pushing the address to jump to on the stack and making use of the routine that switches banks and then does an RTS instruction (this is known as the 'RTS trick'). The latter are more useful for one-way jumps.
The second bank is also missing features that we take for granted, such as the various routines for displaying characters on the screen, clearing the screen, etc. so we need to find out which of these we should write ourselves and which ones to make available via a bank switch.
In the end the most difficult routine we might need from the firmware that we have to call and get back from is to clear the screen, since it has to be done without overwriting the screen holes. Putting stuff on the screen is easy and there are compact ways of doing it. The other functionality is pretty much one-way and for the common functions like jumping to an address for booting, the main needed functionality is in the firmware already.
In the end, I only needed the two-way switchers to enter and exit the reset handler (detects closed-apple and shows the menu), the boot handler (which handles the function selected by the user), and clearing the screen. I decided to use the banner screen clear that prints 'Apple //c' at the top for me. That meant that I needed 22 bytes of common unused address space in both banks for these, which I found.
The remaining switcher is one-way from alt bank to main bank, and I use the RTS trick.
## Patching Pants that Don't Have Holes
So now we have to patch the boot process to recover the RAM disk, and the reset process to capture the closed apple key and present the menu.
Well, firmware programmers for resource-limited machines don't exactly leave a bunch of space available for inserting your own routines, so I had to figure out where I could replace existing code with jumps and no-op padding. Ideally you patch instructons in a 1:1 manner, a 3 byte instruction is replaced by another 3-byte instruction so that code that makes assumptions about where it can jump or call can continue to rely on those assumptions.
With the //c firmware I did not have that luxury for one of the patches, so hopefully it does not break things. I think the chances are pretty low.
I searched over the course of an hour to figure out the best place to put the patches, and ROM 4X is the result.
## Conclusion
So now you have it and you know how it got here. Enjoy ROM 4X.