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 |
#if defined (__GNUC__) && (__GNUC__ >= 4) |
#endif |
31 |
#include <sys/disk.h> |
#if defined(_CARBON_) || defined(__APPLE__) |
32 |
#else |
# if defined (__GNUC__) && (__GNUC__ >= 4) |
33 |
#include <dev/disk.h> |
# include <sys/disk.h> |
34 |
|
# else |
35 |
|
# include <dev/disk.h> |
36 |
|
# endif |
37 |
#endif |
#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> |
|
#include <paths.h> |
|
41 |
#if defined(_CARBON_) || defined(__APPLE__) |
#if defined(_CARBON_) || defined(__APPLE__) |
42 |
|
#include <paths.h> |
43 |
|
#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> |
155 |
|
|
156 |
// Given the path to a CD drive, open the drive. |
// Given the path to a CD drive, open the drive. |
157 |
// Return the file descriptor associated with the device. |
// Return the file descriptor associated with the device. |
158 |
static int OpenDrive(const char *bsdPath) { |
/*static int OpenDrive(const char *bsdPath) { |
159 |
int fileDescriptor; |
int fileDescriptor; |
160 |
|
|
161 |
// This open() call will fail with a permissions error if the sample has been changed to |
// This open() call will fail with a permissions error if the sample has been changed to |
170 |
} |
} |
171 |
|
|
172 |
return fileDescriptor; |
return fileDescriptor; |
173 |
} |
}*/ |
174 |
|
|
175 |
// Given the file descriptor for a whole-media CD device, read a sector from the drive. |
// Given the file descriptor for a whole-media CD device, read a sector from the drive. |
176 |
// Return true if successful, otherwise false. |
// Return true if successful, otherwise false. |
177 |
static Boolean ReadSector(int fileDescriptor) { |
/*static Boolean ReadSector(int fileDescriptor) { |
178 |
char *buffer; |
char *buffer; |
179 |
ssize_t numBytes; |
ssize_t numBytes; |
180 |
u_int32_t blockSize; |
u_int32_t blockSize; |
204 |
free(buffer); |
free(buffer); |
205 |
|
|
206 |
return numBytes == blockSize ? true : false; |
return numBytes == blockSize ? true : false; |
207 |
} |
}*/ |
208 |
|
|
209 |
// Given the file descriptor for a device, close that device. |
// Given the file descriptor for a device, close that device. |
210 |
static void CloseDrive(int fileDescriptor) { |
/*static void CloseDrive(int fileDescriptor) { |
211 |
close(fileDescriptor); |
close(fileDescriptor); |
212 |
} |
}*/ |
213 |
|
|
214 |
// path is the BSD path to a raw device such as /dev/rdisk1 |
// path is the BSD path to a raw device such as /dev/rdisk1 |
215 |
static struct _CDTOC * ReadTOC(const char *devpath) { |
static struct _CDTOC * ReadTOC(const char *devpath) { |
219 |
CFDictionaryRef properties = 0; |
CFDictionaryRef properties = 0; |
220 |
CFDataRef data = 0; |
CFDataRef data = 0; |
221 |
mach_port_t port = 0; |
mach_port_t port = 0; |
222 |
char *devname; |
const char *devname; |
223 |
|
|
224 |
if ((devname = strrchr(devpath, '/')) != NULL) { |
if ((devname = strrchr(devpath, '/')) != NULL) { |
225 |
++devname; |
++devname; |
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 |
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 |
|
|
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; |
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 |
{ |
{ |
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 |
} else { // CDROM |
1879 |
{ |
{ |
1880 |
#if defined(_CARBON_) || defined(__APPLE__) || 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) { |