V2RetroComputing / analog

∀2 Analog VGA card for the Apple II computer line
MIT License
127 stars 18 forks source link

IOSel or DevSel to enable ExtROM #22

Closed rallepalaveev closed 1 year ago

rallepalaveev commented 1 year ago

This issue is related to the activation and deactivation of the ExtROM in case this process is driven by the emulated code, running on the Apple2 and not by the code running inside the RPI Pico.

Currently the PAL logic is turning on the ExtROM upon accessing of the Slot Memory ($CNxx) - by /IOSelect active.

It may be a better solution if ExtROM is activated by /DevSel instead.

The rationale for this is as follows:

If a program is running in the Slot memory ($CNxx), it would be impossible to turn off the ExtROM from within this program (for instance by 'BIT $CFFF'). This is because upon fetching the next instruction in the Slot Memory, the ExtROM would be activated again.

However, if the ExtROM is activated by accessing /DevSel (by BIT $C0F0 for slot 7), then the ExtROM can be turned off by the Slot Memory program and it can finish without turning it on again. This would require of course to take care in the code to turn on ExtROM when needed as it would not happen automatically by just running the program in the Slot Memory.

A workaround for the current /IOSelect solution would be to move the end of the program outside of the Slot Memory to somehere in the RAM and continue the execution there with 'BIT $CFFF' and then 'RTS'.

Another workaround would be that the Slot Memory program performs a 'JMP $CFFC' and there the same ending code: $CFFC: BIT $CFFF $CFFF: RTS

These two methods should successfully turn off ExtROM upon exit from the Slot Memory Program, but they may not be desirable or possible in all cases.

dkgrizzly commented 1 year ago

This is done by convention, as cards that use the $C800-$CFFF address space normally read from $CFFF to disable any other cards using the ExtROM window, and well behaved cards return via a BIT $CFFF stored in the card's scratchpad or other suitable locations that won't trigger a reselect. Apple's recommendation at the time was to use the $CNxx access to set a flipflop and $CFFF to reset it.

Apple themselves ran a foul of this, with the Super Serial Card's Pascal entry points skipping the BIT $CFFF, and if used in a system with a UniDisk controller card (which tended to leave it's own ExtROM active after use) you could see bus conflicts between the cards. Tech Note 03

At this point most cards that use the ExtROM space have either had patched roms made available, or most software has been patched to wrap calls to the cards firmware with BIT $CFFF instructions when needed.

I want to keep the $C0n0 address space as free-form as possible and not hook any of the registers for fixed functions. The PAL chip currently disables the ExtROM space on any access to $CFxx, which negates using that address space to host any existing ROM code from another card you may want to emulate. I believe the current PAL code might not allow enough of a select pulse through for the read to succeed reliably either. As far as putting the RTS at $CFFF, that would be enough on it's own without a separate BIT $CFFF instruction before it (assuming that reading $CFFF works at all).

Changing the PAL code on existing cards requires desoldering the chip and reflashing it, which most users are not going to want to do, though if something warranting a major enough change to the PAL for existing cards were to come along I'm sure we would figure out a solution to get cards reworked and reflashed.

I may still consider some changes to the ExtROM decoding on the next hardware revision I am planning which will be using a larger CPLD to enable the full $C800-$CFFF address space (and release the address space after the read of $CFFF, so the read will still return good values). That CPLD is already in use on the prototype IIgs version to handle all the extra bus qualification needed, and provide some software readable jumpers for selecting which firmware image to boot the card into.

Another nice thing with going to the CPLD on future cards is that it is in-circuit reprogrammable, and a small wire harness or set of jumpers can be included to allow reprogramming from the RP2040.

rallepalaveev commented 1 year ago

Hi, I noticed the $CFxx use for disabling ExtROM. I have implemented a g22V10 and a D-flip-flop by which I decode fully $CFFF and the last byte from $CFFF is reliably fetched as the flip-flop is triggered at the end of the address timing.

oliverschmidt commented 1 year ago

@dkgrizzly:

I understand your statements above in the way that you think that every firmware/software that is done with accessing an ExtROM, does an access to $CFFF in oder to turn the ExtROM off. Can you please point me to examples of code doing so?

Apart from that, I have a hard time to understand how that is supposed to work for firmware: If every access to the SlotROM turns the ExtROM on, then a potential sequence of...

$CnF0: BIT $CFFF
$CnF3: RTS

...leaves the ExtROM turned on because fetching the 'RTS' opcode turns it on.

If you have your CPLD release the ExtROM address space after access to $CFFF, then I see a high risk of a bus fight on access to $CFFF with two of your cards in the system. Even if you claim that "correct" software avoids that, I don't see a benefit that would be even close to being worth the risk.

Please elaborate on what you have in mind.

rallepalaveev commented 1 year ago

The only way to do this is to move the 4 bytes of exit code above to a location outside the Slot Memory and execute it there. Like the card's scratchpad.

oliverschmidt commented 1 year ago

What does "scratchpad" mean in this context?

rallepalaveev commented 1 year ago

The screen holes can be used, although 4 consecutive bytes are needed so there would be invasion of 3 neighboring addresses - may not be an ideal solution...

oliverschmidt commented 1 year ago

Yes, that's the reason why I wasn't considering the screen holes as "your" scratchpad. Instead, the stack could be used. However, from my POV: Any design that requires to be able to do successful R/W on $CFFF (i.e. because that's just the last byte of some 2kB buffer mapped to $C800) is anyhow already totally incompatible with the standard design. Simply because the standard design implies, that the firmware doesn't cleanup after itself. Rather the next user of the ExtROM space cleans up via $CFFF - and no card ever drives the bus on read from $CFFF. And if a design is already incompatible with the standard design, it can as well use any other mechanism to activate its use of the ExtROM space - a mechanism that doesn't make it hard to turn off the ExtROM space usage from code running in the SlotROM space. Just my two cents

rallepalaveev commented 1 year ago

Yes, I did think about the stack and the keyboard buffer too. But these must be used with caution :)

LDA #$2C STA $0100 LDA #$FF STA $0101 LDA #$CF STA $0102 LDA #$60 STA $0103 JMP $0100

:)

rallepalaveev commented 1 year ago

I agree with the alternative methods of activation of ExtROM, I use those.