ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/cdrom.cpp
(Generate patch)

Comparing BasiliskII/src/cdrom.cpp (file contents):
Revision 1.11 by cebix, 2001-02-02T20:52:56Z vs.
Revision 1.20 by cebix, 2004-01-12T15:29:21Z

# Line 1 | Line 1
1   /*
2   *  cdrom.cpp - CD-ROM driver
3   *
4 < *  Basilisk II (C) 1997-2001 Christian Bauer
4 > *  Basilisk II (C) 1997-2004 Christian Bauer
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 28 | Line 28
28   *    Technote FL 36: "Apple Extensions to ISO 9660"
29   */
30  
31 + #include "sysdeps.h"
32 +
33   #include <string.h>
34 + #include <vector>
35 +
36 + #ifndef NO_STD_NAMESPACE
37 + using std::vector;
38 + #endif
39  
33 #include "sysdeps.h"
40   #include "cpu_emulation.h"
41   #include "main.h"
42   #include "macos_util.h"
# Line 97 | Line 103 | static const uint8 bin2bcd[256] = {
103   };
104  
105   static const uint8 bcd2bin[256] = {
106 <        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
106 >         0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
107          10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
108          20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
109          30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
# Line 117 | Line 123 | static const uint8 bcd2bin[256] = {
123  
124  
125   // Struct for each drive
126 < struct DriveInfo {
127 <        DriveInfo()
128 <        {
129 <                next = NULL;
130 <                num = 0;
125 <                fh = NULL;
126 <                start_byte = 0;
127 <                status = 0;
128 <        }
126 > struct cdrom_drive_info {
127 >        cdrom_drive_info() : num(0), fh(NULL), start_byte(0), status(0) {}
128 >        cdrom_drive_info(void *fh_) : num(0), fh(fh_), start_byte(0), status(0) {}
129 >
130 >        void close_fh(void) { SysAllowRemoval(fh); Sys_close(fh); }
131  
130        DriveInfo *next;        // Pointer to next DriveInfo (must be first in struct!)
132          int num;                        // Drive number
133          void *fh;                       // File handle
134          int block_size;         // CD-ROM block size
135          int twok_offset;        // Offset of beginning of 2K block to last Prime position
136 <        uint32 start_byte;      // Start of HFS partition on disk
136 >        loff_t start_byte;      // Start of HFS partition on disk
137          bool to_be_mounted;     // Flag: drive must be mounted in accRun
138          bool mount_non_hfs;     // Flag: Issue disk-inserted events for non-HFS disks
139  
# Line 145 | Line 146 | struct DriveInfo {
146          uint32 status;          // Mac address of drive status record
147   };
148  
149 < // Linked list of DriveInfos
150 < static DriveInfo *first_drive_info;
149 > // List of drives handled by this driver
150 > typedef vector<cdrom_drive_info> drive_vec;
151 > static drive_vec drives;
152  
153   // Icon address (Mac address space, set by PatchROM())
154   uint32 CDROMIconAddr;
# Line 156 | Line 158 | static bool acc_run_called = false;
158  
159  
160   /*
161 < *  Get pointer to drive info, NULL = invalid drive number
161 > *  Get pointer to drive info or drives.end() if not found
162   */
163  
164 < static DriveInfo *get_drive_info(int num)
164 > static drive_vec::iterator get_drive_info(int num)
165   {
166 <        DriveInfo *info = first_drive_info;
167 <        while (info != NULL) {
166 >        drive_vec::iterator info, end = drives.end();
167 >        for (info = drives.begin(); info != end; ++info) {
168                  if (info->num == num)
169                          return info;
168                info = info->next;
170          }
171 <        return NULL;
171 >        return info;
172   }
173  
174  
# Line 175 | Line 176 | static DriveInfo *get_drive_info(int num
176   *  Find HFS partition, set info->start_byte (0 = no HFS partition)
177   */
178  
179 < static void find_hfs_partition(DriveInfo *info)
179 > static void find_hfs_partition(cdrom_drive_info &info)
180   {
181 <        info->start_byte = 0;
181 >        info.start_byte = 0;
182          uint8 *map = new uint8[512];
183 +        D(bug("Looking for HFS partitions on CD-ROM...\n"));
184  
185          // Search first 64 blocks for HFS partition
186          for (int i=0; i<64; i++) {
187 <                if (Sys_read(info->fh, map, i * 512, 512) != 512)
187 >                if (Sys_read(info.fh, map, i * 512, 512) != 512)
188                          break;
189 +                D(bug(" block %d, signature '%c%c' (%02x%02x)\n", i, map[0], map[1], map[0], map[1]));
190  
191                  // Not a partition map block? Then look at next block
192                  uint16 sig = (map[0] << 8) | map[1];
# Line 192 | Line 195 | static void find_hfs_partition(DriveInfo
195  
196                  // Partition map block found, Apple HFS partition?
197                  if (strcmp((char *)(map + 48), "Apple_HFS") == 0) {
198 <                        info->start_byte = ntohl(((uint32 *)map)[2]) << 9;
199 <                        D(bug(" HFS partition found at %d, %d blocks\n", info->start_byte, ntohl(((uint32 *)map)[3])));
198 >                        info.start_byte = (loff_t)((map[8] << 24) | (map[9] << 16) | (map[10] << 8) | map[11]) << 9;
199 >                        uint32 num_blocks = (map[12] << 24) | (map[13] << 16) | (map[14] << 8) | map[15];
200 >                        D(bug(" HFS partition found at %d, %d blocks\n", info.start_byte, num_blocks));
201                          break;
202                  }
203          }
# Line 205 | Line 209 | static void find_hfs_partition(DriveInfo
209   *  Read TOC of disk and set lead_out
210   */
211  
212 < static void read_toc(DriveInfo *info)
212 > static void read_toc(cdrom_drive_info &info)
213   {
214          // Read TOC
215 <        memset(&info->toc, 0, sizeof(info->toc));
216 <        SysCDReadTOC(info->fh, info->toc);
217 <        D(bug(" TOC: %08lx %08lx\n", ntohl(((uint32 *)info->toc)[0]), ntohl(((uint32 *)info->toc)[1])));
215 >        memset(info.toc, 0, sizeof(info.toc));
216 >        SysCDReadTOC(info.fh, info.toc);
217 >
218 > #if DEBUG
219 >        // Dump TOC for debugging
220 >        D(bug(" TOC:\n  %02x%02x%02x%02x        : %d bytes, first track = %d, last track = %d\n", info.toc[0], info.toc[1], info.toc[2], info.toc[3], (info.toc[0] << 8) | info.toc[1], info.toc[2], info.toc[3]));
221 >        for (int i=4; i<804; i+=8) {
222 >                D(bug("  %02x%02x%02x%02x%02x%02x%02x%02x: ", info.toc[i+0], info.toc[i+1], info.toc[i+2], info.toc[i+3], info.toc[i+4], info.toc[i+5], info.toc[i+6], info.toc[i+7]));
223 >                const char *type = (info.toc[i+2] == 0xaa ? "lead-out" : (info.toc[i+1] & 0x04 ? "data" : "audio"));
224 >                D(bug("track %d (%s), addr/ctrl 0x%02x, M %d S %d F %d\n", info.toc[i+2], type, info.toc[i+1], info.toc[i+5], info.toc[i+6], info.toc[i+7]));
225 >                if (info.toc[i+2] == 0xaa)
226 >                        break;
227 >        }
228 > #endif
229  
230          // Find lead-out track
231 <        info->lead_out[0] = 0;
232 <        info->lead_out[1] = 0;
233 <        info->lead_out[2] = 0;
231 >        info.lead_out[0] = 0;
232 >        info.lead_out[1] = 0;
233 >        info.lead_out[2] = 0;
234          for (int i=4; i<804; i+=8) {
235 <                if (info->toc[i+2] == 0xaa) {
236 <                        info->stop_at[0] = info->lead_out[0] = info->toc[i+5];
237 <                        info->stop_at[1] = info->lead_out[1] = info->toc[i+6];
238 <                        info->stop_at[2] = info->lead_out[2] = info->toc[i+7];
235 >                if (info.toc[i+2] == 0xaa) {
236 >                        info.stop_at[0] = info.lead_out[0] = info.toc[i+5];
237 >                        info.stop_at[1] = info.lead_out[1] = info.toc[i+6];
238 >                        info.stop_at[2] = info.lead_out[2] = info.toc[i+7];
239                          break;
240                  }
241          }
242 <        D(bug(" Lead-Out M %d S %d F %d\n", info->lead_out[0], info->lead_out[1], info->lead_out[2]));
242 >        D(bug(" Lead-Out M %d S %d F %d\n", info.lead_out[0], info.lead_out[1], info.lead_out[2]));
243   }
244  
245  
# Line 233 | Line 248 | static void read_toc(DriveInfo *info)
248   *  Return: false = error
249   */
250  
251 < static bool position2msf(DriveInfo *info, uint16 postype, uint32 pos, bool stopping, uint8 &m, uint8 &s, uint8 &f)
251 > static bool position2msf(const cdrom_drive_info &info, uint16 postype, uint32 pos, bool stopping, uint8 &m, uint8 &s, uint8 &f)
252   {
253          switch (postype) {
254                  case 0:
# Line 251 | Line 266 | static bool position2msf(DriveInfo *info
266                          if (stopping)
267                                  track++;
268                          for (int i=4; i<804; i+=8) {
269 <                                if (info->toc[i+2] == track || info->toc[i+2] == 0xaa) {
270 <                                        m = info->toc[i+5];
271 <                                        s = info->toc[i+6];
272 <                                        f = info->toc[i+7];
269 >                                if (info.toc[i+2] == track || info.toc[i+2] == 0xaa) {
270 >                                        m = info.toc[i+5];
271 >                                        s = info.toc[i+6];
272 >                                        f = info.toc[i+7];
273                                          return true;
274                                  }
275                          }
# Line 272 | Line 287 | static bool position2msf(DriveInfo *info
287  
288   void CDROMInit(void)
289   {
275        first_drive_info = NULL;
276
290          // No drives specified in prefs? Then add defaults
291          if (PrefsFindString("cdrom", 0) == NULL)
292                  SysAddCDROMPrefs();
293  
294          // Add drives specified in preferences
295 <        int32 index = 0;
295 >        int index = 0;
296          const char *str;
297          while ((str = PrefsFindString("cdrom", index++)) != NULL) {
298                  void *fh = Sys_open(str, true);
299 <                if (fh) {
300 <                        DriveInfo *info = new DriveInfo;
288 <                        info->fh = fh;
289 <                        DriveInfo *p = (DriveInfo *)&first_drive_info;
290 <                        while (p->next != NULL)
291 <                                p = p->next;
292 <                        p->next = info;
293 <                }
299 >                if (fh)
300 >                        drives.push_back(cdrom_drive_info(fh));
301          }
302   }
303  
# Line 301 | Line 308 | void CDROMInit(void)
308  
309   void CDROMExit(void)
310   {
311 <        DriveInfo *info = first_drive_info, *next;
312 <        while (info != NULL) {
313 <                SysAllowRemoval(info->fh);
314 <                Sys_close(info->fh);
308 <                next = info->next;
309 <                delete info;
310 <                info = next;
311 <        }
311 >        drive_vec::iterator info, end = drives.end();
312 >        for (info = drives.begin(); info != end; ++info)
313 >                info->close_fh();
314 >        drives.clear();
315   }
316  
317  
# Line 318 | Line 321 | void CDROMExit(void)
321  
322   bool CDROMMountVolume(void *fh)
323   {
324 <        DriveInfo *info;
325 <        for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
326 <        if (info) {
324 >        drive_vec::iterator info = drives.begin(), end = drives.end();
325 >        while (info != end && info->fh != fh)
326 >                ++info;
327 >        if (info != end) {
328                  if (SysIsDiskInserted(info->fh)) {
329                          SysPreventRemoval(info->fh);
330                          WriteMacInt8(info->status + dsDiskInPlace, 1);
331 <                        read_toc(info);
332 <                        find_hfs_partition(info);
331 >                        read_toc(*info);
332 >                        find_hfs_partition(*info);
333                          if (info->start_byte != 0 || info->mount_non_hfs)
334                                  info->to_be_mounted = true;
335                  }
# Line 342 | Line 346 | bool CDROMMountVolume(void *fh)
346  
347   static void mount_mountable_volumes(void)
348   {
349 <        DriveInfo *info = first_drive_info;
350 <        while (info != NULL) {
349 >        drive_vec::iterator info, end = drives.end();
350 >        for (info = drives.begin(); info != end; ++info) {
351  
352                  // Disk in drive?
353                  if (ReadMacInt8(info->status + dsDiskInPlace) == 0) {
# Line 362 | Line 366 | static void mount_mountable_volumes(void
366                          Execute68kTrap(0xa02f, &r);             // PostEvent()
367                          info->to_be_mounted = false;
368                  }
365
366                info = info->next;
369          }
370   }
371  
# Line 381 | Line 383 | int16 CDROMOpen(uint32 pb, uint32 dce)
383          acc_run_called = false;
384  
385          // Install drives
386 <        for (DriveInfo *info = first_drive_info; info; info = info->next) {
386 >        drive_vec::iterator info, end = drives.end();
387 >        for (info = drives.begin(); info != end; ++info) {
388  
389                  info->num = FindFreeDriveNumber(1);
390                  info->to_be_mounted = false;
# Line 411 | Line 414 | int16 CDROMOpen(uint32 pb, uint32 dce)
414                          if (SysIsDiskInserted(info->fh)) {
415                                  SysPreventRemoval(info->fh);
416                                  WriteMacInt8(info->status + dsDiskInPlace, 1);
417 <                                read_toc(info);
418 <                                find_hfs_partition(info);
417 >                                read_toc(*info);
418 >                                find_hfs_partition(*info);
419                                  info->to_be_mounted = true;
420                          }
421  
# Line 436 | Line 439 | int16 CDROMPrime(uint32 pb, uint32 dce)
439          WriteMacInt32(pb + ioActCount, 0);
440  
441          // Drive valid and disk inserted?
442 <        DriveInfo *info;
443 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
442 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
443 >        if (info == drives.end())
444                  return nsDrvErr;
445          if (ReadMacInt8(info->status + dsDiskInPlace) == 0)
446                  return offLinErr;
# Line 503 | Line 506 | int16 CDROMControl(uint32 pb, uint32 dce
506          }
507  
508          // Drive valid?
509 <        DriveInfo *info;
510 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
511 <                if (first_drive_info == NULL)
509 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
510 >        if (info == drives.end()) {
511 >                if (drives.empty())
512                          return nsDrvErr;
513                  else
514 <                        info = first_drive_info;        // This is needed for Apple's Audio CD program
514 >                        info = drives.begin();  // This is needed for Apple's Audio CD program
515 >        }
516  
517          // Drive-specific codes
518          switch (code) {
# Line 535 | Line 539 | int16 CDROMControl(uint32 pb, uint32 dce
539                          WriteMacInt32(pb + csParam, CDROMIconAddr);
540                          return noErr;
541  
542 <                case 23:                // DriveInfo
542 >                case 23:                // drive_info
543                          WriteMacInt32(pb + csParam, 0x00000b01);        // Unspecified external removable SCSI disk
544                          return noErr;
545  
# Line 675 | Line 679 | int16 CDROMControl(uint32 pb, uint32 dce
679                                  return offLinErr;
680  
681                          uint8 start_m, start_s, start_f;
682 <                        if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
682 >                        if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
683                                  return paramErr;
684                          info->play_mode = ReadMacInt8(pb + csParam + 9) & 0x0f;
685                          if (!SysCDPlay(info->fh, start_m, start_s, start_f, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
# Line 692 | Line 696 | int16 CDROMControl(uint32 pb, uint32 dce
696  
697                          if (ReadMacInt16(pb + csParam + 6)) {
698                                  // Given stopping address
699 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
699 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
700                                          return paramErr;
701                          } else {
702                                  // Given starting address
703                                  uint8 start_m, start_s, start_f;
704 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
704 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
705                                          return paramErr;
706                                  info->play_mode = ReadMacInt8(pb + csParam + 9) & 0x0f;
707                                  if (!SysCDPlay(info->fh, start_m, start_s, start_f, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
# Line 734 | Line 738 | int16 CDROMControl(uint32 pb, uint32 dce
738                                          return paramErr;
739                          } else {
740                                  // Given stopping address
741 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
741 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
742                                          return paramErr;
743                          }
744                          return noErr;
# Line 779 | Line 783 | int16 CDROMControl(uint32 pb, uint32 dce
783                                  return offLinErr;
784  
785                          uint8 start_m, start_s, start_f;
786 <                        if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
786 >                        if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
787                                  return paramErr;
788  
789                          if (!SysCDScan(info->fh, start_m, start_s, start_f, ReadMacInt16(pb + csParam + 6)))
# Line 857 | Line 861 | int16 CDROMControl(uint32 pb, uint32 dce
861  
862   int16 CDROMStatus(uint32 pb, uint32 dce)
863   {
864 <        DriveInfo *info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
864 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
865          uint16 code = ReadMacInt16(pb + csCode);
866          D(bug("CDROMStatus %d\n", code));
867  
868 <        // General codes
868 >        // General codes (we can get these even if the drive was invalid)
869          switch (code) {
870                  case 43: {      // DriverGestalt
871                          uint32 sel = ReadMacInt32(pb + csParam);
# Line 880 | Line 884 | int16 CDROMStatus(uint32 pb, uint32 dce)
884                                          WriteMacInt32(pb + csParam + 4, 0x01000000);
885                                          break;
886                                  case FOURCC('b','o','o','t'):   // Boot ID
887 <                                        if (info != NULL)
887 >                                        if (info != drives.end())
888                                                  WriteMacInt16(pb + csParam + 4, info->num);
889                                          else
890                                                  WriteMacInt16(pb + csParam + 4, 0);
# Line 909 | Line 913 | int16 CDROMStatus(uint32 pb, uint32 dce)
913          }
914  
915          // Drive valid?
916 <        if (info == NULL)
917 <                if (first_drive_info == NULL)
916 >        if (info == drives.end()) {
917 >                if (drives.empty())
918                          return nsDrvErr;
919                  else
920 <                        info = first_drive_info;        // This is needed for Apple's Audio CD program
920 >                        info = drives.begin();  // This is needed for Apple's Audio CD program
921 >        }
922  
923          // Drive-specific codes
924          switch (code) {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines