/* SONYEMDV.c Copyright (C) 2009 Philip Cummins, Jesus A. Alvarez, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.*/ /* SONY floppy disk EMulated DeVice The Sony hardware is not actually emulated. Instead the ROM is patched to replace the Sony disk driver with code that calls Mini vMac extensions implemented in the file. Information neeeded to better support the Disk Copy 4.2 format was found in libdc42.c of the Lisa Emulator Project by Ray A. Arachelian, and adapted to Mini vMac by Jesus A. Alvarez.*/ #ifndef AllFiles#include "SYSDEPNS.h"#include "MYOSGLUE.h"#include "ENDIANAC.h"#include "EMCONFIG.h"#include "GLOBGLUE.h"#include "MINEM68K.h"#endif #include "SONYEMDV.h" /* ReportAbnormalID unused 0x090B - 0x09FF*/ LOCALVAR ui5b vSonyMountedMask = 0; #define vSonyIsLocked(Drive_No) \ ((vSonyWritableMask & ((ui5b)1 << (Drive_No))) == 0)#define vSonyIsMounted(Drive_No) \ ((vSonyMountedMask & ((ui5b)1 << (Drive_No))) != 0) LOCALFUNC blnr vSonyNextPendingInsert0(tDrive *Drive_No){ /* find next drive to Mount */ ui5b MountPending = vSonyInsertedMask & (~ vSonyMountedMask); if (MountPending != 0) { tDrive i; for (i = 0; i < NumDrives; ++i) { if ((MountPending & ((ui5b)1 << i)) != 0) { *Drive_No = i; return trueblnr; /* only one disk at a time */ } } } return falseblnr;} LOCALFUNC tMacErr CheckReadableDrive(tDrive Drive_No){ tMacErr result; if (Drive_No >= NumDrives) { result = mnvm_nsDrvErr; } else if (! vSonyIsMounted(Drive_No)) { result = mnvm_offLinErr; } else { result = mnvm_noErr; } return result;} LOCALFUNC tMacErr vSonyTransferVM(blnr IsWrite, CPTR Buffera, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount){ /* Transfer data between emulated disk and emulated memory. Taking into account that the emulated memory may not be contiguous in real memory. (Though it generally is for macintosh emulation.) */ tMacErr result; ui5b contig; ui5r actual; ui3p Buffer; ui5r offset = Sony_Start; ui5r n = Sony_Count; label_1: if (0 == n) { result = mnvm_noErr; } else { Buffer = get_real_address0(n, ! IsWrite, Buffera, &contig); if (0 == contig) { result = mnvm_miscErr; } else { result = vSonyTransfer(IsWrite, Buffer, Drive_No, offset, contig, &actual); offset += actual; Buffera += actual; n -= actual; if (mnvm_noErr == result) { goto label_1; } } } if (nullpr != Sony_ActCount) { *Sony_ActCount = Sony_Count - n; } return result;} LOCALPROC MyMoveBytesVM(CPTR srcPtr, CPTR dstPtr, si5b byteCount){ ui3p src; ui3p dst; ui5b contigSrc; ui5b contigDst; ui5r contig; label_1: if (0 != byteCount) { src = get_real_address0(byteCount, falseblnr, srcPtr, &contigSrc); dst = get_real_address0(byteCount, trueblnr, dstPtr, &contigDst); if ((0 == contigSrc) || (0 == contigDst)) { ReportAbnormalID(0x0901, "MyMoveBytesVM fails"); } else { contig = (contigSrc < contigDst) ? contigSrc : contigDst; MyMoveBytes(src, dst, contig); srcPtr += contig; dstPtr += contig; byteCount -= contig; goto label_1; } }} LOCALVAR ui5r ImageDataOffset[NumDrives]; /* size of any header in disk image file */LOCALVAR ui5r ImageDataSize[NumDrives]; /* size of disk image file contents */ #if Sony_SupportTagsLOCALVAR ui5r ImageTagOffset[NumDrives]; /* offset to disk image file tags */#endif #if Sony_SupportDC42#define kDC42offset_diskName 0#define kDC42offset_dataSize 64#define kDC42offset_tagSize 68#define kDC42offset_dataChecksum 72#define kDC42offset_tagChecksum 76#define kDC42offset_diskFormat 80#define kDC42offset_formatByte 81#define kDC42offset_private 82#define kDC42offset_userData 84#endif #define ChecksumBlockSize 1024 #if Sony_SupportDC42 && Sony_WantChecksumsUpdatedLOCALFUNC tMacErr DC42BlockChecksum(tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *r){ tMacErr result; ui5r n; ui3b Buffer[ChecksumBlockSize]; ui3b *p; ui5b sum = 0; ui5r offset = Sony_Start; ui5r remaining = Sony_Count; while (0 != remaining) { /* read a block */ if (remaining > ChecksumBlockSize) { n = ChecksumBlockSize; } else { n = remaining; } result = vSonyTransfer(falseblnr, Buffer, Drive_No, offset, n, nullpr); if (mnvm_noErr != result) { return result; } offset += n; remaining -= n; /* add to Checksum */ p = Buffer; n >>= 1; /* n = number of words */ while (0 != n) { --n; /* ROR.l sum+word */ sum += do_get_mem_word(p); p += 2; sum = (sum >> 1) | ((sum & 1) << 31); } } *r = sum; return mnvm_noErr;}#endif #if Sony_SupportDC42 && Sony_WantChecksumsUpdated#if Sony_SupportTags#define SizeCheckSumsToUpdate 8#else#define SizeCheckSumsToUpdate 4#endif#endif #if Sony_WantChecksumsUpdatedLOCALPROC Drive_UpdateChecksums(tDrive Drive_No){ if (! vSonyIsLocked(Drive_No)) { ui5r DataOffset = ImageDataOffset[Drive_No];#if Sony_SupportDC42 if (kDC42offset_userData == DataOffset) { /* a disk copy 4.2 image */ tMacErr result; ui5r dataChecksum; ui3b Buffer[SizeCheckSumsToUpdate]; ui5r Sony_Count = SizeCheckSumsToUpdate; ui5r DataSize = ImageDataSize[Drive_No]; /* Checksum image data */ result = DC42BlockChecksum(Drive_No, DataOffset, DataSize, &dataChecksum); if (mnvm_noErr != result) { ReportAbnormalID(0x0902, "Failed to find dataChecksum"); dataChecksum = 0; } do_put_mem_long(Buffer, dataChecksum);#if Sony_SupportTags { ui5r tagChecksum; ui5r TagOffset = ImageTagOffset[Drive_No]; ui5r TagSize = (0 == TagOffset) ? 0 : ((DataSize >> 9) * 12); if (TagSize < 12) { tagChecksum = 0; } else { /* Checksum of tags doesn't include first block. presumably because of bug in original disk copy program. */ result = DC42BlockChecksum(Drive_No, TagOffset + 12, TagSize - 12, &tagChecksum); if (mnvm_noErr != result) { ReportAbnormalID(0x0903, "Failed to find tagChecksum"); tagChecksum = 0; } } do_put_mem_long(Buffer + 4, tagChecksum); }#endif /* write Checksums */ vSonyTransfer(trueblnr, Buffer, Drive_No, kDC42offset_dataChecksum, Sony_Count, nullpr); }#endif }}#endif #define checkheaderoffset 0#define checkheadersize 128 #define Sony_SupportOtherFormats Sony_SupportDC42 LOCALFUNC tMacErr vSonyNextPendingInsert(tDrive *Drive_No){ tDrive i; tMacErr result; ui5r L; if (! vSonyNextPendingInsert0(&i)) { result = mnvm_nsDrvErr; } else { result = vSonyGetSize(i, &L); if (mnvm_noErr == result) { /* first, set up for default format */ ui5r DataOffset = 0; ui5r DataSize = L;#if Sony_SupportTags ui5r TagOffset = 0;#endif #if Sony_SupportOtherFormats#if IncludeSonyRawMode if (! vSonyRawMode)#endif { ui5r DataOffset0; ui5r DataSize0; ui5r TagOffset0; ui5r TagSize0; ui3b Temp[checkheadersize]; ui5r Sony_Count = checkheadersize; blnr gotFormat = falseblnr; result = vSonyTransfer(falseblnr, Temp, i, checkheaderoffset, Sony_Count, nullpr); if (mnvm_noErr == result) {#if Sony_SupportDC42 /* Detect Disk Copy 4.2 image */ if (0x0100 == do_get_mem_word( &Temp[kDC42offset_private])) { /* DC42 signature found, check sizes */ DataSize0 = do_get_mem_long( &Temp[kDC42offset_dataSize]); TagSize0 = do_get_mem_long( &Temp[kDC42offset_tagSize]); DataOffset0 = kDC42offset_userData; TagOffset0 = DataOffset0 + DataSize0; if (L >= (TagOffset0 + TagSize0)) if (0 == (DataSize0 & 0x01FF)) if ((DataSize0 >> 9) >= 4) if (Temp[kDC42offset_diskName] < 64) /* length of pascal string */ { if (0 == TagSize0) { /* no tags */ gotFormat = trueblnr; } else if ((DataSize0 >> 9) * 12 == TagSize0) { /* 12 byte tags */ gotFormat = trueblnr; } if (gotFormat) {#if Sony_VerifyChecksums /* mostly useful to check the Checksum code */ ui5r dataChecksum; ui5r tagChecksum; ui5r dataChecksum0 = do_get_mem_long( &Temp[kDC42offset_dataChecksum]); ui5r tagChecksum0 = do_get_mem_long( &Temp[kDC42offset_tagChecksum]); result = DC42BlockChecksum(i, DataOffset0, DataSize0, &dataChecksum); if (TagSize0 >= 12) { result = DC42BlockChecksum(i, TagOffset0 + 12, TagSize0 - 12, &tagChecksum); } else { tagChecksum = 0; } if (dataChecksum != dataChecksum0) { ReportAbnormalID(0x0904, "bad dataChecksum"); } if (tagChecksum != tagChecksum0) { ReportAbnormalID(0x0905, "bad tagChecksum"); }#endif DataOffset = DataOffset0; DataSize = DataSize0;#if Sony_SupportTags TagOffset = (0 == TagSize0) ? 0 : TagOffset0;#endif #if (! Sony_SupportTags) || (! Sony_WantChecksumsUpdated) if (! vSonyIsLocked(i)) {#if ! Sony_WantChecksumsUpdated /* unconditionally revoke */#else if (0 != TagSize0)#endif { DiskRevokeWritable(i); } }#endif } } }#endif /* Sony_SupportDC42 */ } } if (mnvm_noErr == result)#endif /* Sony_SupportOtherFormats */ { vSonyMountedMask |= ((ui5b)1 << i); ImageDataOffset[i] = DataOffset; ImageDataSize[i] = DataSize;#if Sony_SupportTags ImageTagOffset[i] = TagOffset;#endif *Drive_No = i; } } if (mnvm_noErr != result) { (void) vSonyEject(i); } } return result;} #define MinTicksBetweenInsert 240 /* if call PostEvent too frequently, insert events seem to get lost */ LOCALVAR ui4r DelayUntilNextInsert; LOCALVAR CPTR MountCallBack = 0; /* This checks to see if a disk (image) has been inserted */GLOBALPROC Sony_Update (void){ if (DelayUntilNextInsert != 0) { --DelayUntilNextInsert; } else { if (MountCallBack != 0) { tDrive i; if (mnvm_noErr == vSonyNextPendingInsert(&i)) { ui5b data = i; if (vSonyIsLocked(i)) { data |= ((ui5b)0x00FF) << 16; } DiskInsertedPsuedoException(MountCallBack, data); #if IncludeSonyRawMode if (! vSonyRawMode)#endif { DelayUntilNextInsert = MinTicksBetweenInsert; /* but usually will reach kDriveStatus first, where shorten delay. */ } } } }} LOCALFUNC tMacErr Drive_Transfer(blnr IsWrite, CPTR Buffera, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount){ tMacErr result; QuietEnds(); if (nullpr != Sony_ActCount) { *Sony_ActCount = 0; } result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { if (IsWrite && vSonyIsLocked(Drive_No)) { result = mnvm_vLckdErr; } else { ui5r DataSize = ImageDataSize[Drive_No]; if (Sony_Start > DataSize) { result = mnvm_eofErr; } else { blnr hit_eof = falseblnr; ui5r L = DataSize - Sony_Start; if (L >= Sony_Count) { L = Sony_Count; } else { hit_eof = trueblnr; } result = vSonyTransferVM(IsWrite, Buffera, Drive_No,Lines 1–500 of 1644. Load more
/* SONYEMDV.c Copyright (C) 2009 Philip Cummins, Jesus A. Alvarez, Paul C. Pratt You can redistribute this file and/or modify it under the terms of version 2 of the GNU General Public License as published by the Free Software Foundation. You should have received a copy of the license along with this file; see the file COPYING. This file is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. */ /* SONY floppy disk EMulated DeVice The Sony hardware is not actually emulated. Instead the ROM is patched to replace the Sony disk driver with code that calls Mini vMac extensions implemented in the file. Information neeeded to better support the Disk Copy 4.2 format was found in libdc42.c of the Lisa Emulator Project by Ray A. Arachelian, and adapted to Mini vMac by Jesus A. Alvarez. */ #ifndef AllFiles #include "SYSDEPNS.h" #include "MYOSGLUE.h" #include "ENDIANAC.h" #include "EMCONFIG.h" #include "GLOBGLUE.h" #include "MINEM68K.h" #endif #include "SONYEMDV.h" /* ReportAbnormalID unused 0x090B - 0x09FF */ LOCALVAR ui5b vSonyMountedMask = 0; #define vSonyIsLocked(Drive_No) \ ((vSonyWritableMask & ((ui5b)1 << (Drive_No))) == 0) #define vSonyIsMounted(Drive_No) \ ((vSonyMountedMask & ((ui5b)1 << (Drive_No))) != 0) LOCALFUNC blnr vSonyNextPendingInsert0(tDrive *Drive_No) { /* find next drive to Mount */ ui5b MountPending = vSonyInsertedMask & (~ vSonyMountedMask); if (MountPending != 0) { tDrive i; for (i = 0; i < NumDrives; ++i) { if ((MountPending & ((ui5b)1 << i)) != 0) { *Drive_No = i; return trueblnr; /* only one disk at a time */ } } } return falseblnr; } LOCALFUNC tMacErr CheckReadableDrive(tDrive Drive_No) { tMacErr result; if (Drive_No >= NumDrives) { result = mnvm_nsDrvErr; } else if (! vSonyIsMounted(Drive_No)) { result = mnvm_offLinErr; } else { result = mnvm_noErr; } return result; } LOCALFUNC tMacErr vSonyTransferVM(blnr IsWrite, CPTR Buffera, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount) { /* Transfer data between emulated disk and emulated memory. Taking into account that the emulated memory may not be contiguous in real memory. (Though it generally is for macintosh emulation.) */ tMacErr result; ui5b contig; ui5r actual; ui3p Buffer; ui5r offset = Sony_Start; ui5r n = Sony_Count; label_1: if (0 == n) { result = mnvm_noErr; } else { Buffer = get_real_address0(n, ! IsWrite, Buffera, &contig); if (0 == contig) { result = mnvm_miscErr; } else { result = vSonyTransfer(IsWrite, Buffer, Drive_No, offset, contig, &actual); offset += actual; Buffera += actual; n -= actual; if (mnvm_noErr == result) { goto label_1; } } } if (nullpr != Sony_ActCount) { *Sony_ActCount = Sony_Count - n; } return result; } LOCALPROC MyMoveBytesVM(CPTR srcPtr, CPTR dstPtr, si5b byteCount) { ui3p src; ui3p dst; ui5b contigSrc; ui5b contigDst; ui5r contig; label_1: if (0 != byteCount) { src = get_real_address0(byteCount, falseblnr, srcPtr, &contigSrc); dst = get_real_address0(byteCount, trueblnr, dstPtr, &contigDst); if ((0 == contigSrc) || (0 == contigDst)) { ReportAbnormalID(0x0901, "MyMoveBytesVM fails"); } else { contig = (contigSrc < contigDst) ? contigSrc : contigDst; MyMoveBytes(src, dst, contig); srcPtr += contig; dstPtr += contig; byteCount -= contig; goto label_1; } } } LOCALVAR ui5r ImageDataOffset[NumDrives]; /* size of any header in disk image file */ LOCALVAR ui5r ImageDataSize[NumDrives]; /* size of disk image file contents */ #if Sony_SupportTags LOCALVAR ui5r ImageTagOffset[NumDrives]; /* offset to disk image file tags */ #endif #if Sony_SupportDC42 #define kDC42offset_diskName 0 #define kDC42offset_dataSize 64 #define kDC42offset_tagSize 68 #define kDC42offset_dataChecksum 72 #define kDC42offset_tagChecksum 76 #define kDC42offset_diskFormat 80 #define kDC42offset_formatByte 81 #define kDC42offset_private 82 #define kDC42offset_userData 84 #endif #define ChecksumBlockSize 1024 #if Sony_SupportDC42 && Sony_WantChecksumsUpdated LOCALFUNC tMacErr DC42BlockChecksum(tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *r) { tMacErr result; ui5r n; ui3b Buffer[ChecksumBlockSize]; ui3b *p; ui5b sum = 0; ui5r offset = Sony_Start; ui5r remaining = Sony_Count; while (0 != remaining) { /* read a block */ if (remaining > ChecksumBlockSize) { n = ChecksumBlockSize; } else { n = remaining; } result = vSonyTransfer(falseblnr, Buffer, Drive_No, offset, n, nullpr); if (mnvm_noErr != result) { return result; } offset += n; remaining -= n; /* add to Checksum */ p = Buffer; n >>= 1; /* n = number of words */ while (0 != n) { --n; /* ROR.l sum+word */ sum += do_get_mem_word(p); p += 2; sum = (sum >> 1) | ((sum & 1) << 31); } } *r = sum; return mnvm_noErr; } #endif #if Sony_SupportDC42 && Sony_WantChecksumsUpdated #if Sony_SupportTags #define SizeCheckSumsToUpdate 8 #else #define SizeCheckSumsToUpdate 4 #endif #endif #if Sony_WantChecksumsUpdated LOCALPROC Drive_UpdateChecksums(tDrive Drive_No) { if (! vSonyIsLocked(Drive_No)) { ui5r DataOffset = ImageDataOffset[Drive_No]; #if Sony_SupportDC42 if (kDC42offset_userData == DataOffset) { /* a disk copy 4.2 image */ tMacErr result; ui5r dataChecksum; ui3b Buffer[SizeCheckSumsToUpdate]; ui5r Sony_Count = SizeCheckSumsToUpdate; ui5r DataSize = ImageDataSize[Drive_No]; /* Checksum image data */ result = DC42BlockChecksum(Drive_No, DataOffset, DataSize, &dataChecksum); if (mnvm_noErr != result) { ReportAbnormalID(0x0902, "Failed to find dataChecksum"); dataChecksum = 0; } do_put_mem_long(Buffer, dataChecksum); #if Sony_SupportTags { ui5r tagChecksum; ui5r TagOffset = ImageTagOffset[Drive_No]; ui5r TagSize = (0 == TagOffset) ? 0 : ((DataSize >> 9) * 12); if (TagSize < 12) { tagChecksum = 0; } else { /* Checksum of tags doesn't include first block. presumably because of bug in original disk copy program. */ result = DC42BlockChecksum(Drive_No, TagOffset + 12, TagSize - 12, &tagChecksum); if (mnvm_noErr != result) { ReportAbnormalID(0x0903, "Failed to find tagChecksum"); tagChecksum = 0; } } do_put_mem_long(Buffer + 4, tagChecksum); } #endif /* write Checksums */ vSonyTransfer(trueblnr, Buffer, Drive_No, kDC42offset_dataChecksum, Sony_Count, nullpr); } #endif } } #endif #define checkheaderoffset 0 #define checkheadersize 128 #define Sony_SupportOtherFormats Sony_SupportDC42 LOCALFUNC tMacErr vSonyNextPendingInsert(tDrive *Drive_No) { tDrive i; tMacErr result; ui5r L; if (! vSonyNextPendingInsert0(&i)) { result = mnvm_nsDrvErr; } else { result = vSonyGetSize(i, &L); if (mnvm_noErr == result) { /* first, set up for default format */ ui5r DataOffset = 0; ui5r DataSize = L; #if Sony_SupportTags ui5r TagOffset = 0; #endif #if Sony_SupportOtherFormats #if IncludeSonyRawMode if (! vSonyRawMode) #endif { ui5r DataOffset0; ui5r DataSize0; ui5r TagOffset0; ui5r TagSize0; ui3b Temp[checkheadersize]; ui5r Sony_Count = checkheadersize; blnr gotFormat = falseblnr; result = vSonyTransfer(falseblnr, Temp, i, checkheaderoffset, Sony_Count, nullpr); if (mnvm_noErr == result) { #if Sony_SupportDC42 /* Detect Disk Copy 4.2 image */ if (0x0100 == do_get_mem_word( &Temp[kDC42offset_private])) { /* DC42 signature found, check sizes */ DataSize0 = do_get_mem_long( &Temp[kDC42offset_dataSize]); TagSize0 = do_get_mem_long( &Temp[kDC42offset_tagSize]); DataOffset0 = kDC42offset_userData; TagOffset0 = DataOffset0 + DataSize0; if (L >= (TagOffset0 + TagSize0)) if (0 == (DataSize0 & 0x01FF)) if ((DataSize0 >> 9) >= 4) if (Temp[kDC42offset_diskName] < 64) /* length of pascal string */ { if (0 == TagSize0) { /* no tags */ gotFormat = trueblnr; } else if ((DataSize0 >> 9) * 12 == TagSize0) { /* 12 byte tags */ gotFormat = trueblnr; } if (gotFormat) { #if Sony_VerifyChecksums /* mostly useful to check the Checksum code */ ui5r dataChecksum; ui5r tagChecksum; ui5r dataChecksum0 = do_get_mem_long( &Temp[kDC42offset_dataChecksum]); ui5r tagChecksum0 = do_get_mem_long( &Temp[kDC42offset_tagChecksum]); result = DC42BlockChecksum(i, DataOffset0, DataSize0, &dataChecksum); if (TagSize0 >= 12) { result = DC42BlockChecksum(i, TagOffset0 + 12, TagSize0 - 12, &tagChecksum); } else { tagChecksum = 0; } if (dataChecksum != dataChecksum0) { ReportAbnormalID(0x0904, "bad dataChecksum"); } if (tagChecksum != tagChecksum0) { ReportAbnormalID(0x0905, "bad tagChecksum"); } #endif DataOffset = DataOffset0; DataSize = DataSize0; #if Sony_SupportTags TagOffset = (0 == TagSize0) ? 0 : TagOffset0; #endif #if (! Sony_SupportTags) || (! Sony_WantChecksumsUpdated) if (! vSonyIsLocked(i)) { #if ! Sony_WantChecksumsUpdated /* unconditionally revoke */ #else if (0 != TagSize0) #endif { DiskRevokeWritable(i); } } #endif } } } #endif /* Sony_SupportDC42 */ } } if (mnvm_noErr == result) #endif /* Sony_SupportOtherFormats */ { vSonyMountedMask |= ((ui5b)1 << i); ImageDataOffset[i] = DataOffset; ImageDataSize[i] = DataSize; #if Sony_SupportTags ImageTagOffset[i] = TagOffset; #endif *Drive_No = i; } } if (mnvm_noErr != result) { (void) vSonyEject(i); } } return result; } #define MinTicksBetweenInsert 240 /* if call PostEvent too frequently, insert events seem to get lost */ LOCALVAR ui4r DelayUntilNextInsert; LOCALVAR CPTR MountCallBack = 0; /* This checks to see if a disk (image) has been inserted */ GLOBALPROC Sony_Update (void) { if (DelayUntilNextInsert != 0) { --DelayUntilNextInsert; } else { if (MountCallBack != 0) { tDrive i; if (mnvm_noErr == vSonyNextPendingInsert(&i)) { ui5b data = i; if (vSonyIsLocked(i)) { data |= ((ui5b)0x00FF) << 16; } DiskInsertedPsuedoException(MountCallBack, data); #if IncludeSonyRawMode if (! vSonyRawMode) #endif { DelayUntilNextInsert = MinTicksBetweenInsert; /* but usually will reach kDriveStatus first, where shorten delay. */ } } } } } LOCALFUNC tMacErr Drive_Transfer(blnr IsWrite, CPTR Buffera, tDrive Drive_No, ui5r Sony_Start, ui5r Sony_Count, ui5r *Sony_ActCount) { tMacErr result; QuietEnds(); if (nullpr != Sony_ActCount) { *Sony_ActCount = 0; } result = CheckReadableDrive(Drive_No); if (mnvm_noErr == result) { if (IsWrite && vSonyIsLocked(Drive_No)) { result = mnvm_vLckdErr; } else { ui5r DataSize = ImageDataSize[Drive_No]; if (Sony_Start > DataSize) { result = mnvm_eofErr; } else { blnr hit_eof = falseblnr; ui5r L = DataSize - Sony_Start; if (L >= Sony_Count) { L = Sony_Count; } else { hit_eof = trueblnr; } result = vSonyTransferVM(IsWrite, Buffera, Drive_No,