Virtual ISO: Initial commit

This commit is contained in:
RichardG867
2022-03-26 22:17:09 -03:00
parent 7d15a75cf4
commit eeeb7b258d
6 changed files with 1279 additions and 195 deletions

View File

@@ -13,4 +13,4 @@
# Copyright 2020,2021 David Hrdlička. # Copyright 2020,2021 David Hrdlička.
# #
add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image.c) add_library(cdrom OBJECT cdrom.c cdrom_image_backend.c cdrom_image_viso.c cdrom_image.c)

View File

@@ -285,11 +285,12 @@ cdrom_image_open(cdrom_t *dev, const char *fn)
dev->image = img; dev->image = img;
/* Open the image. */ /* Open the image. */
if (!cdi_set_device(img, fn)) int i = cdi_set_device(img, fn);
if (!i)
return image_open_abort(dev); return image_open_abort(dev);
/* All good, reset state. */ /* All good, reset state. */
if (! strcasecmp(plat_get_extension((char *) fn), "ISO")) if (i == 2)
dev->cd_status = CD_STATUS_DATA_ONLY; dev->cd_status = CD_STATUS_DATA_ONLY;
else else
dev->cd_status = CD_STATUS_STOPPED; dev->cd_status = CD_STATUS_STOPPED;

View File

@@ -1,58 +1,53 @@
/* /*
* 86Box A hypervisor and IBM PC system emulator that specializes in * 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM * running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent * PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus. * system designs based on the PCI bus.
* *
* This file is part of the 86Box distribution. * This file is part of the 86Box distribution.
* *
* CD-ROM image file handling module, translated to C from * CD-ROM image file handling module, translated to C from
* cdrom_dosbox.cpp. * cdrom_dosbox.cpp.
* *
* Authors: Miran Grca, <mgrca8@gmail.com> * Authors: Miran Grca, <mgrca8@gmail.com>
* Fred N. van Kempen, <decwiz@yahoo.com> * Fred N. van Kempen, <decwiz@yahoo.com>
* The DOSBox Team, <unknown> * The DOSBox Team, <unknown>
* *
* Copyright 2016-2020 Miran Grca. * Copyright 2016-2020 Miran Grca.
* Copyright 2017-2020 Fred N. van Kempen. * Copyright 2017-2020 Fred N. van Kempen.
* Copyright 2002-2020 The DOSBox Team. * Copyright 2002-2020 The DOSBox Team.
*/ */
#define _LARGEFILE_SOURCE #define _LARGEFILE_SOURCE
#define _LARGEFILE64_SOURCE #define _LARGEFILE64_SOURCE
#define __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS
#include <stdarg.h>
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h> #include <ctype.h>
#include <inttypes.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32 #ifdef _WIN32
# include <string.h> # include <string.h>
#else #else
# include <libgen.h> # include <libgen.h>
#endif #endif
#include <wchar.h>
#define HAVE_STDARG_H #define HAVE_STDARG_H
#include <86box/86box.h> #include <86box/86box.h>
#include <86box/plat.h>
#include <86box/cdrom_image_backend.h> #include <86box/cdrom_image_backend.h>
#include <86box/plat.h>
#define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4))
#define CDROM_BCD(x) (((x) % 10) | (((x) / 10) << 4)) #define MAX_LINE_LENGTH 512
#define MAX_FILENAME_LENGTH 256
#define MAX_LINE_LENGTH 512 #define CROSS_LEN 512
#define MAX_FILENAME_LENGTH 256
#define CROSS_LEN 512
static char temp_keyword[1024];
static char temp_keyword[1024];
#ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG #ifdef ENABLE_CDROM_IMAGE_BACKEND_LOG
int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG; int cdrom_image_backend_do_log = ENABLE_CDROM_IMAGE_BACKEND_LOG;
void void
cdrom_image_backend_log(const char *fmt, ...) cdrom_image_backend_log(const char *fmt, ...)
{ {
@@ -65,10 +60,9 @@ cdrom_image_backend_log(const char *fmt, ...)
} }
} }
#else #else
#define cdrom_image_backend_log(fmt, ...) # define cdrom_image_backend_log(fmt, ...)
#endif #endif
/* Binary file functions. */ /* Binary file functions. */
static int static int
bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count) bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count)
@@ -98,11 +92,10 @@ bin_read(void *p, uint8_t *buffer, uint64_t seek, size_t count)
return 1; return 1;
} }
static uint64_t static uint64_t
bin_get_length(void *p) bin_get_length(void *p)
{ {
off64_t len; off64_t len;
track_file_t *tf = (track_file_t *) p; track_file_t *tf = (track_file_t *) p;
cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", tf->file); cdrom_image_backend_log("CDROM: binary_length(%08lx)\n", tf->file);
@@ -117,7 +110,6 @@ bin_get_length(void *p)
return len; return len;
} }
static void static void
bin_close(void *p) bin_close(void *p)
{ {
@@ -136,7 +128,6 @@ bin_close(void *p)
free(p); free(p);
} }
static track_file_t * static track_file_t *
bin_init(const char *filename, int *error) bin_init(const char *filename, int *error)
{ {
@@ -156,9 +147,9 @@ bin_init(const char *filename, int *error)
/* Set the function pointers. */ /* Set the function pointers. */
if (!*error) { if (!*error) {
tf->read = bin_read; tf->read = bin_read;
tf->get_length = bin_get_length; tf->get_length = bin_get_length;
tf->close = bin_close; tf->close = bin_close;
} else { } else {
free(tf); free(tf);
tf = NULL; tf = NULL;
@@ -167,7 +158,6 @@ bin_init(const char *filename, int *error)
return tf; return tf;
} }
static track_file_t * static track_file_t *
track_file_init(const char *filename, int *error) track_file_init(const char *filename, int *error)
{ {
@@ -176,7 +166,6 @@ track_file_init(const char *filename, int *error)
return bin_init(filename, error); return bin_init(filename, error);
} }
static void static void
track_file_close(track_t *trk) track_file_close(track_t *trk)
{ {
@@ -193,14 +182,13 @@ track_file_close(track_t *trk)
trk->file = NULL; trk->file = NULL;
} }
/* Root functions. */ /* Root functions. */
static void static void
cdi_clear_tracks(cd_img_t *cdi) cdi_clear_tracks(cd_img_t *cdi)
{ {
int i; int i;
track_file_t *last = NULL; track_file_t *last = NULL;
track_t *cur = NULL; track_t *cur = NULL;
if ((cdi->tracks == NULL) || (cdi->tracks_num == 0)) if ((cdi->tracks == NULL) || (cdi->tracks_num == 0))
return; return;
@@ -224,7 +212,6 @@ cdi_clear_tracks(cd_img_t *cdi)
cdi->tracks_num = 0; cdi->tracks_num = 0;
} }
void void
cdi_close(cd_img_t *cdi) cdi_close(cd_img_t *cdi)
{ {
@@ -232,7 +219,6 @@ cdi_close(cd_img_t *cdi)
free(cdi); free(cdi);
} }
int int
cdi_set_device(cd_img_t *cdi, const char *path) cdi_set_device(cd_img_t *cdi, const char *path)
{ {
@@ -240,36 +226,33 @@ cdi_set_device(cd_img_t *cdi, const char *path)
return 1; return 1;
if (cdi_load_iso(cdi, path)) if (cdi_load_iso(cdi, path))
return 1; return 2;
return 0; return 0;
} }
/* TODO: This never returns anything other than 1, should it even be an int? */ /* TODO: This never returns anything other than 1, should it even be an int? */
int int
cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out) cdi_get_audio_tracks(cd_img_t *cdi, int *st_track, int *end, TMSF *lead_out)
{ {
*st_track = 1; *st_track = 1;
*end = cdi->tracks_num - 1; *end = cdi->tracks_num - 1;
FRAMES_TO_MSF(cdi->tracks[*end].start + 150, &lead_out->min, &lead_out->sec, &lead_out->fr); FRAMES_TO_MSF(cdi->tracks[*end].start + 150, &lead_out->min, &lead_out->sec, &lead_out->fr);
return 1; return 1;
} }
/* TODO: This never returns anything other than 1, should it even be an int? */ /* TODO: This never returns anything other than 1, should it even be an int? */
int int
cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out) cdi_get_audio_tracks_lba(cd_img_t *cdi, int *st_track, int *end, uint32_t *lead_out)
{ {
*st_track = 1; *st_track = 1;
*end = cdi->tracks_num - 1; *end = cdi->tracks_num - 1;
*lead_out = cdi->tracks[*end].start; *lead_out = cdi->tracks[*end].start;
return 1; return 1;
} }
int int
cdi_get_audio_track_pre(cd_img_t *cdi, int track) cdi_get_audio_track_pre(cd_img_t *cdi, int track)
{ {
@@ -281,13 +264,12 @@ cdi_get_audio_track_pre(cd_img_t *cdi, int track)
return trk->pre; return trk->pre;
} }
/* This replaces both Info and EndInfo, they are specified by a variable. */ /* This replaces both Info and EndInfo, they are specified by a variable. */
int int
cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr) cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF *start, uint8_t *attr)
{ {
track_t *trk = &cdi->tracks[track - 1]; track_t *trk = &cdi->tracks[track - 1];
int pos = trk->start + 150; int pos = trk->start + 150;
if ((track < 1) || (track > cdi->tracks_num)) if ((track < 1) || (track > cdi->tracks_num))
return 0; return 0;
@@ -297,12 +279,11 @@ cdi_get_audio_track_info(cd_img_t *cdi, int end, int track, int *track_num, TMSF
FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr); FRAMES_TO_MSF(pos, &start->min, &start->sec, &start->fr);
*track_num = trk->track_number; *track_num = trk->track_number;
*attr = trk->attr; *attr = trk->attr;
return 1; return 1;
} }
int int
cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr) cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num, uint32_t *start, uint8_t *attr)
{ {
@@ -314,16 +295,15 @@ cdi_get_audio_track_info_lba(cd_img_t *cdi, int end, int track, int *track_num,
*start = (uint32_t) trk->start; *start = (uint32_t) trk->start;
*track_num = trk->track_number; *track_num = trk->track_number;
*attr = trk->attr; *attr = trk->attr;
return 1; return 1;
} }
int int
cdi_get_track(cd_img_t *cdi, uint32_t sector) cdi_get_track(cd_img_t *cdi, uint32_t sector)
{ {
int i; int i;
track_t *cur, *next; track_t *cur, *next;
/* There must be at least two tracks - data and lead out. */ /* There must be at least two tracks - data and lead out. */
@@ -333,7 +313,7 @@ cdi_get_track(cd_img_t *cdi, uint32_t sector)
/* This has a problem - the code skips the last track, which is /* This has a problem - the code skips the last track, which is
lead out - is that correct? */ lead out - is that correct? */
for (i = 0; i < (cdi->tracks_num - 1); i++) { for (i = 0; i < (cdi->tracks_num - 1); i++) {
cur = &cdi->tracks[i]; cur = &cdi->tracks[i];
next = &cdi->tracks[i + 1]; next = &cdi->tracks[i + 1];
if ((cur->start <= sector) && (sector < next->start)) if ((cur->start <= sector) && (sector < next->start))
return cur->number; return cur->number;
@@ -342,20 +322,19 @@ cdi_get_track(cd_img_t *cdi, uint32_t sector)
return -1; return -1;
} }
/* TODO: See if track start is adjusted by 150 or not. */ /* TODO: See if track start is adjusted by 150 or not. */
int int
cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos) cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track, uint8_t *index, TMSF *rel_pos, TMSF *abs_pos)
{ {
int cur_track = cdi_get_track(cdi, sector); int cur_track = cdi_get_track(cdi, sector);
track_t *trk; track_t *trk;
if (cur_track < 1) if (cur_track < 1)
return 0; return 0;
*track = (uint8_t) cur_track; *track = (uint8_t) cur_track;
trk = &cdi->tracks[*track - 1]; trk = &cdi->tracks[*track - 1];
*attr = trk->attr; *attr = trk->attr;
*index = 1; *index = 1;
FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr); FRAMES_TO_MSF(sector + 150, &abs_pos->min, &abs_pos->sec, &abs_pos->fr);
@@ -366,23 +345,22 @@ cdi_get_audio_sub(cd_img_t *cdi, uint32_t sector, uint8_t *attr, uint8_t *track,
return 1; return 1;
} }
int int
cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector) cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
{ {
size_t length; size_t length;
int track = cdi_get_track(cdi, sector) - 1; int track = cdi_get_track(cdi, sector) - 1;
uint64_t sect = (uint64_t) sector, seek; uint64_t sect = (uint64_t) sector, seek;
track_t *trk; track_t *trk;
int track_is_raw, ret; int track_is_raw, ret;
int raw_size, cooked_size; int raw_size, cooked_size;
uint64_t offset = 0ULL; uint64_t offset = 0ULL;
int m = 0, s = 0, f = 0; int m = 0, s = 0, f = 0;
if (track < 0) if (track < 0)
return 0; return 0;
trk = &cdi->tracks[track]; trk = &cdi->tracks[track];
track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448)); track_is_raw = ((trk->sector_size == RAW_SECTOR_SIZE) || (trk->sector_size == 2448));
seek = trk->skip + ((sect - trk->start) * trk->sector_size); seek = trk->skip + ((sect - trk->start) * trk->sector_size);
@@ -394,7 +372,7 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
if (trk->mode2 && (trk->form != 1)) { if (trk->mode2 && (trk->form != 1)) {
if (trk->form == 2) if (trk->form == 2)
cooked_size = (track_is_raw ? 2328 : trk->sector_size); /* Both 2324 + ECC and 2328 variants are valid. */ cooked_size = (track_is_raw ? 2328 : trk->sector_size); /* Both 2324 + ECC and 2328 variants are valid. */
else else
cooked_size = 2336; cooked_size = 2336;
} else } else
@@ -429,19 +407,18 @@ cdi_read_sector(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector)
return trk->file->read(trk->file, buffer, seek, length); return trk->file->read(trk->file, buffer, seek, length);
} }
int int
cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num) cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint32_t num)
{ {
int sector_size, success = 1; int sector_size, success = 1;
uint8_t *buf; uint8_t *buf;
uint32_t buf_len, i; uint32_t buf_len, i;
/* TODO: This fails to account for Mode 2. Shouldn't we have a function /* TODO: This fails to account for Mode 2. Shouldn't we have a function
to get sector size? */ to get sector size? */
sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE; sector_size = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
buf_len = num * sector_size; buf_len = num * sector_size;
buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t)); buf = (uint8_t *) malloc(buf_len * sizeof(uint8_t));
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i); success = cdi_read_sector(cdi, &buf[i * sector_size], raw, sector + i);
@@ -456,19 +433,18 @@ cdi_read_sectors(cd_img_t *cdi, uint8_t *buffer, int raw, uint32_t sector, uint3
return success; return success;
} }
/* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */ /* TODO: Do CUE+BIN images with a sector size of 2448 even exist? */
int int
cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector) cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector)
{ {
int track = cdi_get_track(cdi, sector) - 1; int track = cdi_get_track(cdi, sector) - 1;
track_t *trk; track_t *trk;
uint64_t s = (uint64_t) sector, seek; uint64_t s = (uint64_t) sector, seek;
if (track < 0) if (track < 0)
return 0; return 0;
trk = &cdi->tracks[track]; trk = &cdi->tracks[track];
seek = trk->skip + ((s - trk->start) * trk->sector_size); seek = trk->skip + ((s - trk->start) * trk->sector_size);
if (trk->sector_size != 2448) if (trk->sector_size != 2448)
return 0; return 0;
@@ -476,11 +452,10 @@ cdi_read_sector_sub(cd_img_t *cdi, uint8_t *buffer, uint32_t sector)
return trk->file->read(trk->file, buffer, seek, 2448); return trk->file->read(trk->file, buffer, seek, 2448);
} }
int int
cdi_get_sector_size(cd_img_t *cdi, uint32_t sector) cdi_get_sector_size(cd_img_t *cdi, uint32_t sector)
{ {
int track = cdi_get_track(cdi, sector) - 1; int track = cdi_get_track(cdi, sector) - 1;
track_t *trk; track_t *trk;
if (track < 0) if (track < 0)
@@ -490,11 +465,10 @@ cdi_get_sector_size(cd_img_t *cdi, uint32_t sector)
return trk->sector_size; return trk->sector_size;
} }
int int
cdi_is_mode2(cd_img_t *cdi, uint32_t sector) cdi_is_mode2(cd_img_t *cdi, uint32_t sector)
{ {
int track = cdi_get_track(cdi, sector) - 1; int track = cdi_get_track(cdi, sector) - 1;
track_t *trk; track_t *trk;
if (track < 0) if (track < 0)
@@ -505,11 +479,10 @@ cdi_is_mode2(cd_img_t *cdi, uint32_t sector)
return !!(trk->mode2); return !!(trk->mode2);
} }
int int
cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector) cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector)
{ {
int track = cdi_get_track(cdi, sector) - 1; int track = cdi_get_track(cdi, sector) - 1;
track_t *trk; track_t *trk;
if (track < 0) if (track < 0)
@@ -520,12 +493,11 @@ cdi_get_mode2_form(cd_img_t *cdi, uint32_t sector)
return trk->form; return trk->form;
} }
static int static int
cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form) cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form)
{ {
uint8_t pvd[COOKED_SECTOR_SIZE]; uint8_t pvd[COOKED_SECTOR_SIZE];
uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */ uint64_t seek = 16ULL * sector_size; /* First VD is located at sector 16. */
if ((!mode2 || (form == 0)) && (sector_size == RAW_SECTOR_SIZE)) if ((!mode2 || (form == 0)) && (sector_size == RAW_SECTOR_SIZE))
seek += 16; seek += 16;
@@ -534,11 +506,9 @@ cdi_can_read_pvd(track_file_t *file, uint64_t sector_size, int mode2, int form)
file->read(file, pvd, seek, COOKED_SECTOR_SIZE); file->read(file, pvd, seek, COOKED_SECTOR_SIZE);
return ((pvd[0] == 1 && !strncmp((char*)(&pvd[1]), "CD001", 5) && pvd[6] == 1) || return ((pvd[0] == 1 && !strncmp((char *) (&pvd[1]), "CD001", 5) && pvd[6] == 1) || (pvd[8] == 1 && !strncmp((char *) (&pvd[9]), "CDROM", 5) && pvd[14] == 1));
(pvd[8] == 1 && !strncmp((char*)(&pvd[9]), "CDROM", 5) && pvd[14] == 1));
} }
/* This reallocates the array and returns the pointer to the last track. */ /* This reallocates the array and returns the pointer to the last track. */
static void static void
cdi_track_push_back(cd_img_t *cdi, track_t *trk) cdi_track_push_back(cd_img_t *cdi, track_t *trk)
@@ -555,14 +525,13 @@ cdi_track_push_back(cd_img_t *cdi, track_t *trk)
cdi->tracks_num++; cdi->tracks_num++;
} }
int int
cdi_load_iso(cd_img_t *cdi, const char *filename) cdi_load_iso(cd_img_t *cdi, const char *filename)
{ {
int error; int error;
track_t trk; track_t trk;
cdi->tracks = NULL; cdi->tracks = NULL;
cdi->tracks_num = 0; cdi->tracks_num = 0;
memset(&trk, 0, sizeof(track_t)); memset(&trk, 0, sizeof(track_t));
@@ -572,28 +541,33 @@ cdi_load_iso(cd_img_t *cdi, const char *filename)
if (error) { if (error) {
if ((trk.file != NULL) && (trk.file->close != NULL)) if ((trk.file != NULL) && (trk.file->close != NULL))
trk.file->close(trk.file); trk.file->close(trk.file);
return 0; trk.file = viso_init(filename, &error);
if (error) {
if ((trk.file != NULL) && (trk.file->close != NULL))
trk.file->close(trk.file);
return 0;
}
} }
trk.number = 1; trk.number = 1;
trk.track_number = 1; trk.track_number = 1;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
/* Try to detect ISO type. */ /* Try to detect ISO type. */
trk.form = 0; trk.form = 0;
trk.mode2 = 0; trk.mode2 = 0;
/* TODO: Merge the first and last cases since they result in the same thing. */ /* TODO: Merge the first and last cases since they result in the same thing. */
if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0, 0)) if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 0, 0))
trk.sector_size = RAW_SECTOR_SIZE; trk.sector_size = RAW_SECTOR_SIZE;
else if (cdi_can_read_pvd(trk.file, 2336, 1, 0)) { else if (cdi_can_read_pvd(trk.file, 2336, 1, 0)) {
trk.sector_size = 2336; trk.sector_size = 2336;
trk.mode2 = 1; trk.mode2 = 1;
} else if (cdi_can_read_pvd(trk.file, 2324, 1, 2)) { } else if (cdi_can_read_pvd(trk.file, 2324, 1, 2)) {
trk.sector_size = 2324; trk.sector_size = 2324;
trk.mode2 = 1; trk.mode2 = 1;
trk.form = 2; trk.form = 2;
} else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 0)) { } else if (cdi_can_read_pvd(trk.file, RAW_SECTOR_SIZE, 1, 0)) {
trk.sector_size = RAW_SECTOR_SIZE; trk.sector_size = RAW_SECTOR_SIZE;
trk.mode2 = 1; trk.mode2 = 1;
} else { } else {
/* We use 2048 mode 1 as the default. */ /* We use 2048 mode 1 as the default. */
trk.sector_size = COOKED_SECTOR_SIZE; trk.sector_size = COOKED_SECTOR_SIZE;
@@ -604,30 +578,29 @@ cdi_load_iso(cd_img_t *cdi, const char *filename)
cdi_track_push_back(cdi, &trk); cdi_track_push_back(cdi, &trk);
/* Lead out track. */ /* Lead out track. */
trk.number = 2; trk.number = 2;
trk.track_number = 0xAA; trk.track_number = 0xAA;
trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */ trk.attr = 0x16; /* Was originally 0x00, but I believe 0x16 is appropriate. */
trk.start = trk.length; trk.start = trk.length;
trk.length = 0; trk.length = 0;
trk.file = NULL; trk.file = NULL;
cdi_track_push_back(cdi, &trk); cdi_track_push_back(cdi, &trk);
return 1; return 1;
} }
static int static int
cdi_cue_get_buffer(char *str, char **line, int up) cdi_cue_get_buffer(char *str, char **line, int up)
{ {
char *s = *line; char *s = *line;
char *p = str; char *p = str;
int quote = 0; int quote = 0;
int done = 0; int done = 0;
int space = 1; int space = 1;
/* Copy to local buffer until we have end of string or whitespace. */ /* Copy to local buffer until we have end of string or whitespace. */
while (! done) { while (!done) {
switch(*s) { switch (*s) {
case '\0': case '\0':
if (quote) { if (quote) {
/* Ouch, unterminated string.. */ /* Ouch, unterminated string.. */
@@ -640,11 +613,12 @@ cdi_cue_get_buffer(char *str, char **line, int up)
quote ^= 1; quote ^= 1;
break; break;
case ' ': case '\t': case ' ':
case '\t':
if (space) if (space)
break; break;
if (! quote) { if (!quote) {
done = 1; done = 1;
break; break;
} }
@@ -659,7 +633,7 @@ cdi_cue_get_buffer(char *str, char **line, int up)
break; break;
} }
if (! done) if (!done)
s++; s++;
} }
*p = '\0'; *p = '\0';
@@ -669,7 +643,6 @@ cdi_cue_get_buffer(char *str, char **line, int up)
return 1; return 1;
} }
static int static int
cdi_cue_get_keyword(char **dest, char **line) cdi_cue_get_keyword(char **dest, char **line)
{ {
@@ -682,12 +655,11 @@ cdi_cue_get_keyword(char **dest, char **line)
return success; return success;
} }
/* Get a string from the input line, handling quotes properly. */ /* Get a string from the input line, handling quotes properly. */
static uint64_t static uint64_t
cdi_cue_get_number(char **line) cdi_cue_get_number(char **line)
{ {
char temp[128]; char temp[128];
uint64_t num; uint64_t num;
if (!cdi_cue_get_buffer(temp, line, 0)) if (!cdi_cue_get_buffer(temp, line, 0))
@@ -699,13 +671,12 @@ cdi_cue_get_number(char **line)
return num; return num;
} }
static int static int
cdi_cue_get_frame(uint64_t *frames, char **line) cdi_cue_get_frame(uint64_t *frames, char **line)
{ {
char temp[128]; char temp[128];
int min, sec, fr; int min, sec, fr;
int success; int success;
success = cdi_cue_get_buffer(temp, line, 0); success = cdi_cue_get_buffer(temp, line, 0);
if (!success) if (!success)
@@ -720,12 +691,11 @@ cdi_cue_get_frame(uint64_t *frames, char **line)
return 1; return 1;
} }
static int static int
cdi_cue_get_flags(track_t *cur, char **line) cdi_cue_get_flags(track_t *cur, char **line)
{ {
char temp[128], temp2[128]; char temp[128], temp2[128];
int success; int success;
success = cdi_cue_get_buffer(temp, line, 0); success = cdi_cue_get_buffer(temp, line, 0);
if (!success) if (!success)
@@ -741,7 +711,6 @@ cdi_cue_get_flags(track_t *cur, char **line)
return 1; return 1;
} }
static int static int
cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap) cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, uint64_t *total_pregap, uint64_t cur_pregap)
{ {
@@ -784,11 +753,11 @@ cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, u
*total_pregap += cur_pregap; *total_pregap += cur_pregap;
cur->start += *total_pregap; cur->start += *total_pregap;
} else { } else {
temp = prev->file->get_length(prev->file) - ((uint64_t) prev->skip); temp = prev->file->get_length(prev->file) - ((uint64_t) prev->skip);
prev->length = temp / ((uint64_t) prev->sector_size); prev->length = temp / ((uint64_t) prev->sector_size);
if ((temp % prev->sector_size) != 0) if ((temp % prev->sector_size) != 0)
prev->length++; prev->length++;
/* Padding. */ /* Padding. */
cur->start += prev->start + prev->length + cur_pregap; cur->start += prev->start + prev->length + cur_pregap;
cur->skip = skip * cur->sector_size; cur->skip = skip * cur->sector_size;
@@ -809,24 +778,23 @@ cdi_add_track(cd_img_t *cdi, track_t *cur, uint64_t *shift, uint64_t prestart, u
return 1; return 1;
} }
int int
cdi_load_cue(cd_img_t *cdi, const char *cuefile) cdi_load_cue(cd_img_t *cdi, const char *cuefile)
{ {
track_t trk; track_t trk;
char pathname[MAX_FILENAME_LENGTH], filename[MAX_FILENAME_LENGTH]; char pathname[MAX_FILENAME_LENGTH], filename[MAX_FILENAME_LENGTH];
char temp[MAX_FILENAME_LENGTH]; char temp[MAX_FILENAME_LENGTH];
uint64_t shift = 0ULL, prestart = 0ULL; uint64_t shift = 0ULL, prestart = 0ULL;
uint64_t cur_pregap = 0ULL, total_pregap = 0ULL; uint64_t cur_pregap = 0ULL, total_pregap = 0ULL;
uint64_t frame = 0ULL, index; uint64_t frame = 0ULL, index;
int i, success; int i, success;
int error, can_add_track = 0; int error, can_add_track = 0;
FILE *fp; FILE *fp;
char buf[MAX_LINE_LENGTH], ansi[MAX_FILENAME_LENGTH]; char buf[MAX_LINE_LENGTH], ansi[MAX_FILENAME_LENGTH];
char *line, *command; char *line, *command;
char *type; char *type;
cdi->tracks = NULL; cdi->tracks = NULL;
cdi->tracks_num = 0; cdi->tracks_num = 0;
memset(&trk, 0, sizeof(track_t)); memset(&trk, 0, sizeof(track_t));
@@ -855,10 +823,10 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
if (strlen(buf) > 0) { if (strlen(buf) > 0) {
if (buf[strlen(buf) - 1] == '\n') if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0'; buf[strlen(buf) - 1] = '\0';
/* nuke trailing newline */ /* nuke trailing newline */
else if (buf[strlen(buf) - 1] == '\r') else if (buf[strlen(buf) - 1] == '\r')
buf[strlen(buf) - 1] = '\0'; buf[strlen(buf) - 1] = '\0';
/* nuke trailing newline */ /* nuke trailing newline */
} }
} }
@@ -872,86 +840,86 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
if (!success) if (!success)
break; break;
trk.start = 0; trk.start = 0;
trk.skip = 0; trk.skip = 0;
cur_pregap = 0; cur_pregap = 0;
prestart = 0; prestart = 0;
trk.number = cdi_cue_get_number(&line); trk.number = cdi_cue_get_number(&line);
trk.track_number = trk.number; trk.track_number = trk.number;
success = cdi_cue_get_keyword(&type, &line); success = cdi_cue_get_keyword(&type, &line);
if (!success) if (!success)
break; break;
trk.form = 0; trk.form = 0;
trk.mode2 = 0; trk.mode2 = 0;
trk.pre = 0; trk.pre = 0;
if (!strcmp(type, "AUDIO")) { if (!strcmp(type, "AUDIO")) {
trk.sector_size = RAW_SECTOR_SIZE; trk.sector_size = RAW_SECTOR_SIZE;
trk.attr = AUDIO_TRACK; trk.attr = AUDIO_TRACK;
} else if (!strcmp(type, "MODE1/2048")) { } else if (!strcmp(type, "MODE1/2048")) {
trk.sector_size = COOKED_SECTOR_SIZE; trk.sector_size = COOKED_SECTOR_SIZE;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
} else if (!strcmp(type, "MODE1/2352")) { } else if (!strcmp(type, "MODE1/2352")) {
trk.sector_size = RAW_SECTOR_SIZE; trk.sector_size = RAW_SECTOR_SIZE;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
} else if (!strcmp(type, "MODE1/2448")) { } else if (!strcmp(type, "MODE1/2448")) {
trk.sector_size = 2448; trk.sector_size = 2448;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
} else if (!strcmp(type, "MODE2/2048")) { } else if (!strcmp(type, "MODE2/2048")) {
trk.form = 1; trk.form = 1;
trk.sector_size = COOKED_SECTOR_SIZE; trk.sector_size = COOKED_SECTOR_SIZE;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
trk.mode2 = 1; trk.mode2 = 1;
} else if (!strcmp(type, "MODE2/2324")) { } else if (!strcmp(type, "MODE2/2324")) {
trk.form = 2; trk.form = 2;
trk.sector_size = 2324; trk.sector_size = 2324;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
trk.mode2 = 1; trk.mode2 = 1;
} else if (!strcmp(type, "MODE2/2328")) { } else if (!strcmp(type, "MODE2/2328")) {
trk.form = 2; trk.form = 2;
trk.sector_size = 2328; trk.sector_size = 2328;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
trk.mode2 = 1; trk.mode2 = 1;
} else if (!strcmp(type, "MODE2/2336")) { } else if (!strcmp(type, "MODE2/2336")) {
trk.sector_size = 2336; trk.sector_size = 2336;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
trk.mode2 = 1; trk.mode2 = 1;
} else if (!strcmp(type, "MODE2/2352")) { } else if (!strcmp(type, "MODE2/2352")) {
/* Assume this is XA Mode 2 Form 1. */ /* Assume this is XA Mode 2 Form 1. */
trk.form = 1; trk.form = 1;
trk.sector_size = RAW_SECTOR_SIZE; trk.sector_size = RAW_SECTOR_SIZE;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
trk.mode2 = 1; trk.mode2 = 1;
} else if (!strcmp(type, "MODE2/2448")) { } else if (!strcmp(type, "MODE2/2448")) {
/* Assume this is XA Mode 2 Form 1. */ /* Assume this is XA Mode 2 Form 1. */
trk.form = 1; trk.form = 1;
trk.sector_size = 2448; trk.sector_size = 2448;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
trk.mode2 = 1; trk.mode2 = 1;
} else if (!strcmp(type, "CDG/2448")) { } else if (!strcmp(type, "CDG/2448")) {
trk.sector_size = 2448; trk.sector_size = 2448;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
trk.mode2 = 1; trk.mode2 = 1;
} else if (!strcmp(type, "CDI/2336")) { } else if (!strcmp(type, "CDI/2336")) {
trk.sector_size = 2336; trk.sector_size = 2336;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
trk.mode2 = 1; trk.mode2 = 1;
} else if (!strcmp(type, "CDI/2352")) { } else if (!strcmp(type, "CDI/2352")) {
trk.sector_size = RAW_SECTOR_SIZE; trk.sector_size = RAW_SECTOR_SIZE;
trk.attr = DATA_TRACK; trk.attr = DATA_TRACK;
trk.mode2 = 1; trk.mode2 = 1;
} else } else
success = 0; success = 0;
can_add_track = 1; can_add_track = 1;
} else if (!strcmp(command, "INDEX")) { } else if (!strcmp(command, "INDEX")) {
index = cdi_cue_get_number(&line); index = cdi_cue_get_number(&line);
success = cdi_cue_get_frame(&frame, &line); success = cdi_cue_get_frame(&frame, &line);
switch(index) { switch (index) {
case 0: case 0:
prestart = frame; prestart = frame;
break; break;
@@ -984,7 +952,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
break; break;
trk.file = NULL; trk.file = NULL;
error = 1; error = 1;
if (!strcmp(type, "BINARY")) { if (!strcmp(type, "BINARY")) {
memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(char)); memset(temp, 0, MAX_FILENAME_LENGTH * sizeof(char));
@@ -1006,9 +974,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
success = cdi_cue_get_frame(&cur_pregap, &line); success = cdi_cue_get_frame(&cur_pregap, &line);
else if (!strcmp(command, "FLAGS")) else if (!strcmp(command, "FLAGS"))
success = cdi_cue_get_flags(&trk, &line); success = cdi_cue_get_flags(&trk, &line);
else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "ISRC") || else if (!strcmp(command, "CATALOG") || !strcmp(command, "CDTEXTFILE") || !strcmp(command, "ISRC") || !strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") || !strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) {
!strcmp(command, "PERFORMER") || !strcmp(command, "POSTGAP") || !strcmp(command, "REM") ||
!strcmp(command, "SONGWRITER") || !strcmp(command, "TITLE") || !strcmp(command, "")) {
/* Ignored commands. */ /* Ignored commands. */
success = 1; success = 1;
} else { } else {
@@ -1016,7 +982,7 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", command); cdrom_image_backend_log("CUE: unsupported command '%s' in cue sheet!\n", command);
#endif #endif
success = 0; success = 0;
} }
if (!success) if (!success)
break; break;
@@ -1033,17 +999,16 @@ cdi_load_cue(cd_img_t *cdi, const char *cuefile)
/* Add lead out track. */ /* Add lead out track. */
trk.number++; trk.number++;
trk.track_number = 0xAA; trk.track_number = 0xAA;
trk.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */ trk.attr = 0x16; /* Was 0x00 but I believe 0x16 is appropriate. */
trk.start = 0; trk.start = 0;
trk.length = 0; trk.length = 0;
trk.file = NULL; trk.file = NULL;
if (!cdi_add_track(cdi, &trk, &shift, 0, &total_pregap, 0)) if (!cdi_add_track(cdi, &trk, &shift, 0, &total_pregap, 0))
return 0; return 0;
return 1; return 1;
} }
int int
cdi_has_data_track(cd_img_t *cdi) cdi_has_data_track(cd_img_t *cdi)
{ {
@@ -1061,7 +1026,6 @@ cdi_has_data_track(cd_img_t *cdi)
return 0; return 0;
} }
int int
cdi_has_audio_track(cd_img_t *cdi) cdi_has_audio_track(cd_img_t *cdi)
{ {

1112
src/cdrom/cdrom_image_viso.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -52,6 +52,7 @@ typedef struct {
char fn[260]; char fn[260];
FILE *file; FILE *file;
void *priv;
} track_file_t; } track_file_t;
typedef struct { typedef struct {
@@ -89,5 +90,11 @@ extern int cdi_load_cue(cd_img_t *cdi, const char *cuefile);
extern int cdi_has_data_track(cd_img_t *cdi); extern int cdi_has_data_track(cd_img_t *cdi);
extern int cdi_has_audio_track(cd_img_t *cdi); extern int cdi_has_audio_track(cd_img_t *cdi);
/* Virtual ISO functions. */
extern int viso_read(void *p, uint8_t *buffer, uint64_t seek, size_t count);
extern uint64_t viso_get_length(void *p);
extern void viso_close(void *p);
extern track_file_t *viso_init(const char *dirname, int *error);
#endif /*CDROM_IMAGE_BACKEND_H*/ #endif /*CDROM_IMAGE_BACKEND_H*/

View File

@@ -618,7 +618,7 @@ MINIVHDOBJ := cwalk.o libxml2_encoding.o minivhd_convert.o \
minivhd_struct_rw.o minivhd_util.o minivhd_struct_rw.o minivhd_util.o
CDROMOBJ := cdrom.o \ CDROMOBJ := cdrom.o \
cdrom_image_backend.o cdrom_image.o cdrom_image_backend.o cdrom_image_viso.o cdrom_image.o
ZIPOBJ := zip.o ZIPOBJ := zip.o