AppleWin icon indicating copy to clipboard operation
AppleWin copied to clipboard

Hard disk driver does not report size back in X/Y on ProDOS status call

Open peteri opened this issue 1 year ago • 30 comments

The ProDOS driver for the HD doesn't report back the block size in the X (low) and Y (high) registers on a ProDOS status call. This would need some modification to the HDD firmware 6502 code to allow for this (if the c++ code just tweaked the registers directly).

Also there does not seem to be a mechanism for having a hard disc (or smartdrv) file that does not auto grow to (although maybe I missed this)

Looking at the other ProDOS disk driver issues there does seem to be some appetitie for rewriting this code, so I thought I'd raise this first.

I noticed this as an issue when trying to get the Cirtech CP/M plus code running in AppleWin, I can certainly change the loader BIOS for CP/M to use the value of from the slot ROM if the status call returns a value that isn't $28 and the slot ROM block size isn't $0000 as per the ProDOS 2.4.2 disk driver documentation.

Note the size at $CxFC seems to be wrong for a 32Mb image? Formatting a new disk with ProDOS 2.4.2 shows the size as being 32767 blocks (which is 16MB) although the code happily works with a 32MB image (i.e. Total Replay shows the disk size as 65535 blocks)

Are you open to a patch for these issues? Or is there a plan to add better support for SmartDrv with all of the extended calls (see issue #1207 ) ?

peteri avatar Dec 19 '23 18:12 peteri

I can supply some disk images for CP/M bootable in AppleWin if you'd like and the source code is available. (The BIOS supports both SmartDRV & ProDOS)

peteri avatar Dec 19 '23 18:12 peteri

Hi @peteri, I'm without a good connection at the moment. Let me reply properly in a few days' time.

In general supplying a patch is fine, but it would be good for you to read the notes on submitting AppleWin pull requests (the link is off the main page), and also for you to define the "spec" of your patch first.

tomcw avatar Dec 23 '23 08:12 tomcw

Okay, I think I need to have a good hard look at the code to be honest along with some of the other issues raised, make a plan then share it.

My thirty year old ProDOS 1.0 programmers workbench doesn't even mention returning back stuff in X/Y for the status call (it is definitely very sparse).

The other annoyance is that a lot of the Apple Technotes say "removed please see the //c or IIGS tech ref" which misses out a lot of context for older programs that might rely on a specific behaviour.

I'll see if I get something together for the start of 2024..

peteri avatar Dec 24 '23 11:12 peteri

https://archive.org/download/Apple_ProDOS_8_Technical_Reference_Manual/Apple_ProDOS_8_Technical_Reference_Manual.pdf

Page 113, depends of some ROM location for BLK mode controllers : $CnFD-FE

https://archive.org/download/apple-prodos-advanced-features-for-programmers/Apple%20ProDOS%20Advanced%20Features%20for%20Programmers.pdf

Status call returns block count in X,Y if $CnFD-FE=$0000

burniouf avatar Dec 24 '23 11:12 burniouf

Cirtech CP/M is using more advanced Z80 adapter than Z80 Softcard by MS. There are multiple other more advanced such adapters and for now Applewin supports only the standard one - Z80 Softcard. Because of that, unmodified code from those CP/M OS will not run, at least for now. Probably Tom can say if there are plans to include support of the other CP/M adapters.

SEGStriker avatar Dec 31 '23 13:12 SEGStriker

Hi @SEGStriker - thanks for your input here. If you have any details of the hardware differences, then that would help with any progress on adding support for the Cirtech card.

tomcw avatar Dec 31 '23 15:12 tomcw

Hi Tom, sorry, I don't know a lot about this project, except in its own documentation: https://github.com/peteri/CirtechCPM/blob/main/README.md However, I guess it will make more sense to emulate some other advanced CP/M card, especially those that supports HDDs. Well, the ordinary Z80 Softcard also should work with CP/M booted from HDD, but no one bothered to write drivers, that's why we can't make it work directly with HDDs or HDD images in an emulator.

These cards are a good example: https://roger.geek.nz/apple2/cpm.html - ALS. https://roger.geek.nz/apple2/cpm.html - ALS (disk images). https://www.atarimagazines.com/creative/v10n1/100_The_PCPI_AppliCard.php - PCPI https://mirrors.apple2.org.za/ftp.apple.asimov.net/documentation/hardware/processors/pcpi_appli-card_mini_manual.pdf - PCPI Z80 Plus - Applied Engineering (same company that created Transwarp and many other great cards) GZ/80 - Turbo CP/M Softcard Z80

I guess PCPI and ALS are the best options for now.

Thanks, Stanislav Georgiev

P.S. Happy new 2024 :)

SEGStriker avatar Dec 31 '23 16:12 SEGStriker

And Happy New Year to you too!

This memory mapping image (Z80 address to 6502) is the same as AppleWin's SoftCard emulation mapping: https://github.com/peteri/CirtechCPM/blob/main/images/address-map-schematic.png

But this "Cirtech CPM memory map" file here shows 2 "swapped addresses":

6502  Z80                          Main memory               Aux memory
  :`
8800  9800  (Swapped address) |  Banked BDOS           |                        |
  :
A800  7800  (Swapped address) |  Banked BDOS           |                        |

Perhaps important, so making a note about it here.

tomcw avatar Dec 31 '23 17:12 tomcw

Ah, probably the more useful doc is this one https://github.com/peteri/CirtechCPM/blob/main/src/address-map.md where I explain that that from my real hardware testing it seems that two $800 sized blocks are swapped around. The Cirtech hardware also uses a 32x8 PROM for the address mapping rather than the 4 bit adder the classic Z80 softcard uses, it looks like Cirtech used the A11 line into the PROM for a form of copy protection.

Changes required to support the original Cirtech boot disks would probably be a new address mapper for the Z80 code in AppleWin and running a few more cycles of Z80 emulator in between the 6502 cycles, along with returning the hard disc size in X/Y. The Cirtech card is a bit faster than the classic softcard (although it uses a 7Mhz clock the actual speed after 6502 interleaving is supposed to be around 4-5Mhz). At somepoint I'm going to get my scope / logic analyzer out and do some tracing of the exact behaviour.

Version 2.0 of the Cirtech CP/M system (I have copies of the IIGS disks) doesn't boot on my real hardware. Interestingly the //e card check code increments the address for the Z80->6502 write in the Z80 card either by one or two bytes from the normal 0E401H ($C401) so I suspect there are some slight variations in the hardware checks across hardware types.

I will probably fix my patched BIOS so it uses the size from the $CxFE address if the value is non-zero but I'd like to finish up a few other things first, before tackling the wider AppleWin Hard Disk code. Anyway that's a 2024 problem and I wish you all a happy new year.....

peteri avatar Dec 31 '23 21:12 peteri

I've done a quick first pass here to see if my patched CP/M boots, https://github.com/peteri/AppleWin/pull/1/files?diff=unified&w=1 please ignore the whitespace issues I've created as I'll do another PR later on.

I added a couple of registers in the $Cn80 space that return back the disk size, but this is going to break with the auto-extending HDV size code. This leaves me with a question as to what would be preferred to fix this? Options that I can see are:

a) For zero sized files return back $7FFF as the size, could work for ProDOS as it stores the number of blocks on disk which means the autoextend code should work (untested). b) Always extend a zero length file to $7FFF blocks on the host disk returning back $7FFF. c) Remove the extending code completely (would anyone use it these days with current disk sizes?) d) Provide some alternative ROMs for the HDD controller: one with a fixed $7fff in the disk size, one with a $0000 and finally one with $00 for SmartDrive usage in $Cn07.

I noticed that the SmartDrive code references the //C plus version of Prince of Persia? I can't see how to get AppleWin to go into a //C plus emulation, is this just a reference to booting the 800K disk in //e enhanced mode?

Finally I noticed the Profile controller for the Apple ][ range source code uses $55 in $Cn07 as an ID byte so older Pascal versions don't pick up the disk up as a Disk II but the Autostart ROM should boot it (from the comments, I've not tested this).

Thoughts ?

peteri avatar Jan 08 '24 10:01 peteri

Do you have any HDD driver on the CP/M side that will recognize the HDD after the boot?

SEGStriker avatar Jan 08 '24 11:01 SEGStriker

On the CP/M side, the BIOS calls the HDD driver by bouncing into 6502 land and making the ProDOS call, this does work with a patched AppleWin that returns the sized in X/Y registers.

The problem with a CP/M disk is the disk geometry is never stored anywhere on the disk. It's hard coded for a Disk II and uses the ProDOS size to compute the sizes at runtime for everything else. A ported to C# version of this is in https://github.com/peteri/CirtechCPM/blob/8055f7256f4aabde6c5612b43041e1014d153418/Tools/CpmDsk/CpmDisk.cs#L56 so getting the correct disk size is important for the Cirtech implementation.

ProDOS stores the number of blocks in the directory header starting so if you create a disk via AppleWin you always get a 16Mb ProDOS Volume. However if you create an image via CiderPress (for example) ProDOS ignores the HDD firmware size and uses the block count from the Directory Entry (I'm using https://github.com/fadden/CiderPress2/blob/main/DiskArc/FS/ProDOS-notes.md for this assumption I've not checked any code) so things look okay for a 32Mb disk ($ffff blocks) in spite of the HDD firmware saying the size is $7fff.

The issue is the "start with 0 byte HDV and extend when a block is written" code in AppleWin which broken by this possible patch as the disk size will be reported as zero.

peteri avatar Jan 08 '24 12:01 peteri

Hi, thanks for 2MB CPM hdv image for testing (https://github.com/peteri/CirtechCPM/blob/8055f7256f4aabde6c5612b43041e1014d153418/DiskImages/buildcpm3.hdv). The image seems to use the SoftCard address translation and not the CirtechCPM address translation as mentioned above.

univta0001 avatar Jan 08 '24 12:01 univta0001

Yeah the image is test image I built to try building on real hardware, the Cirtech BIOS doesn't use the address translation other than as a hardware check. Sadly Microsoft Softcard CP/M doesn't boot on the Cirtech card although I need to try some of the bigger TPA versions (weirdly the 56K version doesn't work in AppleWin but that might be me doing something wrong).

Mame takes around 15 minutes to do the build, real hardware takes around 9 minutes.

peteri avatar Jan 08 '24 13:01 peteri

Oh I forgot option (e) (e) I modify the Z80 BIOS and just stick with a disk size of $7fff blocks and add a note that only HDV images of that size are supported for AppleWin.

peteri avatar Jan 08 '24 14:01 peteri

Even on a real hardware, plain CP/M boot from HDD is not possible, except when using ALS or PCPI card with ProDOS tools and partition. But this is something like a workaround. We know that CP/M is perfectly able to boot from HDD on another hardware, but the problem with Apple II platform and the original Softcard is that MS never created suitable HDD drivers. Because of that, Apple CP/M supports only FDDs and RAM disk on slot 3. Not sure about Cirtech, but as I saw ProDOS mentioned, it will probably work via ProDOS partition, again as a workaround (on a real hardware).

SEGStriker avatar Jan 08 '24 15:01 SEGStriker

@SEGStriker The Cirtech CP/M system will happily boot from a HDD with a ProDOS driver firmware (assuming the Apple Monitor can boot from that drive, in the case of my unenhanced //e I do need to do a manual PR#7). I'd expect it would work with a Profile drive but mine currently has a blown up PSU I need to fix. It will also boot from a RAM card that supports a SmartDrive interface. The buildcpm3.hdv image at https://github.com/peteri/CirtechCPM/blob/main/DiskImages will happily boot in mame and there's no ProDOS structure on that disk (see the readme.md for a suitable command line).

Version 2 of Cirtech CP/M can also create a partition for CP/M in a file on a ProDOS partition and can be booted from it (assuming you have the correct Z80 card). I assume it's working in the same manner as the Pascal Partition Manager. Disassembling it is next on my list after this AppleWin issue.

peteri avatar Jan 08 '24 16:01 peteri

Okay I have patched the LDRBIOS to ignore the size returned from the status call if the disk size in the $CnFC size is not-zero, this allows AppleWin to boot the Cirtech CP/M disks. I have also added a hdv image to https://github.com/peteri/CirtechCPM/tree/main/DiskImages that AppleWin can boot, along with system.dsk and utility.dsk disk images.

peteri avatar Jan 08 '24 19:01 peteri

@peteri wrote:

(weirdly the 56K version doesn't work in AppleWin but that might be me doing something wrong).

It may be related to #498 ?

Okay I have patched the LDRBIOS...

This sounds like you have patched a floppy/hdv image. We should be aiming to mimic the Cirtech h/w, and so allow the original s/w to run (unpatched) under emulation.

tomcw avatar Jan 09 '24 07:01 tomcw

@peteri wrote:

(weirdly the 56K version doesn't work in AppleWin but that might be me doing something wrong).

It may be related to #498 ?

I'm not sure if that is down to me failing to understand how the CPM56.COM file works. I have found an 56K image that does work in AppleWin so I'll try that on real Cirtech hardware as the 44K version crashed.

Okay I have patched the LDRBIOS...

This sounds like you have patched a floppy/hdv image. We should be aiming to mimic the Cirtech h/w, and so allow the original s/w to run (unpatched) under emulation.

Ah a slightly different approach here, I've just done a patched build as it fixes a "bug" in the Loader BIOS and as a happy side effect lets the code work with a fixed 16MB auto expanding HDV file.

To run the original Cirtech code, we would need to modify z80_RDMEM and z80_WRMEM in z80.cpp to use a 0xF800 mask for the swapped addresses (and probably run a few more T-States, I need to break out my scope to figure out exact numbers). This does break the Softcard code, so what is the recommendation for controlling what sort of Z80 card is being emulated? Add it to the UI or just use a command line option (since it presumably won't be a popular requirement). The real question here is support for the other later Z80 cards is desired (Softcard //e, Applicard etc) with their separate on card 64K address space in future in which case adding a drop down to select the card type makes sense.

In a similar vein, adding support for returning the number of blocks in the hdv file breaks the auto expanding behavior that is currently in place. Again the question is should a patch just break this behavior or would we want some sort of UI. My personal preference is to add a command line switch if a user want's auto-expanding hdv files (i.e. -autoexpandhdv 0x7fff probably allowing both hex and decimal sizes) My guess here is most folks use CiderPress or similar to create a 32MB file anyway, given modern disc sizes, so a breaking change isn't a disaster.

Basically I'm don't have a strong opinion here and I'm looking for a bit of guidance on how to implement things without breaking existing users.

I would expect this to be two PRs (one for the z80 / one for the disk)

peteri avatar Jan 09 '24 11:01 peteri

This does break the Softcard code, so what is the recommendation for controlling what sort of Z80 card is being emulated? Add it to the UI or just use a command line option...

Adding a command line option is simplest, and is always a necessary first step. (GUI can be added later.)

re. auto expanding behaviour (aka auto-grow / auto-extend)

My personal preference is to add a command line switch if a user want's auto-expanding hdv files...

Yes, probably another cmd lin option for this. Like you, I agree that it's unlikely anyone actually uses this behaviour.

And finally from your 1st comment (at the top of this issue):

Note the size at $CxFC seems to be wrong for a 32Mb image? Formatting a new disk with ProDOS 2.4.2 shows the size as being 32767 blocks (which is 16MB) although the code happily works with a 32MB image (i.e. Total Replay shows the disk size as 65535 blocks)

We should probably fix this too - this issue is being tracked here in #1033. IE. the $Csnn firmware at $CsFC should be updated to reflect whatever is connected (harddisk) or in the drive (3.5" 800K floppy).

tomcw avatar Jan 09 '24 22:01 tomcw

This does break the Softcard code, so what is the recommendation for controlling what sort of Z80 card is being emulated? Add it to the UI or just use a command line option...

Adding a command line option is simplest, and is always a necessary first step. (GUI can be added later.)

re. auto expanding behaviour (aka auto-grow / auto-extend)

My personal preference is to add a command line switch if a user want's auto-expanding hdv files...

Yes, probably another cmd lin option for this. Like you, I agree that it's unlikely anyone actually uses this behaviour.

And finally from your 1st comment (at the top of this issue):

Note the size at $CxFC seems to be wrong for a 32Mb image? Formatting a new disk with ProDOS 2.4.2 shows the size as being 32767 blocks (which is 16MB) although the code happily works with a 32MB image (i.e. Total Replay shows the disk size as 65535 blocks)

We should probably fix this too - this issue is being tracked here in #1033. IE. the $Csnn firmware at $CsFC should be updated to reflect whatever is connected (harddisk) or in the drive (3.5" 800K floppy).

Sounds good to me, I'll probably have something together by the weekend (bit too much wine this evening) I'll have a look at 1033 as it seems related.

peteri avatar Jan 09 '24 22:01 peteri

Good progress in thinking. About 20 years ago no one wanted to implement Z80 Softcard in Applewin, as "not necessary" :) And it seems that soon we will have at least 2 different Z80 cards emulated...

SEGStriker avatar Jan 09 '24 23:01 SEGStriker

For the images from the link https://github.com/peteri/CirtechCPM/blob/main/DiskImages for CIRTECH CPM V2 BOOT.DSK and 0030_Cirtech_CPM_Plus_System_Master.po, even if the address mapping are done in AppleWin in accordance to the description below, it will not be able to boot Cirtech CP/M, it will return with the error "Incompatible Z-80 hardware"

Z80 6502
7800H $A800 (Swapped address)
9800H $8800 (Swapped address)

The address mapping is missing some entries, After the missing entries are added, it is able to boot both Cirtech CP/M version 1.07 and 2.02. The corrected address mapping table is shown below

Z80 6502
7800H $A800 (Swapped address)
8800H $A000 (Missing Entry)
9000H $9800 (Missing Entry)
9800H $8800 (Swapped address)

univta0001 avatar Jan 11 '24 08:01 univta0001

For the images from the link https://github.com/peteri/CirtechCPM/blob/main/DiskImages for CIRTECH CPM V2 BOOT.DSK and 0030_Cirtech_CPM_Plus_System_Master.po, even if the address mapping are done in AppleWin in accordance to the description below, it will not be able to boot Cirtech CP/M, it will return with the error "Incompatible Z-80 hardware"

Oooo nice find, I haven't yet dug into the V2 Cirtech code. The images I've seen of V2 are all for the IIGS (or at least they're all 800K disk images) the IIGS card doesn't plug into the 6502 socket (like the //c & //e) it's slot based. There is a Apple User magazine review of the hardware for the IIGS that says there are //c & //e versions available, but I don't know if that is using the same slot based hardware that the IIGS version uses.

I suspect that some of the other Cirtech hardware uses writes to the low bits of the address (A1,A0) as a means to perform the same copy protection that the address PROM provides by using A11 for the //e card. Certainly at least one revision of the Cirtech hardware does this as the code in the BIOS has two different mechanisms for checking the card. The code in the OEM version of the BIOS looks like this:

		ld   (ZROUT_6502),de
		ld   de,(ZCARD_Z80)	; de=E401
		inc  de
		inc  de			; de=E403
		ld   (de),a		; Off to 6502 land with odd address mapping		

or this (depending on which hardware check is being performed)

		ld   de,(ZCARD_Z80)	; Get card address (0E401H)
		inc  de			; Add one to it 0E402H
		ld   (de),a		; Jump to 6502

My guess would be that the low bits of the address bus are latched when the write to $E40x is seen and then the outputs of the latch are fed into the 4 bit adder on a typical Softcard clone design as a means of copy protection. But I've no idea what the IIGS V2 code is doing yet (the boot sector is definitely different).

It's worth noting that the Cirtech cards software uses $C401 / 0E401H rather than $C400 / 0E400H to swap between Z80 and 6502 mode so I'm guessing there are multiple revisions around.

I will add that as an option for the Cirtech Z80 mode.

peteri avatar Jan 11 '24 10:01 peteri

I did find a contact via the VCF hardware forums that might still have IIGS Cirtech hardware.

I'll see if I can get him to run the address mapper testing code I wrote for my hardware.

peteri avatar Jan 11 '24 10:01 peteri

In the Cirtech V2 code, the card checking code is different from v1. One of the card checking code is at 0005H / $1005 (in Z80) and $f9a in 6502. The code is shown below. The code provided the hint that 8800H is mapped to $A000.

; Z80 code check on 8875H with 6502 $A075. If does not matched bail out

        ld  hl, $88A0       ; Initialize hl to 88A0H
        ld  l, $75          ; Update hl to 8875H
        ld  a, (hl)             
        ld  c, a            ; Save the value of 8875H
        xor $59              
        ld  (hl),a          ; Store the value ^ 0x59 to 8875H
        ld  de, $0f9a       ; Setup return 6502 address to $F9A
        ld  ($f3d0),de
        ld  de,($f3de)      ; Set Z80 entry point, de = E401H
        inc de              ; de = E402H
        ld  (de),a          ; Going back to 6502, the $F9A routine will be called
        ld  a,c             ; Get back the result from 6502
        cp  (hl)            ; Compare the value in $A075 with 8875H
        ret z               ; Return successfully if matched
        jp  $FFAC           ; Show Incompatible Z80 Hardware
; 6502 routine at address $F9A

        lda $1006
        sta $0fa5
        sta $0faa
fa3:    lda $ff75           ; $ff will be modified to $a0
        eor #$59
fa8:    sta $ff75           ; $ff will be modified to $a0
        rts

univta0001 avatar Jan 11 '24 11:01 univta0001

Hi @peteri ,

Just a general point...

re. contributing patches / PRs - see note on CONTRIBUTING

Specifically if you can land some small PRs (and not just one big PR) this is much more managable for the reasons set out in the above the note.

So for example, a patch that adds a new command line option, even if it is only calls down to placeholder / dummy code is fine.

And also I'm happy to answer questions on AppleWin architecture. EG. if you add a 2nd CP/M card type (eg. Cirtech CP/M Plus) then what new files (cpp/h) should you add, and what existing files can you take advantage of. NB. I've not looked at your code in your branch/repo, so don't know how you have tackled this.

btw, as you probably seen in CardManager.cpp only one Z80 card can exist in an emulated Apple II model: https://github.com/AppleWin/AppleWin/blob/0888a25710fb67d44ac1f579d6ec18d6baaecca5/source/CardManager.cpp#L91 So all the code in Z80VICE can be used as-is for the Cirtech card, since there's only ever a single instance. (So no need to make any changes to any of these source files.)

tomcw avatar Jan 13 '24 11:01 tomcw

Hi there, I'm part way through on the hard drive stuff. I'm hoping to fiinish putting together the HDD stuff this weekend, right now my plan is add the option to the CmdLine class and #include CmdLine.h into the Harddisk.cpp and use a new member variable in g_cmdLine . For the Z80 stuff I'll open a new issue. The Z80 card is a bit more complicated as I suspect subclassing and making z80_RDMEM / z80_WRMEM virtual might the best way forward.

peteri avatar Jan 13 '24 11:01 peteri

The Z80 card is a bit more complicated as I suspect subclassing and making z80_RDMEM / z80_WRMEM virtual might the best way forward.

The patch from @univta0001 in #1271 is "good enough" from my POV. Try to KISS rather than C++ sub-classing (which feels like it'll just add more code & complexity). If more CP/M cards (with further different memory mappings) need to be added in the future, then maybe the #1271 patch doesn't scale. But we can cross that bridge if/when we come to it.

tomcw avatar Jan 16 '24 07:01 tomcw