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.10 by cebix, 2000-10-11T17:40:07Z vs.
Revision 1.18 by cebix, 2002-04-28T14:06:17Z

# Line 1 | Line 1
1   /*
2   *  cdrom.cpp - CD-ROM driver
3   *
4 < *  Basilisk II (C) 1997-2000 Christian Bauer
4 > *  Basilisk II (C) 1997-2002 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 >        D(bug(" TOC: %08lx %08lx\n", ntohl(((uint32 *)info.toc)[0]), ntohl(((uint32 *)info.toc)[1])));
218  
219          // Find lead-out track
220 <        info->lead_out[0] = 0;
221 <        info->lead_out[1] = 0;
222 <        info->lead_out[2] = 0;
220 >        info.lead_out[0] = 0;
221 >        info.lead_out[1] = 0;
222 >        info.lead_out[2] = 0;
223          for (int i=4; i<804; i+=8) {
224 <                if (info->toc[i+2] == 0xaa) {
225 <                        info->stop_at[0] = info->lead_out[0] = info->toc[i+5];
226 <                        info->stop_at[1] = info->lead_out[1] = info->toc[i+6];
227 <                        info->stop_at[2] = info->lead_out[2] = info->toc[i+7];
224 >                if (info.toc[i+2] == 0xaa) {
225 >                        info.stop_at[0] = info.lead_out[0] = info.toc[i+5];
226 >                        info.stop_at[1] = info.lead_out[1] = info.toc[i+6];
227 >                        info.stop_at[2] = info.lead_out[2] = info.toc[i+7];
228                          break;
229                  }
230          }
231 <        D(bug(" Lead-Out M %d S %d F %d\n", info->lead_out[0], info->lead_out[1], info->lead_out[2]));
231 >        D(bug(" Lead-Out M %d S %d F %d\n", info.lead_out[0], info.lead_out[1], info.lead_out[2]));
232   }
233  
234  
# Line 233 | Line 237 | static void read_toc(DriveInfo *info)
237   *  Return: false = error
238   */
239  
240 < static bool position2msf(DriveInfo *info, uint16 postype, uint32 pos, bool stopping, uint8 &m, uint8 &s, uint8 &f)
240 > static bool position2msf(const cdrom_drive_info &info, uint16 postype, uint32 pos, bool stopping, uint8 &m, uint8 &s, uint8 &f)
241   {
242          switch (postype) {
243                  case 0:
# Line 251 | Line 255 | static bool position2msf(DriveInfo *info
255                          if (stopping)
256                                  track++;
257                          for (int i=4; i<804; i+=8) {
258 <                                if (info->toc[i+2] == track || info->toc[i+2] == 0xaa) {
259 <                                        m = info->toc[i+5];
260 <                                        s = info->toc[i+6];
261 <                                        f = info->toc[i+7];
258 >                                if (info.toc[i+2] == track || info.toc[i+2] == 0xaa) {
259 >                                        m = info.toc[i+5];
260 >                                        s = info.toc[i+6];
261 >                                        f = info.toc[i+7];
262                                          return true;
263                                  }
264                          }
# Line 272 | Line 276 | static bool position2msf(DriveInfo *info
276  
277   void CDROMInit(void)
278   {
275        first_drive_info = NULL;
276
279          // No drives specified in prefs? Then add defaults
280          if (PrefsFindString("cdrom", 0) == NULL)
281                  SysAddCDROMPrefs();
282  
283          // Add drives specified in preferences
284 <        int32 index = 0;
284 >        int index = 0;
285          const char *str;
286          while ((str = PrefsFindString("cdrom", index++)) != NULL) {
287                  void *fh = Sys_open(str, true);
288 <                if (fh) {
289 <                        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 <                }
288 >                if (fh)
289 >                        drives.push_back(cdrom_drive_info(fh));
290          }
291   }
292  
# Line 301 | Line 297 | void CDROMInit(void)
297  
298   void CDROMExit(void)
299   {
300 <        DriveInfo *info = first_drive_info, *next;
301 <        while (info != NULL) {
302 <                SysAllowRemoval(info->fh);
303 <                Sys_close(info->fh);
308 <                next = info->next;
309 <                delete info;
310 <                info = next;
311 <        }
300 >        drive_vec::iterator info, end = drives.end();
301 >        for (info = drives.begin(); info != end; ++info)
302 >                info->close_fh();
303 >        drives.clear();
304   }
305  
306  
# Line 318 | Line 310 | void CDROMExit(void)
310  
311   bool CDROMMountVolume(void *fh)
312   {
313 <        DriveInfo *info;
314 <        for (info = first_drive_info; info != NULL && info->fh != fh; info = info->next) ;
315 <        if (info) {
313 >        drive_vec::iterator info = drives.begin(), end = drives.end();
314 >        while (info != end && info->fh != fh)
315 >                ++info;
316 >        if (info != end) {
317                  if (SysIsDiskInserted(info->fh)) {
318                          SysPreventRemoval(info->fh);
319                          WriteMacInt8(info->status + dsDiskInPlace, 1);
320 <                        read_toc(info);
321 <                        find_hfs_partition(info);
320 >                        read_toc(*info);
321 >                        find_hfs_partition(*info);
322                          if (info->start_byte != 0 || info->mount_non_hfs)
323                                  info->to_be_mounted = true;
324                  }
# Line 342 | Line 335 | bool CDROMMountVolume(void *fh)
335  
336   static void mount_mountable_volumes(void)
337   {
338 <        DriveInfo *info = first_drive_info;
339 <        while (info != NULL) {
338 >        drive_vec::iterator info, end = drives.end();
339 >        for (info = drives.begin(); info != end; ++info) {
340  
341                  // Disk in drive?
342                  if (ReadMacInt8(info->status + dsDiskInPlace) == 0) {
# Line 362 | Line 355 | static void mount_mountable_volumes(void
355                          Execute68kTrap(0xa02f, &r);             // PostEvent()
356                          info->to_be_mounted = false;
357                  }
365
366                info = info->next;
358          }
359   }
360  
# Line 381 | Line 372 | int16 CDROMOpen(uint32 pb, uint32 dce)
372          acc_run_called = false;
373  
374          // Install drives
375 <        for (DriveInfo *info = first_drive_info; info; info = info->next) {
375 >        drive_vec::iterator info, end = drives.end();
376 >        for (info = drives.begin(); info != end; ++info) {
377  
378                  info->num = FindFreeDriveNumber(1);
379                  info->to_be_mounted = false;
# Line 411 | Line 403 | int16 CDROMOpen(uint32 pb, uint32 dce)
403                          if (SysIsDiskInserted(info->fh)) {
404                                  SysPreventRemoval(info->fh);
405                                  WriteMacInt8(info->status + dsDiskInPlace, 1);
406 <                                read_toc(info);
407 <                                find_hfs_partition(info);
406 >                                read_toc(*info);
407 >                                find_hfs_partition(*info);
408                                  info->to_be_mounted = true;
409                          }
410  
# Line 436 | Line 428 | int16 CDROMPrime(uint32 pb, uint32 dce)
428          WriteMacInt32(pb + ioActCount, 0);
429  
430          // Drive valid and disk inserted?
431 <        DriveInfo *info;
432 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
431 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
432 >        if (info == drives.end())
433                  return nsDrvErr;
434          if (ReadMacInt8(info->status + dsDiskInPlace) == 0)
435                  return offLinErr;
# Line 503 | Line 495 | int16 CDROMControl(uint32 pb, uint32 dce
495          }
496  
497          // Drive valid?
498 <        DriveInfo *info;
499 <        if ((info = get_drive_info(ReadMacInt16(pb + ioVRefNum))) == NULL)
500 <                if (first_drive_info == NULL)
498 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
499 >        if (info == drives.end()) {
500 >                if (drives.empty())
501                          return nsDrvErr;
502                  else
503 <                        info = first_drive_info;        // This is needed for Apple's Audio CD program
503 >                        info = drives.begin();  // This is needed for Apple's Audio CD program
504 >        }
505  
506          // Drive-specific codes
507          switch (code) {
# Line 535 | Line 528 | int16 CDROMControl(uint32 pb, uint32 dce
528                          WriteMacInt32(pb + csParam, CDROMIconAddr);
529                          return noErr;
530  
531 <                case 23:                // DriveInfo
531 >                case 23:                // drive_info
532                          WriteMacInt32(pb + csParam, 0x00000b01);        // Unspecified external removable SCSI disk
533                          return noErr;
534  
# Line 675 | Line 668 | int16 CDROMControl(uint32 pb, uint32 dce
668                                  return offLinErr;
669  
670                          uint8 start_m, start_s, start_f;
671 <                        if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
671 >                        if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
672                                  return paramErr;
673                          info->play_mode = ReadMacInt8(pb + csParam + 9) & 0x0f;
674                          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 685 | int16 CDROMControl(uint32 pb, uint32 dce
685  
686                          if (ReadMacInt16(pb + csParam + 6)) {
687                                  // Given stopping address
688 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
688 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
689                                          return paramErr;
690                          } else {
691                                  // Given starting address
692                                  uint8 start_m, start_s, start_f;
693 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
693 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
694                                          return paramErr;
695                                  info->play_mode = ReadMacInt8(pb + csParam + 9) & 0x0f;
696                                  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 727 | int16 CDROMControl(uint32 pb, uint32 dce
727                                          return paramErr;
728                          } else {
729                                  // Given stopping address
730 <                                if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
730 >                                if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), true, info->stop_at[0], info->stop_at[1], info->stop_at[2]))
731                                          return paramErr;
732                          }
733                          return noErr;
# Line 779 | Line 772 | int16 CDROMControl(uint32 pb, uint32 dce
772                                  return offLinErr;
773  
774                          uint8 start_m, start_s, start_f;
775 <                        if (!position2msf(info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
775 >                        if (!position2msf(*info, ReadMacInt16(pb + csParam), ReadMacInt32(pb + csParam + 2), false, start_m, start_s, start_f))
776                                  return paramErr;
777  
778                          if (!SysCDScan(info->fh, start_m, start_s, start_f, ReadMacInt16(pb + csParam + 6)))
# Line 857 | Line 850 | int16 CDROMControl(uint32 pb, uint32 dce
850  
851   int16 CDROMStatus(uint32 pb, uint32 dce)
852   {
853 <        DriveInfo *info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
853 >        drive_vec::iterator info = get_drive_info(ReadMacInt16(pb + ioVRefNum));
854          uint16 code = ReadMacInt16(pb + csCode);
855          D(bug("CDROMStatus %d\n", code));
856  
857 <        // General codes
857 >        // General codes (we can get these even if the drive was invalid)
858          switch (code) {
859                  case 43: {      // DriverGestalt
860                          uint32 sel = ReadMacInt32(pb + csParam);
# Line 880 | Line 873 | int16 CDROMStatus(uint32 pb, uint32 dce)
873                                          WriteMacInt32(pb + csParam + 4, 0x01000000);
874                                          break;
875                                  case FOURCC('b','o','o','t'):   // Boot ID
876 <                                        if (info != NULL)
876 >                                        if (info != drives.end())
877                                                  WriteMacInt16(pb + csParam + 4, info->num);
878                                          else
879                                                  WriteMacInt16(pb + csParam + 4, 0);
# Line 909 | Line 902 | int16 CDROMStatus(uint32 pb, uint32 dce)
902          }
903  
904          // Drive valid?
905 <        if (info == NULL)
906 <                if (first_drive_info == NULL)
905 >        if (info == drives.end()) {
906 >                if (drives.empty())
907                          return nsDrvErr;
908                  else
909 <                        info = first_drive_info;        // This is needed for Apple's Audio CD program
909 >                        info = drives.begin();  // This is needed for Apple's Audio CD program
910 >        }
911  
912          // Drive-specific codes
913          switch (code) {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines