beebem-windows icon indicating copy to clipboard operation
beebem-windows copied to clipboard

OPUS DDOS 3.45 usually not writing last byte of track

Open SamSkivington opened this issue 4 years ago • 30 comments

When using OSWORD &7F or OSFILE, the last byte of every(+) track written to disk is 00 when using Opus DDOS 3.45, although logging shows the correct values are sent to the FDC.

The same is not true when using Acorn DFS 2.26.

I can't see anything different in the order that FDC registers are read/written during successes and failures so I'm guessing it's timing related.

(+) If I perform these OSBYTE &7F calls:

  • write track 77 with 10 sectors
  • read 10 sectors back from track 77 (and compare)
  • write track 78 with 10 sectors
  • read 10 sectors back from track 78 (and compare)
  • write track 79 with 10 sectors
  • read 10 sectors back from track 79 (and compare)

tracks 77 and 78 writes a zero as the last byte on the track (disk image file shows that either 00 has been written or nothing was) and track 79 is correct when it's read back.

I've tried this with BeebEm versions as far back as 4.03 and it's the same.

I've also tried reducing and increasing the delay in DDOS between writing the last byte to the data register and sending the Force Interrupt command, but no change.

I'm happy to go and hunt down the relevant bit(s) of code in the FDC emulation; just wondering whether someone might (1) already be looking at this or (2) have a bit of insight into where/why this might be happening. I can see there are a couple of Opus-related comments in disc1770.cpp.

Thanks :)

SamSkivington avatar Sep 04 '20 18:09 SamSkivington

Thanks Sam. I'm not aware of anyone looking at this, so any help you can give would be very welcome!

chrisn avatar Sep 04 '20 19:09 chrisn

Quick update: Acorn DFS 2.26 performs multiple sector writes one at a time rather than all in one go, whereas DDOS writes them all in one operation.

SamSkivington avatar Sep 06 '20 09:09 SamSkivington

When I take NMILock out of the equation during the 1770 poll function, the issue disappears on DDOS 3.45 (and a test program I wrote based on the datasheet). DDOS (and me) sends the ForceInterrupt command inside the NMI routine. Now to work out why it was being tested in the poll function in the first place.

SamSkivington avatar Sep 07 '20 11:09 SamSkivington

@chrisn does a list of DFS* and a test Beeb program exist that the 1770 emulation has previously been tested with? I'm fine writing the program to give the FDC a workout, so maybe just a list of FS ROMs/versions? Everything seems fine with Opus DDOS 3.45, Acorn DFS 2.26 and ADFS 1.33.

SamSkivington avatar Sep 07 '20 11:09 SamSkivington

When I take NMILock out of the equation during the 1770 poll function, the issue disappears on DDOS 3.45 (and a test program I wrote based on the datasheet). DDOS (and me) sends the ForceInterrupt command inside the NMI routine. Now to work out why it was being tested in the poll function in the first place.

This change was introduced in BeebEm 1.4 (see diff in disc1770.cpp), at the same time as Force Interrupt was implemented, although I don't know why (I haven't studied the 1770 emulation).

chrisn avatar Sep 07 '20 16:09 chrisn

Hmmm. I saw the last change to that line was a very long time ago and felt sure I'd seen DDOS working since then. It would seem not. It does suggest it may have been added for a specific scenario, possibly related to Force Interrupt and/or Read Address. I'll write a program to put raw FDC access, OSWORD & all the other FS related OS* calls through their paces and run it against a large-ish selection of (A)DFS/machine type combinations then. I'll report back.

SamSkivington avatar Sep 07 '20 16:09 SamSkivington

Actually, before I do that, NMILock appears to be related to the 6502 not attempting to re-enter the NMI routine whilst an existing one is running (haven't got the datasheet for 6502 open but I'm pretty certain NMIs aren't detected while one is being processed). The FDC has no idea what was going on with the internal state of the 6502, so I don't think it should be in the 1770 code at all. What do you think?

SamSkivington avatar Sep 07 '20 17:09 SamSkivington

A further thought on that is that a WD1770PH 02-02 variant could be clocked at 16MHz to allow it to read/write HD floppy disks, although it was incredibly tight fitting a NMI handler in that wasn't too long in terms of CPU cycles. Perhaps it was related to an attempt to get that working? Are there any DFS's that claim to support HD floppies that you're aware of?

SamSkivington avatar Sep 07 '20 17:09 SamSkivington

I still think I need to write a program to test Read Address, though. I haven't explicitly tried that, although I can't think of a reason it would be any different to a Read Sector command in terms of the timing of the DFS telling the FDC to stop sending data - there's plenty of time during the 'gap' following (or even before) the ID CRC to send Force Interrupt before the next byte fully appears under the head and the FDC starts prodding the NMI pin again.

SamSkivington avatar Sep 07 '20 17:09 SamSkivington

Actually, before I do that, NMILock appears to be related to the 6502 not attempting to re-enter the NMI routine whilst an existing one is running (haven't got the datasheet for 6502 open but I'm pretty certain NMIs aren't detected while one is being processed).

Reading this and this, I'm not sure if that's true. The NMILock variable has been in BeebEm since the very beginning, but I don't know why it's there. Other emulators (B-Em and JSBeeb) don't have a similar lock.

chrisn avatar Sep 07 '20 18:09 chrisn

Timing diagram confirms that - a NMI can interrupt a NMI. Didn't know that - I guess there's usually only one NMI source in a lot of cases so unlikely to occur. :)

So shall we take the NMILock part out of the 1770 code? (probably not worth raising a PR for that - it's one line of code being changed). It doesn't really belong in an external chip's code.

I'm looking more deeply into the Read Address command now because DDOS isn't trying to switch densities when the initial SD Read Address command fails, where it does on a physical machine. It'd be good to get both of these aspects of the FDC working closer to 100%.

SamSkivington avatar Sep 07 '20 18:09 SamSkivington

I might remove the NMILock altogether in my local copy and see if anything breaks. I wonder if we need to add timing before which a second NMI won't be recognised.

I've just done a quick test with Watford DDFS 1.54T from here, which seems to work if you select the Watford.dll FDC. Maybe we should distribute this ROM with BeebEm.

A set of tests would be really helpful, thanks for looking into this!

chrisn avatar Sep 07 '20 19:09 chrisn

I might remove the NMILock altogether in my local copy and see if anything breaks.

Opus DDOS 3.45 seems OK with the NMILock removed, but Watford DDFS 1.54T doesn't like it (*CAT hangs and produces no output).

chrisn avatar Sep 07 '20 19:09 chrisn

You said 1.54T worked with the Watford board selected before. Sure you had the right board selected during that last test? General behaviour I've seen with non-Acorn DFS's is to hang with the wrong board in.

SamSkivington avatar Sep 07 '20 19:09 SamSkivington

Yes, in both cases I had Watford.dll selected. The first test was before I removed NMILock and it worked OK, and it hangs after removing NMILock.

chrisn avatar Sep 07 '20 19:09 chrisn

Ok. I'll have a look at what it's trying to do, NMI code first. Assuming Shift+Break did the same? That FS is DD only, isn't it?

SamSkivington avatar Sep 07 '20 19:09 SamSkivington

Yes, Shift+Break hangs in the same way. The DDFS I guess supports both SD and DD disks, although I only have SD images to test with. *CAT on a .ssd file reports "Single density".

chrisn avatar Sep 07 '20 19:09 chrisn

Ah. Sounding similar to DDOS then. Do you know whether 1.54T uses 16 or 18 sectors in DD?

SamSkivington avatar Sep 07 '20 20:09 SamSkivington

Assuming this is the correct manual (it's the only one I've found so far), it's 18 sectors per track.

chrisn avatar Sep 07 '20 20:09 chrisn

Ok. Cool. Thank you. That will all give me some good pointers for analysing the code. It'll be something small that we haven't thought of, I'm sure :)

SamSkivington avatar Sep 07 '20 20:09 SamSkivington

I hope so! This isn't an area I've looked at before, so I'm learning as we go.

chrisn avatar Sep 07 '20 20:09 chrisn

When I removed NMILock from the 1770 code, 1.54T hangs. It's waiting for the contents of &1036 to have bit 0 clear. The NMI routine sets ?&1036 to ?FDC_STATUS_REGISTER most of the time, but when the byte counter reaches zero it sets ?&1036 to zero and then has a pause before sending the Force Interrupt command. In the emulation, during that pause, the next sector's byte is triggering another NMI, so when Force Interrupt is performed the value has been overwritten with ?FDC_STATUS_REGISTER again (including bit 0 indicating a busy status). When I slow the disc revolution time down a bit (1400000 instead of 500000) it takes a while but it does catalogue the disc.

So what I think is going on is that the Read Sector command isn't waiting long enough between sectors before sending the next sector's bytes. On a real machine, there's a gap between sectors (all the 4E bytes and the 00s, the ID, ID CRC, DAM etc.) so the NMI routine pause is nowhere near long enough to cause a problem - it wouldn't be interrupted by the next sector's data.

So, when I set LoadingCycles to (BYTE_TIME * 80) (for now) when it's a multi sector read and the last byte in the sector has been transferred, and change the disc revolution time back to 500000, it seems to be working. I'll do a lot more testing of this - and actually count how many bytes the datasheet says are the minimum between sectors.

SamSkivington avatar Sep 08 '20 08:09 SamSkivington

Sorting out the Write Sector command is going to be a bit more tricky. At the moment it looks like it's going to need a bit or re-ordering because it writes a byte to disc and, if the command had the multi-sector flag set, immediately raises another interrupt, which is not correct; at the end of the sector it should wait for the gap time again before asking the CPU for the next byte.

SamSkivington avatar Sep 08 '20 10:09 SamSkivington

I'm going to have to pause with this for the rest of the day. It's going kinda ok, but there are inconsistencies with whether or not it will write to the disc and let the NMI routine realise. I have successfully formatted a few discs, but it's about a 50% failure rate too, so I need to have a think about how that could be in a software emulation. There shouldn't be anything else interfering so maybe it's related to the Read Address command that's going wrong in Opus DDOS and DDFS is getting itself into a bit of a tizz, not realising it already knows the density of the disc/drive in question..

SamSkivington avatar Sep 08 '20 13:09 SamSkivington

What disc image format are you using for DDOS/DDFS discs? Here are some links to related discussions:

  • https://stardot.org.uk/forums/viewtopic.php?t=20187
  • https://stardot.org.uk/forums/viewtopic.php?t=11924
  • https://stardot.org.uk/forums/viewtopic.php?t=5821

chrisn avatar Sep 08 '20 13:09 chrisn

I haven't settled on one yet. At the moment I've just copy/paste/modify the ADFS bits and told it the relevant numbers for 18 sectors instead of 16 and called it OPUS instead of ADFS. I'm getting a little closer (but not close enough just yet) to thinking the 1770 code should be torn up (I hope not, but it's very difficult to read 20 years after the event and perhaps some #defines or an enum or two would help), at which point I'd probably start thinking about raw MF/MFM that the HxC floppy drive emulates as an internal format but still support the existing ones for on-disk/online image files. Raw FM/MFM could still be a thing without tearing up the existing FDC emulation(s) but that's a discussion for later. Also, using such a format, even internally would involve discussions and gaining consensus among a few parties, including you of course, all developers who are working anywhere near FDC code or disk manipulation, etc, and certainly not a small undertaking. I've only really had high level thoughts about that so far. What would be your preference(s)?

SamSkivington avatar Sep 08 '20 14:09 SamSkivington

I've now read those all to completion. I think it's a wider conversation for standardising what BeebEm uses internally and for other formats it could load/save (and import/export to/from). It would be nice to get all of that side of things into separate areas (VS filter folders) so that a disc format would have a standard interface (a bit like the DDOS/DDFS board DLLs - but hopefully not DLLs for a few number and boolean definitions) and importers/exporters would have their own place in the solution structure too. I guess that's another point for discussion. Maybe a Zoom call or two might happen? Things are generally solved faster when people speak instead of typing :)

SamSkivington avatar Sep 08 '20 14:09 SamSkivington

Someone's working on a new format for load/save so it would be good to get them involved in the discussion because whatever is decided would/could have a big impact on future development, when, say, DeveloperX invents some amazing format that the whole emulation scene decided to use. It may or may not be important for them atm, but we should keep an eye on who's announced what for new file format support.

SamSkivington avatar Sep 08 '20 15:09 SamSkivington

Consensus seems now to be for HFE as preferred format, at least for reading. Supporting this in BeebEm is likely to require rewriting the 1770 and 8271 emulation. I'd like to look at that separately though, and for now stick with an SSD like format.

chrisn avatar Sep 08 '20 16:09 chrisn

It would be SO good to make all the DD fans happy with a disc format everyone agrees on. Let's do that.

SamSkivington avatar Sep 08 '20 17:09 SamSkivington