1
0
mirror of https://github.com/ErnyTech/Open-USB-Extreme synced 2024-06-02 03:16:33 +02:00
Open-USB-Extreme/lib/usbextreme.d

213 lines
5.3 KiB
D
Raw Normal View History

2019-08-21 15:46:46 +02:00
module usbextreme;
2019-08-19 14:21:16 +02:00
import std.stdint;
enum USBEXTREME_NAME_LENGTH = 32;
enum USBEXTREME_ID_LENGTH = 15;
enum USBEXTREME_NAME_EXT_LENGTH = 10;
enum USBEXTREME_MAGIC = 0x08;
2019-08-28 15:45:06 +02:00
enum USBEXTREME_HEADER_SIZE = UsbExtremeBase.sizeof;
2019-08-19 14:21:16 +02:00
2019-08-28 15:45:06 +02:00
align(1) struct UsbExtremeBase {
2019-08-20 16:27:11 +02:00
align(1):
2019-08-19 14:21:16 +02:00
uint8_t[6 + USBEXTREME_ID_LENGTH + USBEXTREME_NAME_LENGTH] empty;
uint8_t magic;
uint8_t[10] empty2;
}
2019-08-28 15:45:06 +02:00
align(1) struct UsbExtremeV0 {
2019-08-20 16:27:11 +02:00
align(1):
2019-08-20 16:19:22 +02:00
char[USBEXTREME_NAME_LENGTH] name;
char[USBEXTREME_ID_LENGTH] id;
uint8_t n_parts;
SCECdvdMediaType type;
2019-08-20 16:19:22 +02:00
uint8_t[4] empty;
uint8_t magic;
uint8_t[USBEXTREME_NAME_EXT_LENGTH] empty2;
}
2019-08-28 15:45:06 +02:00
align(1) struct UsbExtremeV1 {
2019-08-20 16:27:11 +02:00
align(1):
2019-08-20 16:19:22 +02:00
char[USBEXTREME_NAME_LENGTH] name;
char[USBEXTREME_ID_LENGTH] id;
uint8_t n_parts;
SCECdvdMediaType type;
2019-08-20 16:19:22 +02:00
uint16_t size;
2019-08-28 15:45:06 +02:00
uint8_t videoMode;
UsbExtremeVersion usbExtremeVersion;
2019-08-20 16:19:22 +02:00
uint8_t magic;
2019-08-28 15:45:06 +02:00
char[USBEXTREME_NAME_EXT_LENGTH] nameExt;
2019-08-20 16:19:22 +02:00
}
2019-08-28 15:45:06 +02:00
struct UsbExtremeHeaders {
const(void)* firstHeader;
const(UsbExtremeBase)[] headers;
size_t numHeaders;
2019-08-28 15:45:06 +02:00
size_t headersLen;
2019-08-21 15:26:05 +02:00
UsbExtremeVersion oueVersion;
}
2019-08-28 15:45:06 +02:00
struct UsbExtremeFilestat {
size_t offset;
2019-08-21 15:46:46 +02:00
char[USBEXTREME_NAME_LENGTH + USBEXTREME_NAME_EXT_LENGTH] name;
SCECdvdMediaType type;
uint16_t size;
2019-08-28 15:45:06 +02:00
uint8_t videoMode;
UsbExtremeVersion usbExtremeVersion;
2019-08-21 15:46:46 +02:00
}
enum UsbExtremeVersion : uint8_t {
2019-08-20 15:53:03 +02:00
V0 = 0x00,
V1,
Unknown
2019-08-20 15:53:03 +02:00
}
enum SCECdvdMediaType : uint8_t {
2019-08-21 15:46:46 +02:00
SCECdNODISC = 0x00,
SCECdDETCT,
SCECdDETCTCD,
SCECdDETCTDVDS,
SCECdDETCTDVDD,
SCECdUNKNOWN,
SCECdPSCD = 0x10,
SCECdPSCDDA,
SCECdPS2CD,
SCECdPS2CDDA,
SCECdPS2DVD,
SCECdCDDA = 0xFD,
SCECdDVDV,
SCECdIllegalMediaoffset
}
extern(D) bool isOue(const(void)[] headers) {
2019-08-28 15:45:06 +02:00
auto headersOeu = castArray!(const UsbExtremeBase)(headers);
2019-08-19 14:21:16 +02:00
2019-08-28 15:45:06 +02:00
foreach (header; headersOeu) {
2019-08-19 14:21:16 +02:00
if (header.magic != USBEXTREME_MAGIC) {
return false;
2019-08-19 14:21:16 +02:00
}
}
return true;
2019-08-19 14:21:16 +02:00
}
2019-08-20 15:53:03 +02:00
extern(D) UsbExtremeVersion getVersion(UsbExtremeVersion usbExtremeVersion) {
2019-08-20 15:53:03 +02:00
switch (usbExtremeVersion) {
case UsbExtremeVersion.V0: {
2019-08-20 15:53:03 +02:00
return UsbExtremeVersion.V0;
}
case UsbExtremeVersion.V1: {
2019-08-20 15:53:03 +02:00
return UsbExtremeVersion.V1;
}
default: {
return UsbExtremeVersion.V0;
2019-08-20 15:53:03 +02:00
}
}
}
2019-08-20 15:58:04 +02:00
extern(D) size_t oueNumHeaders(const(void)[] headers) {
auto headersLen = castArray!(UsbExtremeBase)(headers).length;
2019-08-20 15:58:04 +02:00
if (!isOue(headers)) {
2019-08-20 15:58:04 +02:00
return -1;
}
2019-08-28 15:45:06 +02:00
return headersLen;
2019-08-20 15:58:04 +02:00
}
2019-08-20 16:10:46 +02:00
extern(D) size_t ouePointHeaders(ref const(UsbExtremeBase)[] headers, const(void)[] rawHeaders) {
2019-08-28 15:45:06 +02:00
auto headersLen = oueNumHeaders(rawHeaders);
2019-08-20 16:10:46 +02:00
2019-08-28 15:45:06 +02:00
if (headersLen <= 0) {
2019-08-20 16:10:46 +02:00
return -1;
}
2019-08-28 15:45:06 +02:00
headers = castArray!(const(UsbExtremeBase))(rawHeaders)[];
return headersLen;
2019-08-20 16:10:46 +02:00
}
2019-08-20 16:19:22 +02:00
extern(D) UsbExtremeVersion oueHeadersVersion(const(void)[] headers) {
2019-08-28 15:45:06 +02:00
auto headersOeu = castArray!(UsbExtremeV1)(headers);
auto firstVersion = UsbExtremeVersion.V0;
2019-08-20 16:19:22 +02:00
if (!isOue(headers)) {
return UsbExtremeVersion.Unknown;
2019-08-20 16:19:22 +02:00
}
2019-08-28 15:45:06 +02:00
foreach (i, header; headersOeu) {
2019-08-20 16:19:22 +02:00
if (i == 0) {
2019-08-28 15:45:06 +02:00
firstVersion = getVersion(header.usbExtremeVersion);
2019-08-20 16:19:22 +02:00
} else {
2019-08-28 15:45:06 +02:00
if (firstVersion != getVersion(header.usbExtremeVersion)) {
return UsbExtremeVersion.V0;
2019-08-20 16:19:22 +02:00
}
}
}
2019-08-28 15:45:06 +02:00
return firstVersion;
2019-08-20 16:19:22 +02:00
}
2019-08-21 15:26:05 +02:00
2019-08-28 15:45:06 +02:00
extern(D) int oueReadHeaders(ref UsbExtremeHeaders headers, const(void)[] rawHeaders) {
auto oueVersion = oueHeadersVersion(rawHeaders);
auto numHeaders = oueNumHeaders(rawHeaders);
2019-08-28 15:45:06 +02:00
if (!isOue(rawHeaders)) {
return -1;
2019-08-21 15:26:05 +02:00
}
if (oueVersion == UsbExtremeVersion.Unknown) {
2019-08-21 15:26:05 +02:00
return -1;
}
2019-08-28 15:45:06 +02:00
auto headersArr = castArray!(UsbExtremeBase)(rawHeaders);
headers = UsbExtremeHeaders(rawHeaders.ptr,
headersArr,
2019-08-28 15:45:06 +02:00
numHeaders,
rawHeaders.length,
oueVersion);
2019-08-21 15:26:05 +02:00
return 1;
}
2019-08-21 15:46:46 +02:00
2019-08-28 15:45:06 +02:00
extern(D) UsbExtremeFilestat[] oueRead(UsbExtremeFilestat[] filestats, const(UsbExtremeHeaders) headers) {
auto headersFull = castArray!(UsbExtremeV1)(headers.headers);
auto headersLength = headersFull.length;
int fileStatsLength = 0;
2019-08-21 15:46:46 +02:00
foreach (i, ref filestat; filestats) {
if (headersLength == 0) {
return filestats[0..i];
2019-08-21 15:46:46 +02:00
}
2019-08-28 15:45:06 +02:00
auto header = headersFull[i];
filestat.name[0..USBEXTREME_NAME_LENGTH] = header.name[0..$];
2019-08-28 15:45:06 +02:00
auto headerVersion = getVersion(header.usbExtremeVersion);
uint16_t size = 0;
uint8_t videoMode = 0;
if (headerVersion >= 1) {
2019-08-21 15:46:46 +02:00
size = header.size;
2019-08-28 15:45:06 +02:00
videoMode = header.videoMode;
filestat.name[USBEXTREME_NAME_LENGTH..USBEXTREME_NAME_LENGTH + USBEXTREME_NAME_EXT_LENGTH] = header.nameExt[0..$];
2019-08-21 15:46:46 +02:00
}
filestat.size = size;
filestat.type = header.type;
filestat.offset = i;
2019-08-28 15:45:06 +02:00
filestat.videoMode = videoMode;
filestat.usbExtremeVersion = headerVersion;
headersLength -= 1;
fileStatsLength += 1;
2019-08-21 15:46:46 +02:00
}
return filestats[0..fileStatsLength];
2019-08-21 15:46:46 +02:00
}
private R[] castArray(R, T) (T[] array) { // Workaround for https://issues.dlang.org/show_bug.cgi?id=20088
auto ptr = array.ptr;
auto castPtr = cast(R*) ptr;
return castPtr[0..((array.length * T.sizeof) / R.sizeof)];
}