/[svn]/libgig/trunk/src/Akai.cpp
ViewVC logotype

Diff of /libgig/trunk/src/Akai.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2572 by schoenebeck, Thu May 22 12:14:04 2014 UTC revision 3476 by schoenebeck, Wed Feb 20 19:12:49 2019 UTC
# Line 2  Line 2 
2    libakai - C++ cross-platform akai sample disk reader    libakai - C++ cross-platform akai sample disk reader
3    Copyright (C) 2002-2003 Sébastien Métrot    Copyright (C) 2002-2003 Sébastien Métrot
4    
5    Linux port by Christian Schoenebeck <cuse@users.sourceforge.net> 2003-2014    Linux port by Christian Schoenebeck <cuse@users.sourceforge.net> 2003-2019
6    
7    This library is free software; you can redistribute it and/or    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Lesser General Public    modify it under the terms of the GNU Lesser General Public
# Line 24  Line 24 
24    
25  #include <stdio.h>  #include <stdio.h>
26  #include <string.h>  #include <string.h>
27  #include <unistd.h>  #ifndef _MSC_VER
28  #include <fcntl.h>  # include <unistd.h>
29  #include <sys/ioctl.h>  # include <fcntl.h>
30    #endif
31    #if defined(_CARBON_) || defined(__APPLE__)
32    # if defined (__GNUC__) && (__GNUC__ >= 4)
33    #  include <sys/disk.h>
34    # else
35    #  include <dev/disk.h>
36    # endif
37    #endif
38  #include <sys/types.h>  #include <sys/types.h>
39  #include <sys/stat.h>  #include <sys/stat.h>
40  #include <errno.h>  #include <errno.h>
41    #if defined(_CARBON_) || defined(__APPLE__)
42  #include <paths.h>  #include <paths.h>
43  #ifdef _CARBON_  #include <sys/ioctl.h>
44  #include <sys/param.h>  #include <sys/param.h>
45  #include <IOKit/IOKitLib.h>  #include <IOKit/IOKitLib.h>
46  #include <IOKit/IOBSD.h>  #include <IOKit/IOBSD.h>
# Line 42  Line 51 
51  #include <CoreFoundation/CoreFoundation.h>  #include <CoreFoundation/CoreFoundation.h>
52  #endif  #endif
53    
54    #if defined(_CARBON_) || defined(__APPLE__)
55    
56    // These definitions were taken from mount_cd9660.c
57    // There are some similar definitions in IOCDTypes.h
58    // however there seems to be some dissagreement in
59    // the definition of CDTOC.length
60    struct _CDMSF {
61        u_char   minute;
62        u_char   second;
63        u_char   frame;
64    };
65    
66    #define MSF_TO_LBA(msf)                \
67         (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150)
68    
69    struct _CDTOC_Desc {
70        u_char        session;
71        u_char        ctrl_adr;  /* typed to be machine and compiler independent */
72        u_char        tno;
73        u_char        point;
74        struct _CDMSF address;
75        u_char        zero;
76        struct _CDMSF p;
77    };
78    
79    struct _CDTOC {
80        u_short            length;  /* in native cpu endian */
81        u_char             first_session;
82        u_char             last_session;
83        struct _CDTOC_Desc trackdesc[1];
84    };
85    
86    // Most of the following Mac CDROM IO functions were taken from Apple's IOKit
87    // examples (BSD style license). ReadTOC() function was taken from the Bochs x86
88    // Emulator (LGPL). Most probably they have taken it however also from some
89    // other BSD style licensed example code as well ...
90    
91    // Returns an iterator across all CD media (class IOCDMedia). Caller is responsible for releasing
92    // the iterator when iteration is complete.
93    static kern_return_t FindEjectableCDMedia(io_iterator_t *mediaIterator) {
94        kern_return_t kernResult;
95        CFMutableDictionaryRef classesToMatch;
96    
97        // CD media are instances of class kIOCDMediaClass
98        classesToMatch = IOServiceMatching(kIOCDMediaClass);
99        if (classesToMatch == NULL) {
100            printf("IOServiceMatching returned a NULL dictionary.\n");
101        } else {
102            CFDictionarySetValue(classesToMatch, CFSTR(kIOMediaEjectableKey), kCFBooleanTrue);
103            // Each IOMedia object has a property with key kIOMediaEjectableKey which is true if the
104            // media is indeed ejectable. So add this property to the CFDictionary we're matching on.
105        }
106    
107        kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, mediaIterator);
108        
109        return kernResult;
110    }
111    
112    // Given an iterator across a set of CD media, return the BSD path to the
113    // next one. If no CD media was found the path name is set to an empty string.
114    static kern_return_t GetBSDPath(io_iterator_t mediaIterator, char *bsdPath, CFIndex maxPathSize) {
115        io_object_t nextMedia;
116        kern_return_t kernResult = KERN_FAILURE;
117        
118        *bsdPath = '\0';
119        
120        nextMedia = IOIteratorNext(mediaIterator);
121        if (nextMedia) {
122            CFTypeRef bsdPathAsCFString;
123            
124            bsdPathAsCFString = IORegistryEntryCreateCFProperty(nextMedia,
125                                                                CFSTR(kIOBSDNameKey),
126                                                                kCFAllocatorDefault,
127                                                                0);
128            if (bsdPathAsCFString) {
129                strlcpy(bsdPath, _PATH_DEV, maxPathSize);
130                
131                // Add "r" before the BSD node name from the I/O Registry to specify the raw disk
132                // node. The raw disk nodes receive I/O requests directly and do not go through
133                // the buffer cache.
134                
135                strlcat(bsdPath, "r", maxPathSize);
136                
137                size_t devPathLength = strlen(bsdPath);
138                
139                if (CFStringGetCString((CFStringRef)bsdPathAsCFString,
140                                       bsdPath + devPathLength,
141                                       maxPathSize - devPathLength,
142                                       kCFStringEncodingUTF8)) {
143                    printf("BSD path: %s\n", bsdPath);
144                    kernResult = KERN_SUCCESS;
145                }
146                
147                CFRelease(bsdPathAsCFString);
148            }
149        
150            IOObjectRelease(nextMedia);
151        }
152        
153        return kernResult;
154    }
155    
156    // Given the path to a CD drive, open the drive.
157    // Return the file descriptor associated with the device.
158    /*static int OpenDrive(const char *bsdPath) {
159        int fileDescriptor;
160        
161        // This open() call will fail with a permissions error if the sample has been changed to
162        // look for non-removable media. This is because device nodes for fixed-media devices are
163        // owned by root instead of the current console user.
164    
165        fileDescriptor = open(bsdPath, O_RDONLY);
166        
167        if (fileDescriptor == -1) {
168            printf("Error opening device %s: ", bsdPath);
169            perror(NULL);
170        }
171        
172        return fileDescriptor;
173    }*/
174    
175    // Given the file descriptor for a whole-media CD device, read a sector from the drive.
176    // Return true if successful, otherwise false.
177    /*static Boolean ReadSector(int fileDescriptor) {
178        char *buffer;
179        ssize_t numBytes;
180        u_int32_t blockSize;
181        
182        // This ioctl call retrieves the preferred block size for the media. It is functionally
183        // equivalent to getting the value of the whole media object's "Preferred Block Size"
184        // property from the IORegistry.
185        if (ioctl(fileDescriptor, DKIOCGETBLOCKSIZE, &blockSize)) {
186            perror("Error getting preferred block size");
187            
188            // Set a reasonable default if we can't get the actual preferred block size. A real
189            // app would probably want to bail at this point.
190            blockSize = kCDSectorSizeCDDA;
191        }
192        
193        printf("Media has block size of %d bytes.\n", blockSize);
194        
195        // Allocate a buffer of the preferred block size. In a real application, performance
196        // can be improved by reading as many blocks at once as you can.
197        buffer = (char*) malloc(blockSize);
198        
199        // Do the read. Note that we use read() here, not fread(), since this is a raw device
200        // node.
201        numBytes = read(fileDescriptor, buffer, blockSize);
202            
203        // Free our buffer. Of course, a real app would do something useful with the data first.
204        free(buffer);
205        
206        return numBytes == blockSize ? true : false;
207    }*/
208    
209    // Given the file descriptor for a device, close that device.
210    /*static void CloseDrive(int fileDescriptor) {
211        close(fileDescriptor);
212    }*/
213    
214    // path is the BSD path to a raw device such as /dev/rdisk1
215    static struct _CDTOC * ReadTOC(const char *devpath) {
216        struct _CDTOC * toc_p = NULL;
217        io_iterator_t iterator = 0;
218        io_registry_entry_t service = 0;
219        CFDictionaryRef properties = 0;
220        CFDataRef data = 0;
221        mach_port_t port = 0;
222        const char *devname;
223    
224        if ((devname = strrchr(devpath, '/')) != NULL) {
225            ++devname;
226        } else {
227            devname = (char *) devpath;
228        }
229    
230        if (IOMasterPort(bootstrap_port, &port) != KERN_SUCCESS) {
231            fprintf(stderr, "IOMasterPort failed\n");
232            goto Exit;
233        }
234    
235        if (IOServiceGetMatchingServices(port, IOBSDNameMatching(port, 0, devname),
236                                         &iterator) != KERN_SUCCESS) {
237            fprintf(stderr, "IOServiceGetMatchingServices failed\n");
238            goto Exit;
239        }
240    
241        service = IOIteratorNext(iterator);
242    
243        IOObjectRelease(iterator);
244    
245        iterator = 0;
246    
247        while (service && !IOObjectConformsTo(service, "IOCDMedia")) {
248            if (IORegistryEntryGetParentIterator(service, kIOServicePlane,
249                                                 &iterator) != KERN_SUCCESS)
250            {
251                fprintf(stderr, "IORegistryEntryGetParentIterator failed\n");
252                goto Exit;
253            }
254    
255            IOObjectRelease(service);
256            service = IOIteratorNext(iterator);
257            IOObjectRelease(iterator);
258        }
259    
260        if (!service) {
261            fprintf(stderr, "CD media not found\n");
262            goto Exit;
263        }
264    
265        if (IORegistryEntryCreateCFProperties(service, (__CFDictionary **) &properties,
266                                              kCFAllocatorDefault,
267                                              kNilOptions) != KERN_SUCCESS)
268        {
269            fprintf(stderr, "IORegistryEntryGetParentIterator failed\n");
270            goto Exit;
271        }
272    
273        data = (CFDataRef) CFDictionaryGetValue(properties, CFSTR(kIOCDMediaTOCKey));
274        if (data == NULL) {
275            fprintf(stderr, "CFDictionaryGetValue failed\n");
276            goto Exit;
277        } else {
278            CFRange range;
279            CFIndex buflen;
280    
281            buflen = CFDataGetLength(data) + 1;
282            range = CFRangeMake(0, buflen);
283            toc_p = (struct _CDTOC *) malloc(buflen);
284            if (toc_p == NULL) {
285                fprintf(stderr, "Out of memory\n");
286                goto Exit;
287            } else {
288                CFDataGetBytes(data, range, (unsigned char *) toc_p);
289            }
290    
291           /*
292            fprintf(stderr, "Table of contents\n length %d first %d last %d\n",
293                    toc_p->length, toc_p->first_session, toc_p->last_session);
294            */
295    
296            CFRelease(properties);
297        }
298    
299        Exit:
300    
301        if (service) {
302            IOObjectRelease(service);
303        }
304    
305        return toc_p;
306    }
307    
308    #endif // defined(_CARBON_) || defined(__APPLE__)
309    
310  //////////////////////////////////  //////////////////////////////////
311  // AkaiSample:  // AkaiSample:
312  AkaiSample::AkaiSample(DiskImage* pDisk, AkaiVolume* pParent, const AkaiDirEntry& DirEntry)  AkaiSample::AkaiSample(DiskImage* pDisk, AkaiVolume* pParent, const AkaiDirEntry& DirEntry)
# Line 251  bool AkaiProgram::Load() Line 516  bool AkaiProgram::Load()
516      return false;      return false;
517    }    }
518    //     2-3     first keygroup address      150,0          //     2-3     first keygroup address      150,0      
519    uint16_t KeygroupAddress = mpDisk->ReadInt16();    /*uint16_t KeygroupAddress =*/ mpDisk->ReadInt16();
520    //     4-15    program name                10,10,10... AKAII character set    //     4-15    program name                10,10,10... AKAII character set
521    char buffer[13];    char buffer[13];
522    mpDisk->Read(buffer, 12, 1);    mpDisk->Read(buffer, 12, 1);
# Line 397  bool AkaiKeygroup::Load(DiskImage* pDisk Line 662  bool AkaiKeygroup::Load(DiskImage* pDisk
662    if (pDisk->ReadInt8() != AKAI_KEYGROUP_ID)    if (pDisk->ReadInt8() != AKAI_KEYGROUP_ID)
663      return false;      return false;
664    //     2-3     next keygroup address       44,1        300,450,600,750.. (16-bit)    //     2-3     next keygroup address       44,1        300,450,600,750.. (16-bit)
665    uint16_t NextKeygroupAddress = pDisk->ReadInt16();    /*uint16_t NextKeygroupAddress =*/ pDisk->ReadInt16();
666    //     4       low key                     24          24..127    //     4       low key                     24          24..127
667    mLowKey = pDisk->ReadInt8();    mLowKey = pDisk->ReadInt8();
668    //     5       high key                    127         24..127    //     5       high key                    127         24..127
# Line 527  bool AkaiKeygroupSample::Load(DiskImage* Line 792  bool AkaiKeygroupSample::Load(DiskImage*
792    //     47      low vel                     0           0..127    //     47      low vel                     0           0..127
793    mLowLevel = pDisk->ReadInt8();    mLowLevel = pDisk->ReadInt8();
794    //     48      high vel                    127         0..127    //     48      high vel                    127         0..127
795    uint8_t mHighLevel = pDisk->ReadInt8();    /*uint8_t mHighLevel =*/ pDisk->ReadInt8();
796    //     49      tune cents                  0           -128..127 (-50..50 cents)    //     49      tune cents                  0           -128..127 (-50..50 cents)
797    int8_t mTuneCents = pDisk->ReadInt8();    /*int8_t mTuneCents =*/ pDisk->ReadInt8();
798    //     50      tune semitones              0           -50..50    //     50      tune semitones              0           -50..50
799    int8_t mTuneSemitones = pDisk->ReadInt8();    /*int8_t mTuneSemitones =*/ pDisk->ReadInt8();
800    //     51      loudness                    0           -50..+50    //     51      loudness                    0           -50..+50
801    int8_t mLoudness = pDisk->ReadInt8();    /*int8_t mLoudness =*/ pDisk->ReadInt8();
802    //     52      filter                      0           -50..+50    //     52      filter                      0           -50..+50
803    int8_t mFilter = pDisk->ReadInt8();    /*int8_t mFilter =*/ pDisk->ReadInt8();
804    //     53      pan                         0           -50..+50    //     53      pan                         0           -50..+50
805    int8_t mPan = pDisk->ReadInt8();    /*int8_t mPan =*/ pDisk->ReadInt8();
806    //     54      loop mode                   0           0=AS_SAMPLE 1=LOOP_IN_REL    //     54      loop mode                   0           0=AS_SAMPLE 1=LOOP_IN_REL
807    //                                                     2=LOOP_UNTIL_REL 3=NO_LOOP    //                                                     2=LOOP_UNTIL_REL 3=NO_LOOP
808    //                                                     4=PLAY_TO_END    //                                                     4=PLAY_TO_END
809    uint8_t mLoopMode = pDisk->ReadInt8();    /*uint8_t mLoopMode =*/ pDisk->ReadInt8();
810    //     55      (internal use)              255    //     55      (internal use)              255
811    pDisk->ReadInt8();    pDisk->ReadInt8();
812    //     56      (internal use)              255    //     56      (internal use)              255
# Line 565  AkaiVolume::AkaiVolume(DiskImage* pDisk, Line 830  AkaiVolume::AkaiVolume(DiskImage* pDisk,
830    if (mDirEntry.mType != AKAI_TYPE_DIR_S1000 && mDirEntry.mType != AKAI_TYPE_DIR_S3000)    if (mDirEntry.mType != AKAI_TYPE_DIR_S1000 && mDirEntry.mType != AKAI_TYPE_DIR_S3000)
831    {    {
832      printf("Creating Unknown Volume type! %d\n",mDirEntry.mType);      printf("Creating Unknown Volume type! %d\n",mDirEntry.mType);
833  #ifdef _WIN32_  #ifdef WIN32
834      OutputDebugString("Creating Unknown Volume type!\n");      OutputDebugString("Creating Unknown Volume type!\n");
835  #endif  #endif
836    }    }
# Line 1241  DiskImage::DiskImage(int disk) Line 1506  DiskImage::DiskImage(int disk)
1506      mSize = dg.BytesPerSector * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.Cylinders.LowPart;      mSize = dg.BytesPerSector * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.Cylinders.LowPart;
1507      mClusterSize = dg.BytesPerSector;      mClusterSize = dg.BytesPerSector;
1508    }    }
1509  #elif defined _CARBON_  #elif defined(_CARBON_) || defined(__APPLE__)
1510    kern_return_t  kernResult;    kern_return_t  kernResult;
1511    io_iterator_t mediaIterator;    io_iterator_t mediaIterator;
1512    char  bsdPath[ MAXPATHLEN ];    char  bsdPath[ MAXPATHLEN ];
# Line 1262  DiskImage::DiskImage(int disk) Line 1527  DiskImage::DiskImage(int disk)
1527          // get the address of the immediately previous (or following depending          // get the address of the immediately previous (or following depending
1528          // on how you look at it).  The difference in the sector numbers          // on how you look at it).  The difference in the sector numbers
1529          // is returned as the sized of the data track.          // is returned as the sized of the data track.
1530          for (int i=toc_entries - 1; i>=0; i-- )          for (ssize_t i=toc_entries - 1; i>=0; i-- )
1531          {          {
1532            if ( start_sector != -1 )            if ( start_sector != -1 )
1533            {            {
# Line 1296  DiskImage::DiskImage(int disk) Line 1561  DiskImage::DiskImage(int disk)
1561      {      {
1562        printf("opened file: %s\n",bsdPath);        printf("opened file: %s\n",bsdPath);
1563    
1564              mSize = lseek(mFile,1000000000,SEEK_SET);              mSize = (int) lseek(mFile,1000000000,SEEK_SET);
1565              printf("size %d\n",mSize);              printf("size %d\n",mSize);
1566              lseek(mFile,0,SEEK_SET);              lseek(mFile,0,SEEK_SET);
1567    
# Line 1320  void DiskImage::Init() Line 1585  void DiskImage::Init()
1585    mCluster     = (uint)-1;    mCluster     = (uint)-1;
1586    mStartFrame  = -1;    mStartFrame  = -1;
1587    mEndFrame    = -1;    mEndFrame    = -1;
1588  #ifdef _WIN32_  #ifdef WIN32
1589    mpCache = (char*) VirtualAlloc(NULL,mClusterSize,MEM_COMMIT,PAGE_READWRITE);    mpCache = (char*) VirtualAlloc(NULL,mClusterSize,MEM_COMMIT,PAGE_READWRITE);
1590  #else  #else
1591    mpCache = NULL; // we allocate the cache later when we know what type of media we access    mpCache = NULL; // we allocate the cache later when we know what type of media we access
# Line 1329  void DiskImage::Init() Line 1594  void DiskImage::Init()
1594    
1595  DiskImage::~DiskImage()  DiskImage::~DiskImage()
1596  {  {
1597  #ifdef _WIN32_  #ifdef WIN32
1598    if (mFile != INVALID_HANDLE_VALUE)    if (mFile != INVALID_HANDLE_VALUE)
1599    {    {
1600      CloseHandle(mFile);      CloseHandle(mFile);
1601    }    }
1602  #elif defined _CARBON_ || LINUX  #elif defined _CARBON_ || defined(__APPLE__) || LINUX
1603    if (mFile)    if (mFile)
1604    {    {
1605      close(mFile);      close(mFile);
# Line 1342  DiskImage::~DiskImage() Line 1607  DiskImage::~DiskImage()
1607  #endif  #endif
1608    if (mpCache)    if (mpCache)
1609    {    {
1610  #ifdef _WIN32_  #ifdef WIN32
1611      VirtualFree(mpCache, 0, MEM_RELEASE);      VirtualFree(mpCache, 0, MEM_RELEASE);
1612  #elif defined _CARBON_ || LINUX  #elif defined(_CARBON_) || defined(__APPLE__) || LINUX
1613      free(mpCache);      free(mpCache);
1614  #endif  #endif
1615    }    }
# Line 1403  int DiskImage::Read(void* pData, uint Wo Line 1668  int DiskImage::Read(void* pData, uint Wo
1668                                            : mPos / mClusterSize + mStartFrame;                                            : mPos / mClusterSize + mStartFrame;
1669      if (mCluster != requestedCluster) { // read the requested cluster into cache      if (mCluster != requestedCluster) { // read the requested cluster into cache
1670        mCluster = requestedCluster;        mCluster = requestedCluster;
1671  #ifdef _WIN32_  #ifdef WIN32
1672        if (mCluster * mClusterSize != SetFilePointer(mFile, mCluster * mClusterSize, NULL, FILE_BEGIN)) {        if (mCluster * mClusterSize != SetFilePointer(mFile, mCluster * mClusterSize, NULL, FILE_BEGIN)) {
1673          printf("ERROR: couldn't seek device!\n");          printf("ERROR: couldn't seek device!\n");
1674    #if 0 // FIXME: endian correction is missing correct detection
1675          if ((readbytes > 0) && (mEndian != eEndianNative)) {          if ((readbytes > 0) && (mEndian != eEndianNative)) {
1676            switch (WordSize) {            switch (WordSize) {
1677              case 2: bswap_16_s ((uint16*)pData, readbytes); break;              case 2: bswap_16_s ((uint16*)pData, readbytes); break;
# Line 1413  int DiskImage::Read(void* pData, uint Wo Line 1679  int DiskImage::Read(void* pData, uint Wo
1679              case 8: bswap_64_s ((uint64*)pData, readbytes); break;              case 8: bswap_64_s ((uint64*)pData, readbytes); break;
1680            }            }
1681          }          }
1682    #endif
1683          return readbytes / WordSize;          return readbytes / WordSize;
1684        }        }
1685        DWORD size;        DWORD size;
1686        ReadFile(mFile, mpCache, mClusterSize, &size, NULL);        ReadFile(mFile, mpCache, mClusterSize, &size, NULL);
1687  #elif defined _CARBON_ || LINUX  #elif defined(_CARBON_) || defined(__APPLE__) || LINUX
1688        if (mCluster * mClusterSize != lseek(mFile, mCluster * mClusterSize, SEEK_SET))        if (mCluster * mClusterSize != lseek(mFile, mCluster * mClusterSize, SEEK_SET))
1689          return readbytes / WordSize;          return readbytes / WordSize;
1690  //          printf("trying to read %d bytes from device!\n",mClusterSize);  //          printf("trying to read %d bytes from device!\n",mClusterSize);
1691        int size = read(mFile, mpCache, mClusterSize);        /*int size =*/ read(mFile, mpCache, mClusterSize);
1692  //          printf("read %d bytes from device!\n",size);  //          printf("read %d bytes from device!\n",size);
1693  #endif  #endif
1694      }      }
# Line 1440  int DiskImage::Read(void* pData, uint Wo Line 1707  int DiskImage::Read(void* pData, uint Wo
1707  //      printf("new pos %d\n",mPos);  //      printf("new pos %d\n",mPos);
1708    }    }
1709    
1710  #if 0  #if 0 // FIXME: endian correction is missing correct detection
1711    if ((readbytes > 0) && (mEndian != eEndianNative))    if ((readbytes > 0) && (mEndian != eEndianNative))
1712      switch (WordSize)      switch (WordSize)
1713      {      {
# Line 1519  uint32_t DiskImage::ReadInt32() Line 1786  uint32_t DiskImage::ReadInt32()
1786  }  }
1787    
1788  void DiskImage::OpenStream(const char* path) {  void DiskImage::OpenStream(const char* path) {
1789  #ifdef _WIN32_  #ifdef WIN32
1790    mFile = CreateFile(path, GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS,NULL);    mFile = CreateFile(path, GENERIC_READ,0,NULL,OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS,NULL);
1791    BY_HANDLE_FILE_INFORMATION FileInfo;    BY_HANDLE_FILE_INFORMATION FileInfo;
1792    GetFileInformationByHandle(mFile,&FileInfo);    GetFileInformationByHandle(mFile,&FileInfo);
1793    mSize = FileInfo.nFileSizeLow;    mSize = FileInfo.nFileSizeLow;
1794  #elif _CARBON_ || LINUX  #elif defined(_CARBON_) || defined(__APPLE__) || LINUX
1795    struct stat filestat;    struct stat filestat;
1796    stat(path,&filestat);    stat(path,&filestat);
1797    mFile = open(path, O_RDONLY | O_NONBLOCK);    mFile = open(path, O_RDONLY | O_NONBLOCK);
# Line 1537  void DiskImage::OpenStream(const char* p Line 1804  void DiskImage::OpenStream(const char* p
1804    if (S_ISREG(filestat.st_mode)) { // regular file    if (S_ISREG(filestat.st_mode)) { // regular file
1805      printf("Using regular Akai image file.\n");      printf("Using regular Akai image file.\n");
1806      mRegularFile = true;      mRegularFile = true;
1807      mSize        = filestat.st_size;      mSize        = (int) filestat.st_size;
1808      mClusterSize = DISK_CLUSTER_SIZE;      mClusterSize = DISK_CLUSTER_SIZE;
1809      mpCache = (char*) malloc(mClusterSize);      mpCache = (char*) malloc(mClusterSize);
1810    }    } else { // CDROM
1811    else { // CDROM  #if defined(_CARBON_) || defined(__APPLE__)
1812        printf("Can't open %s: not a regular file\n", path);
1813    #else // Linux ...
1814      mRegularFile = false;      mRegularFile = false;
1815      mClusterSize = CD_FRAMESIZE;      mClusterSize = CD_FRAMESIZE;
1816      mpCache = (char*) malloc(mClusterSize);      mpCache = (char*) malloc(mClusterSize);
# Line 1601  void DiskImage::OpenStream(const char* p Line 1870  void DiskImage::OpenStream(const char* p
1870      mStartFrame = start;      mStartFrame = start;
1871      mEndFrame   = end;      mEndFrame   = end;
1872      mSize       = length * CD_FRAMESIZE;      mSize       = length * CD_FRAMESIZE;
1873    #endif
1874    } // CDROM    } // CDROM
1875  #endif  #endif
1876  }  }
1877    
1878  bool DiskImage::WriteImage(const char* path)  bool DiskImage::WriteImage(const char* path)
1879  {  {
1880  #if _CARBON_ || LINUX  #if defined(_CARBON_) || defined(__APPLE__) || LINUX
1881    const uint bufferSize = 524288; // 512 kB    const uint bufferSize = 524288; // 512 kB
1882    int fOut = open(path, O_WRONLY | O_NONBLOCK | O_CREAT | O_TRUNC);    int fOut = open(path, O_WRONLY | O_NONBLOCK | O_CREAT | O_TRUNC,
1883                      S_IRUSR | S_IWUSR | S_IRGRP);
1884    if (mFile <= 0) {    if (mFile <= 0) {
1885      printf("Can't open output file %s\n", path);      printf("Can't open output file %s\n", path);
1886      return false;      return false;
# Line 1624  bool DiskImage::WriteImage(const char* p Line 1895  bool DiskImage::WriteImage(const char* p
1895    close(fOut);    close(fOut);
1896    return true;    return true;
1897  #endif // _CARBON_ || LINUX  #endif // _CARBON_ || LINUX
1898      return false;
1899  }  }
1900    
1901  inline void DiskImage::swapBytes_16(void* Word) {  inline void DiskImage::swapBytes_16(void* Word) {

Legend:
Removed from v.2572  
changed lines
  Added in v.3476

  ViewVC Help
Powered by ViewVC