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 |
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> |
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) |
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); |
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 |
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 |
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 |
} |
} |
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 ]; |
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 |
{ |
{ |
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 |
|
|
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 |
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); |
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 |
} |
} |
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; |
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 |
} |
} |
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 |
{ |
{ |
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); |
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); |
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; |
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) { |