📄 nrg.c
字号:
CdioListNode *node; if (lsn >= env->size) { cdio_warn ("trying to read beyond image size (%lu >= %lu)", (long unsigned int) lsn, (long unsigned int) env->size); return -1; } _CDIO_LIST_FOREACH (node, env->mapping) { _mapping_t *_map = _cdio_list_node_data (node); if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->sec_count - 1))) { int ret; long int img_offset = _map->img_offset; img_offset += (lsn - _map->start_lsn) * CDIO_CD_FRAMESIZE_RAW; ret = cdio_stream_seek (env->gen.data_source, img_offset, SEEK_SET); if (ret!=0) return ret; ret = cdio_stream_read (env->gen.data_source, data, CDIO_CD_FRAMESIZE_RAW, nblocks); if (ret==0) return ret; break; } } if (!node) cdio_warn ("reading into pre gap (lsn %lu)", (long unsigned int) lsn); return 0;}static int_read_mode1_sector_nrg (void *user_data, void *data, lsn_t lsn, bool b_form2){ _img_private_t *env = user_data; char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; CdioListNode *node; if (lsn >= env->size) { cdio_warn ("trying to read beyond image size (%lu >= %lu)", (long unsigned int) lsn, (long unsigned int) env->size); return -1; } _CDIO_LIST_FOREACH (node, env->mapping) { _mapping_t *_map = _cdio_list_node_data (node); if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->sec_count - 1))) { int ret; long int img_offset = _map->img_offset; img_offset += (lsn - _map->start_lsn) * _map->blocksize; ret = cdio_stream_seek (env->gen.data_source, img_offset, SEEK_SET); if (ret!=0) return ret; /* FIXME: Not completely sure the below is correct. */ ret = cdio_stream_read (env->gen.data_source, (M2RAW_SECTOR_SIZE == _map->blocksize) ? (buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE) : buf, _map->blocksize, 1); if (ret==0) return ret; break; } } if (!node) cdio_warn ("reading into pre gap (lsn %lu)", (long unsigned int) lsn); memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE, b_form2 ? M2RAW_SECTOR_SIZE: CDIO_CD_FRAMESIZE); return 0;}/*! Reads nblocks of mode2 sectors from cd device into data starting from lsn. Returns 0 if no error. */static int_read_mode1_sectors_nrg (void *user_data, void *data, lsn_t lsn, bool b_form2, unsigned nblocks){ _img_private_t *env = user_data; int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { if ( (retval = _read_mode1_sector_nrg (env, ((char *)data) + (blocksize * i), lsn + i, b_form2)) ) return retval; } return 0;}static int_read_mode2_sector_nrg (void *user_data, void *data, lsn_t lsn, bool b_form2){ _img_private_t *env = user_data; char buf[CDIO_CD_FRAMESIZE_RAW] = { 0, }; CdioListNode *node; if (lsn >= env->size) { cdio_warn ("trying to read beyond image size (%lu >= %lu)", (long unsigned int) lsn, (long unsigned int) env->size); return -1; } _CDIO_LIST_FOREACH (node, env->mapping) { _mapping_t *_map = _cdio_list_node_data (node); if (IN (lsn, _map->start_lsn, (_map->start_lsn + _map->sec_count - 1))) { int ret; long int img_offset = _map->img_offset; img_offset += (lsn - _map->start_lsn) * _map->blocksize; ret = cdio_stream_seek (env->gen.data_source, img_offset, SEEK_SET); if (ret!=0) return ret; ret = cdio_stream_read (env->gen.data_source, (M2RAW_SECTOR_SIZE == _map->blocksize) ? (buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE) : buf, _map->blocksize, 1); if (ret==0) return ret; break; } } if (!node) cdio_warn ("reading into pre gap (lsn %lu)", (long unsigned int) lsn); if (b_form2) memcpy (data, buf + CDIO_CD_SYNC_SIZE + CDIO_CD_HEADER_SIZE, M2RAW_SECTOR_SIZE); else memcpy (data, buf + CDIO_CD_XA_SYNC_HEADER, CDIO_CD_FRAMESIZE); return 0;}/*! Reads nblocks of mode2 sectors from cd device into data starting from lsn. Returns 0 if no error. */static int_read_mode2_sectors_nrg (void *user_data, void *data, lsn_t lsn, bool b_form2, unsigned nblocks){ _img_private_t *env = user_data; int i; int retval; unsigned int blocksize = b_form2 ? M2RAW_SECTOR_SIZE : CDIO_CD_FRAMESIZE; for (i = 0; i < nblocks; i++) { if ( (retval = _read_mode2_sector_nrg (env, ((char *)data) + (blocksize * i), lsn + i, b_form2)) ) return retval; } return 0;}/* Free memory resources associated with NRG object.*/static void _free_nrg (void *user_data) { _img_private_t *env = user_data; if (NULL == env) return; if (NULL != env->mapping) _cdio_list_free (env->mapping, true); /* The remaining part of the image is like the other image drivers, so free that in the same way. */ _free_image(user_data);}/*! Eject media -- there's nothing to do here except free resources. We always return 2. */static int_eject_media_nrg(void *obj){ _free_nrg (obj); return 2;}/*! Return an array of strings giving possible NRG disk images. */char **cdio_get_devices_nrg (void){ char **drives = NULL; unsigned int num_files=0;#ifdef HAVE_GLOB_H unsigned int i; glob_t globbuf; globbuf.gl_offs = 0; glob("*.nrg", GLOB_DOOFFS, NULL, &globbuf); for (i=0; i<globbuf.gl_pathc; i++) { cdio_add_device_list(&drives, globbuf.gl_pathv[i], &num_files); } globfree(&globbuf);#else cdio_add_device_list(&drives, DEFAULT_CDIO_DEVICE, &num_files);#endif /*HAVE_GLOB_H*/ cdio_add_device_list(&drives, NULL, &num_files); return drives;}/*! Return a string containing the default CD device. */char *cdio_get_default_device_nrg(void){ char **drives = cdio_get_devices_nrg(); char *drive = (drives[0] == NULL) ? NULL : strdup(drives[0]); cdio_free_device_list(drives); return drive;}static boolget_hwinfo_nrg ( const CdIo *p_cdio, /*out*/ cdio_hwinfo_t *hw_info){ strcpy(hw_info->psz_vendor, "libcdio"); strcpy(hw_info->psz_model, "Nero"); strcpy(hw_info->psz_revision, CDIO_VERSION); return true; }/*! Return the number of tracks in the current medium. CDIO_INVALID_TRACK is returned on error.*/static track_format_tget_track_format_nrg(void *user_data, track_t track_num) { _img_private_t *env = user_data; if (track_num > env->gen.i_tracks || track_num == 0) return TRACK_FORMAT_ERROR; if ( env->dtyp != DTYP_INVALID) { switch (env->dtyp) { case DTYP_MODE2_XA: return TRACK_FORMAT_XA; case DTYP_MODE1: return TRACK_FORMAT_DATA; default: ; } } /*if ( MTYP_AUDIO_CD == env->mtyp) return TRACK_FORMAT_AUDIO; */ return env->tocent[track_num-1].track_format;}/*! Return true if we have XA data (green, mode2 form1) or XA data (green, mode2 form2). That is track begins: sync - header - subheader 12 4 - 8 FIXME: there's gotta be a better design for this and get_track_format?*/static bool_get_track_green_nrg(void *user_data, track_t track_num) { _img_private_t *env = user_data; if (track_num > env->gen.i_tracks || track_num == 0) return false; if ( MTYP_AUDIO_CD == env->mtyp) return false; return env->tocent[track_num-1].track_green;}/*! Check that a NRG file is valid. *//* Later we'll probably do better. For now though, this gets us started for now.*/boolcdio_is_nrg(const char *psz_nrg) { unsigned int i; if (psz_nrg == NULL) return false; i=strlen(psz_nrg)-strlen("nrg"); if (i>0) { if (psz_nrg[i]=='n' && psz_nrg[i+1]=='r' && psz_nrg[i+2]=='g') { return true; } else if (psz_nrg[i]=='N' && psz_nrg[i+1]=='R' && psz_nrg[i+2]=='G') { return true; } } return false;}/*! Initialization routine. This is the only thing that doesn't get called via a function pointer. In fact *we* are the ones to set that up. */CdIo *cdio_open_am_nrg (const char *psz_source_name, const char *psz_access_mode){ if (psz_access_mode != NULL && strcmp(psz_access_mode, "image")) cdio_warn ("there is only one access mode for nrg. Arg %s ignored", psz_access_mode); return cdio_open_nrg(psz_source_name);}CdIo *cdio_open_nrg (const char *psz_source){ CdIo *ret; _img_private_t *_data; cdio_funcs _funcs; memset( &_funcs, 0, sizeof(_funcs) ); _funcs.eject_media = _eject_media_nrg; _funcs.free = _free_nrg; _funcs.get_arg = _get_arg_image; _funcs.get_cdtext = get_cdtext_generic; _funcs.get_devices = cdio_get_devices_nrg; _funcs.get_default_device = cdio_get_default_device_nrg; _funcs.get_discmode = _get_discmode_image; _funcs.get_drive_cap = _get_drive_cap_image; _funcs.get_first_track_num= _get_first_track_num_image; _funcs.get_hwinfo = get_hwinfo_nrg; _funcs.get_mcn = _get_mcn_image; _funcs.get_num_tracks = _get_num_tracks_image; _funcs.get_track_format = get_track_format_nrg; _funcs.get_track_green = _get_track_green_nrg; _funcs.get_track_lba = NULL; /* Will use generic routine via msf */ _funcs.get_track_msf = _get_track_msf_image; _funcs.lseek = _lseek_nrg; _funcs.read = _read_nrg; _funcs.read_audio_sectors = _read_audio_sectors_nrg; _funcs.read_mode1_sector = _read_mode1_sector_nrg; _funcs.read_mode1_sectors = _read_mode1_sectors_nrg; _funcs.read_mode2_sector = _read_mode2_sector_nrg; _funcs.read_mode2_sectors = _read_mode2_sectors_nrg; _funcs.set_arg = _set_arg_image; _funcs.stat_size = _stat_size_nrg; _data = _cdio_malloc (sizeof (_img_private_t)); _data->gen.init = false; _data->gen.i_tracks = 0; _data->mtyp = 0; _data->dtyp = DTYP_INVALID; _data->gen.i_first_track= 1; _data->is_dao = false; _data->is_cues = false; /* FIXME: remove is_cues. */ ret = cdio_new ((void *)_data, &_funcs); if (ret == NULL) { free(_data); return NULL; } _set_arg_image(_data, "source", (NULL == psz_source) ? DEFAULT_CDIO_DEVICE: psz_source); _data->psz_cue_name = strdup(_get_arg_image(_data, "source")); if (!cdio_is_nrg(_data->psz_cue_name)) { cdio_debug ("source name %s is not recognized as a NRG image", _data->psz_cue_name); _free_nrg(_data); return NULL; } _set_arg_image (_data, "cue", _data->psz_cue_name); if (_init_nrg(_data)) return ret; else { _free_nrg(_data); free(ret); return NULL; }}boolcdio_have_nrg (void){ return true;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -