nkeynes@678: /** nkeynes@729: * $Id$ nkeynes@678: * nkeynes@678: * This file defines the structures and functions used by the GD-Rom nkeynes@678: * disc drivers. (ie, the modules that supply a CD image to be used by the nkeynes@678: * system). nkeynes@678: * nkeynes@678: * Copyright (c) 2005 Nathan Keynes. nkeynes@678: * nkeynes@678: * This program is free software; you can redistribute it and/or modify nkeynes@678: * it under the terms of the GNU General Public License as published by nkeynes@678: * the Free Software Foundation; either version 2 of the License, or nkeynes@678: * (at your option) any later version. nkeynes@678: * nkeynes@678: * This program is distributed in the hope that it will be useful, nkeynes@678: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@678: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@678: * GNU General Public License for more details. nkeynes@678: */ nkeynes@678: nkeynes@736: #ifndef lxdream_gddriver_H nkeynes@736: #define lxdream_gddriver_H 1 nkeynes@678: nkeynes@678: #include nkeynes@678: #include "lxdream.h" nkeynes@678: #include "gdrom/gdrom.h" nkeynes@678: #include nkeynes@678: nkeynes@736: #ifdef __cplusplus nkeynes@736: extern "C" { nkeynes@736: #endif nkeynes@736: nkeynes@678: #define MAX_SECTOR_SIZE 2352 nkeynes@678: nkeynes@720: #define CD_FRAMES_PER_SECOND 75 nkeynes@720: #define CD_SECONDS_PER_MINUTE 60 nkeynes@720: #define CD_FRAMES_PER_MINUTE (CD_FRAMES_PER_SECOND*CD_SECONDS_PER_MINUTE) nkeynes@709: nkeynes@678: struct gdrom_toc { nkeynes@678: uint32_t track[99]; nkeynes@678: uint32_t first, last, leadout; nkeynes@678: }; nkeynes@678: nkeynes@678: #define GDROM_PREGAP 150 /* Sectors */ nkeynes@678: nkeynes@678: extern uint32_t gdrom_sector_size[]; nkeynes@678: #define GDROM_SECTOR_SIZE(x) gdrom_sector_size[x] nkeynes@678: /** nkeynes@678: * Track data type enumeration for cd images and devices. This somewhat nkeynes@678: * conflates the real track mode with the format of the image file, but nkeynes@678: * it manages to make sense so far. nkeynes@678: */ nkeynes@678: typedef enum { nkeynes@678: GDROM_MODE0, // Mode 0 - should never actually see this nkeynes@736: /* Data-only modes (image file contains only the user data) */ nkeynes@678: GDROM_MODE1, // Standard CD-Rom Mode 1 data track nkeynes@678: GDROM_MODE2_FORMLESS, // Mode 2 data track with no sub-structure (rare) nkeynes@678: GDROM_MODE2_FORM1, // Mode 2/Form 1 data track (standard for multisession) nkeynes@678: GDROM_MODE2_FORM2, // Mode 2/Form 2 data track (also fairly uncommon). nkeynes@678: GDROM_CDDA, // Standard audio track nkeynes@678: nkeynes@736: /* This one is somewhat special - the image file contains the 2336 bytes of nkeynes@736: * "extended user data", which in turn contains either a form 1 or form 2 nkeynes@736: * sector. In other words it's a raw mode2 XA sector without the 16-byte header. nkeynes@736: */ nkeynes@678: GDROM_SEMIRAW_MODE2, nkeynes@736: /* Raw modes (image contains the full 2352-byte sector). Split into XA/Non-XA nkeynes@736: * here for convenience, although it's really a session level flag. */ nkeynes@678: GDROM_RAW_XA, nkeynes@678: GDROM_RAW_NONXA, nkeynes@678: } gdrom_track_mode_t; nkeynes@678: nkeynes@678: /* The disc register indicates the current contents of the drive. When open nkeynes@678: * contains 0x06. nkeynes@678: */ nkeynes@678: #define IDE_DISC_READY 0x01 /* ored with above */ nkeynes@678: #define IDE_DISC_IDLE 0x02 /* ie spun-down */ nkeynes@678: #define IDE_DISC_NONE 0x06 nkeynes@678: nkeynes@678: #define IDE_DISC_AUDIO 0x00 nkeynes@678: #define IDE_DISC_CDROM 0x10 nkeynes@678: #define IDE_DISC_CDROMXA 0x20 nkeynes@678: #define IDE_DISC_GDROM 0x80 nkeynes@678: nkeynes@678: #define TRACK_PRE_EMPHASIS 0x10 nkeynes@678: #define TRACK_COPY_PERMITTED 0x20 nkeynes@678: #define TRACK_DATA 0x40 nkeynes@678: #define TRACK_FOUR_CHANNEL 0x80 nkeynes@678: nkeynes@678: typedef struct gdrom_track { nkeynes@678: gdrom_track_mode_t mode; nkeynes@678: uint8_t flags; /* Track flags */ nkeynes@678: int session; /* session # containing this track */ nkeynes@678: uint32_t lba; /* start sector address */ nkeynes@678: uint32_t sector_size; /* For convenience, determined by mode */ nkeynes@678: uint32_t sector_count; nkeynes@678: uint32_t offset; /* File offset of start of track - image files only */ nkeynes@678: FILE *file; nkeynes@678: } *gdrom_track_t; nkeynes@678: nkeynes@678: struct gdrom_disc { nkeynes@678: /** nkeynes@678: * Read a single sector from the disc at the specified logical address. nkeynes@678: * @param disc pointer to the disc structure nkeynes@678: * @param lba logical address to read from nkeynes@678: * @param mode mode field from the read command nkeynes@678: * @param buf buffer to receive data (at least MAX_SECTOR_SIZE bytes) nkeynes@678: * @param length unsigned int to receive the number of bytes actually read. nkeynes@678: * @return PKT_ERR_OK on success, or another PKT_ERR_* code on failure. nkeynes@678: */ nkeynes@678: gdrom_error_t (*read_sector)( struct gdrom_disc *disc, nkeynes@736: uint32_t lba, int mode, nkeynes@736: unsigned char *buf, uint32_t *length ); nkeynes@736: nkeynes@678: /** nkeynes@678: * Read the TOC from the disc and write it into the specified buffer. nkeynes@678: * The method is responsible for returning the data in gd-rom nkeynes@678: * format. nkeynes@678: * @param disc pointer to the disc structure nkeynes@678: * @param buf buffer to receive data (0x198 bytes long) nkeynes@678: */ nkeynes@678: gdrom_error_t (*read_toc)(struct gdrom_disc *disc, unsigned char *buf); nkeynes@678: nkeynes@678: /** nkeynes@678: * Read the information for the specified sector and return it in the nkeynes@678: * supplied buffer. nkeynes@678: * @param disc pointer to the disc structure nkeynes@678: * @param session of interest. If 0, return end of disc information. nkeynes@678: * @param buf buffer to receive data (6 bytes) nkeynes@678: */ nkeynes@678: gdrom_error_t (*read_session)(struct gdrom_disc *disc, int session, unsigned char *buf); nkeynes@678: nkeynes@678: /** nkeynes@678: * Read the position information (subchannel) for the specified sector nkeynes@678: * and return it in the supplied buffer. This method does not need to nkeynes@678: * write the first 4 bytes of the buffer. nkeynes@678: * @param disc pointer to the disc structure nkeynes@678: * @param lba sector to get position information for nkeynes@678: * @param buf buffer to receive data (14 bytes) nkeynes@678: */ nkeynes@678: gdrom_error_t (*read_position)(struct gdrom_disc *disc, uint32_t lba, unsigned char *buf); nkeynes@678: nkeynes@678: /** nkeynes@678: * Return the current disc status, expressed as a combination of the nkeynes@678: * IDE_DISC_* flags above. nkeynes@678: * @param disc pointer to the disc structure nkeynes@678: * @return an integer status value. nkeynes@678: */ nkeynes@678: int (*drive_status)(struct gdrom_disc *disc); nkeynes@678: nkeynes@678: /** nkeynes@678: * Begin playing audio from the given lba address on the disc. nkeynes@678: */ nkeynes@678: gdrom_error_t (*play_audio)(struct gdrom_disc *disc, uint32_t lba, uint32_t endlba); nkeynes@678: nkeynes@678: /** nkeynes@678: * Executed once per time slice to perform house-keeping operations nkeynes@678: * (checking disc status, media changed, etc). nkeynes@678: */ nkeynes@678: uint32_t (*run_time_slice)( struct gdrom_disc *disc, uint32_t nanosecs ); nkeynes@678: nkeynes@678: /** nkeynes@678: * Close the disc and release any storage or resources allocated including nkeynes@678: * the disc structure itself. nkeynes@678: */ nkeynes@678: void (*close)( struct gdrom_disc *disc ); nkeynes@678: const gchar *name; /* Device name / Image filename */ nkeynes@837: char title[129]; /* Disc title (if any) */ nkeynes@678: }; nkeynes@678: nkeynes@678: typedef struct gdrom_image { nkeynes@678: struct gdrom_disc disc; nkeynes@678: int disc_type; nkeynes@678: int track_count; nkeynes@678: struct gdrom_track track[99]; nkeynes@678: gchar mcn[14]; /* Media catalogue number */ nkeynes@678: FILE *file; /* Open file stream */ nkeynes@720: void *private; /* image private data */ nkeynes@678: } *gdrom_image_t; nkeynes@678: nkeynes@678: /** nkeynes@678: * nkeynes@678: */ nkeynes@678: typedef struct gdrom_image_class { nkeynes@678: const gchar *name; nkeynes@678: const gchar *extension; nkeynes@678: gboolean (*is_valid_file)(FILE *f); nkeynes@678: gdrom_disc_t (*open_image_file)(const gchar *filename, FILE *f); nkeynes@678: } *gdrom_image_class_t; nkeynes@678: nkeynes@678: extern struct gdrom_image_class nrg_image_class; nkeynes@678: extern struct gdrom_image_class cdi_image_class; nkeynes@678: extern struct gdrom_image_class gdi_image_class; nkeynes@678: extern struct gdrom_image_class cdrom_device_class; nkeynes@678: nkeynes@678: /** nkeynes@678: * Construct a new image file using the default methods. nkeynes@678: */ nkeynes@678: gdrom_disc_t gdrom_image_new( const gchar *filename, FILE *f ); nkeynes@678: nkeynes@678: /** nkeynes@678: * Destroy an image data structure without closing the file nkeynes@678: * (Intended for use from image loaders only) nkeynes@678: */ nkeynes@678: void gdrom_image_destroy_no_close( gdrom_disc_t d ); nkeynes@678: nkeynes@782: /** nkeynes@782: * Determine the track number containing the specified sector by lba. nkeynes@782: */ nkeynes@782: int gdrom_image_get_track_by_lba( gdrom_image_t image, uint32_t lba ); nkeynes@678: nkeynes@678: /** nkeynes@678: * Given a base filename (eg for a .cue file), generate the path for the given nkeynes@678: * find_name relative to the original file. nkeynes@678: * @return a newly allocated string. nkeynes@678: */ nkeynes@678: gchar *gdrom_get_relative_filename( const gchar *base_name, const gchar *find_name ); nkeynes@678: nkeynes@709: gdrom_device_t gdrom_device_new( const gchar *name, const gchar *dev_name ); nkeynes@709: nkeynes@709: void gdrom_device_destroy( gdrom_device_t dev ); nkeynes@709: nkeynes@720: /************* Host-native support functions ***************/ nkeynes@720: nkeynes@720: /** nkeynes@782: * Given a raw (2352 byte) data sector, extract the requested components into the nkeynes@782: * target buffer. length will also be updated with the length of the copied nkeynes@782: * data nkeynes@782: */ nkeynes@782: void gdrom_extract_raw_data_sector( char *sector_data, int mode, unsigned char *buf, uint32_t *length ); nkeynes@782: nkeynes@782: /** nkeynes@720: * Parse a format 2 TOC, and write the results into the supplied disc structure. nkeynes@720: */ nkeynes@720: void mmc_parse_toc2( gdrom_image_t disc, unsigned char *buf ); nkeynes@720: nkeynes@720: /** nkeynes@720: * Construct a Read CD command for the given sector + mode nkeynes@720: */ nkeynes@720: void mmc_make_read_cd_cmd( char *cmd, uint32_t sector, int mode ); nkeynes@736: nkeynes@736: #endif /* !lxdream_gddriver_H */