Hiya,

I've been implementing a fake block device driver in Pyromaniac and found 
that I was unable to access the hard disc files used by RPCEmu. All I was 
doing was the (I thought) most obvious solution of treating the disc file 
as a raw sequence of bytes. That's not how the HDF works, and from reading 
the ide.c source in loadhd and a clue from David Thomas, I see that it 
does some jumping around to decide whether it should skip 512 bytes at the 
start of the file.

There's no justification given in the comments, so I tried to work out a 
reason for it. Other than 'leaving space for a potential header in the 
future, but still working with raw disc dumps', I couldn't come up with 
one. It would be handy if such things were described, so in my 
implementation I've left some commentary of this to explain it in the 
future. I offer that code and commentary in case it helps someone to 
improve the existing RPCEmu (ie someone could explain why this juggling is 
done), or someone can explain where it's wrong and I can update my code. 

This is python code, and it's based an an existing BlockData class which 
provides the guarded access to the disc image between a given offset and 
size:

----
class HDFBlockData(BlockData):
    """
    Handle a block file for a HDF file, as used by RPCEmu.

    These files are based around the storage of a harddisc image as written by
    the controller in RPCEmu using the parameters stored in the FileCore
    disc record at the start of the disc (disc address &C00). However, there is
    the potential for all the disc data to be offset by 512 bytes.

    The algorithm basically allows the HDF reader to read a raw FileCore image
    if one has been given, but defaults to the image being at offset 512.

    The result is that newly created discs will have the 512 byte header.
    Existing discs which skip a 512 byte header will be just fine.
    Existing, and newly ripped, discs that are just a dump of the disc contents
    will be fine.

    There's a risk that another format might have data in these low sectors but
    then the chance of those discs being supplied to RPCEmu is low, so this is
    probably reasonable.

    The probable reason for this offset was that some header containing metadata
    could be included in the future. However, no such metadata is used or 
present
    at the current time.
    """

    def __init__(self, *args, **kwargs):
        super(HDFBlockData, self).__init__(*args, **kwargs)

        # First read some data from the start of the file.
        sector_c00 = bytearray(self.read(DiscTransfer(address=0xc00, 
size=0x200), 0x200))
        sector_e00 = bytearray(self.read(DiscTransfer(address=0xe00, 
size=0x200), 0x200))

        if len(sector_c00) < 0x200 or len(sector_e00) < 0x200:
            # This disc is short, so we'll do no manipulation at all.
            return

        secspertrack_c00 = sector_c00[0x1c1]
        heads_c00 = sector_c00[0x1c2]
        secspertrack_e00 = sector_e00[0x1c1]
        heads_e00 = sector_e00[0x1c2]

        offset = 0
        if secspertrack_e00 != 0 and heads_e00 != 0:
            # The two fields we're using as our basis are valid at offset 512. 
So
            # we use that. So there is a disc record here, we'll use it.
            print("HDF disc record lives at offset 512 + 0xc00")
            offset = 512
        elif secspertrack_c00 == 0 and heads_c00 == 0:
            # The two fields aren't valid without any offset. We will apply the
            # offset of 512.
            print("HDF disc record not present so assumingdisc offset at offset 
512")
            offset = 512
        else:
            # There was a disc record at offset 0, so we use that.
            print("HDF disc record lives at offset 0 + 0xc00")
            offset = 0

        if offset:
            # We need to change the data access offsets for this data so that 
we only
            # access the actual data which RISC OS expects to see.
            self.close()
            if self._initial_limit:
                self._initial_limit -= offset
            self.data_offset += offset
----

It's not at all complex, but it matches the results of what loadhd does, 
and allows me to mount existing .hdf files and raw dumps of a disc.

-- 
Charles Justin Ferguson
[ All information, speculation, opinion or data within, or attached to,
  this email is private and confidential. Such content may not be
  disclosed to third parties, or a public forum, without explicit
  permission being granted. ]


_______________________________________________
RPCEmu mailing list
RPCEmu@riscos.info
http://www.riscos.info/cgi-bin/mailman/listinfo/rpcemu

Reply via email to