mgcaret / rom4x

*Archived because I am not permitted to make/accept changes for the foreseeable future* Improved Apple //c (ROM 4X) and Apple IIc Plus (ROM 5X) firmware.
79 stars 14 forks source link

rom5x working in modified kegs... #8

Closed leonbottou closed 6 years ago

leonbottou commented 6 years ago

I hacked Kegs (a 2gs emulator) to work with essentially all kinds of apple2 roms. As you can guess, the Apple IIc+ was the most difficult to get to work. I found your project while researching the MIG chip. I can now run the rom5 firmware and read/write the (simulated) apple3.5drives of the 2gs. I just tried your ROM5x and it seems to work fine. At this point I haven't yet implemented the ACIA --kegs simulates a z8530-- and the accelerator support is the one provided by Kegs (a 8Mhz ZipGS). See (https://github.com/leonbottou/kegs-universal) for the hacked kegs. The MIG simulation is near line 200 in moremem.c.

a2c-rom5x a2c-rom5x-vols

Sorry for making this an issue. I could not find another way to reach you. In case you want details, my email address is myfirstname>@<mylastname.org

mgcaret commented 6 years ago

This is... fantastic.

"the MIG RESET line is tied to both the /IOSEL line and the A14 ROM line which selects the alternate 16KB ROM bank"

Nice catch! I should have seen that.

I would like to chat, either via email or you can often find me at irc.a2central.com in the #a2c.chat channel.

If I'm interpreting your message correctly, your email is your firstname at lastname dot org?

mgcaret commented 6 years ago

Also, I can address this comment in your MIG commentary:

"According to some sources, the MIG was designed to allow a 1Mhz 65c02 to keep up with the 3.5" drive timing requirements. Although the self-incrementing bank register might help a bit, I remain unconvinced. "

It's not necessarily the IWM timing that needs to be addressed by the MIG. A 1 MHz 6502 can successfully read a 3.5" disk, but remember the data bytes are coming in every 16 cycles, and an unindexed read or write takes 4 cycles, an indexed read or write takes 5.

Here's part of ProDOS 2.0.3's read routine, pretty standard:

        LDY #$AA
        LDA #0
RDATA1  STA WTEMP       ; (3 cycles) use zpage for checksum keeping.
RD4     LDX $C0EC       ; (4 cycles) warning: self modified.
        BPL RD4  ; (2 cycles if not taken)
        LDA DNIBL,X ; (4 cycles, no page cross)
        STA NBUF2-$AA,Y ; (5 cycles) save the two-bit groups in nbuf.
        EOR WTEMP      ; (3 cycles) update checksum.
        INY     ; (2 cycles) BUMP to next nbuf position.
        BNE RDATA1      ; (3 cycles, no page cross) loop for all $56 two-bit groups.
        LDY #$AA        ;now read directly into user buffer.
        BNE RD5 ;branch always taken!!!

The routine must: read the byte, denibbilize, store in the buffer, and update the checksum. Note the that it takes 26 cycles to do all that, leaving 6 cycles to spare for the IWM in "slow" mode for the Disk II. So that's not going to happen for the IWM in "fast" mode for the 3.5" disk using the same code.

To get raw data off of a 3.5" disk, code might do the following for Y bytes of data:

R1: LDA Q6L ; 4 cycles
   BPL R1 ; 2 if not taken
   STA BUF,Y ; 5 cycles, store in reverse order
   DEY ; 2 cycles
   BNE R1 ; 3 cycles

That's 16 cycles to read something that comes in every 16 cycles, no room for error. So we probably have to buffer the full sector's raw data somewhere. But where do we do it? Can't really write it to main or aux RAM, because existing code might be using it.

That's where the MIG RAM comes in... it's got enough room to buffer the entire sector. Examining the MIG RAM's contents seems to bear this out.

I've been meaning to disassemble and the 3.5" code in the IIc Plus, but I haven't really had the time.

leonbottou commented 6 years ago

Yes my email is firstname at lastname dot org .
I am afraid I never used IRC...

I can see your point about the timing. Clearly there is no way to denibblize on the fly. Also your solution does not exactly work because one needs to read more than the 256 bytes accessible by STA BUF,Y. So one needs to do something like

R1 LDA Q6L        ; 4 cycles
   BPL R1         ; 2 cycles when not taken
   STA BUF1,Y     ; 5 cycles
R2 LDA Q6L        ; here with 5 cycles to spare
   BPL R2
   STA BUF2,Y
   INY            ; eat 2 additional cycles
R3 LDA Q6L
   BPL R3
   STA BUF3-1,Y
   CPY #whatever  ; eat 2 additional cycles
R4 LDA Q6L
   BPL R4
   STA BUF4-1,Y
   BCC R1         ; eat 3 additional cycles

The trick is to spread the loop increment, test, and branch on multiple reads.I have seen this technique used in the ROM code. That said I agree that there is not obvious memory to do this and that we cannot do indirect addressing (we need a fixed buffer). So yes the MIG memory is certainly convenient for this.

Paradoxically, for my project, the trickiest part was to transparently remap the three drives managed by the MIG to the two apple35 drives simulated by kegs. I also spend a lot of time understanding what each of the external drives (the apple3.5 and the smartport ones) have to do to daisy chain properly. The apple35 need to do quite a bit of logic, that is

Meanwhile the Unidrives have to process messages when the stepper phases are in opposition. But since they don't know about 3.5SEL, they can respond when one is trying to access an nonexistent second Apple3.5 on the daisy chain. Fortunately this only happens when the firmware establishes the list of existing devices on the daisy-chained bus (so that they can be careful.) When the phases are in opposition, the last Unidrive has to de-assert the outgoing DR1ENB and DR2ENB in order to avoid triggering the 5.25 drives. I've read that a Unidrive knows that it is last by sensing the outgoing HDSEL line (this is signal that propagates in the reverse direction from the one that comes from the motherboard). They must conflict somewhere in the chain...

mgcaret commented 6 years ago

My example was contrived, I did not mean to imply the IIc Plus ROM was doing exactly that.

The ROM uses a lot of unrolled accesses to do reads. I’ve been engaged in disassembling it over the past year as I have had time available. It’s been slow-going as it’s less fun than building new things. :-)

leonbottou commented 6 years ago

Thanks for the explanation.

mgcaret commented 6 years ago

Leon, I have updated the README.md for ROM 5X to reference your universal emulators and subsequent changes to MAME that fix the Apple IIc Plus emulation there.

I'm closing this as an issue just to check the box. Thanks again for your insight!